/// <summary> /// Draw the coordinate system represented by a transformation matrix /// using arrows. The x vector is represented by a red arrow, and the y /// vector is represented by a green arrow. /// </summary> public void DrawCoordinateSystem2D( Matrix3 mat, ArrowParams ap = null ) { if ( ap == null ) ap = new ArrowParams(); ShaderPush(); ImmBegin( DrawMode.Triangles, 9 * 2 ); SetColor( Colors.Red ); DrawArrow( mat.Z.Xy, mat.Z.Xy + mat.X.Xy, ap ); SetColor( Colors.Green ); DrawArrow( mat.Z.Xy, mat.Z.Xy + mat.Y.Xy, ap ); ImmEnd(); ShaderPop(); }
/// <summary> /// Return the transform matrix of this node, expressed in its parent space. /// /// The node transform matrix is formed using the data accessed with the Position, Scale, Skew, /// Rotation/Angle/RotationNormalize, Pivot properties. The transform matrix is equivalent to: /// /// Matrix3.Translation( Position ) /// * Matrix3.Translation( Pivot ) /// * Matrix3.Rotation( Rotation ) /// * Matrix3.Scale( Scale ) /// * Matrix3.Skew( Skew ) /// * Matrix3.Translation( -Pivot ) /// /// Node that the transform matrix returned is a pure 2D transform. /// VertexZ is applied separately in the PushTransform function. /// </summary> public Matrix3 GetTransform() { if ( m_cached_local_transform_info_is_dirty ) { // Note that the Pivot is in LOCAL space // m_cached_local_transform = Matrix3.Translation( Position ) // * Matrix3.Translation( Pivot ) // * Matrix3.Rotation( Rotation ) // * Matrix3.Scale( Scale ) // * Matrix3.Skew( m_skew_tan ) // * Matrix3.Translation( -Pivot ) // ; // this should be the exact same as above Math.TranslationRotationScale( ref m_cached_local_transform, Position + Pivot, Rotation, Scale ); // m_cached_local_transform = m_cached_local_transform // * Matrix3.Skew( m_skew_tan ) // * Matrix3.Translation( -Pivot ); m_cached_local_transform = m_cached_local_transform // form the Matrix3.Skew( m_skew_tan ) * Matrix3.Translation( -Pivot ) matrix directly: * new Matrix3( new Vector3( 1.0f, m_skew_tan.X, 0.0f ) , new Vector3( m_skew_tan.Y, 1.0f, 0.0f ) , new Vector3( -Pivot * ( Math._11 + m_skew_tan.Yx ), 1.0f ) ); m_cached_local_transform_info_is_identity = false; // we don't know, so false m_cached_local_transform_info_is_orthonormal = ( Scale == Math._11 && Skew == GameEngine2D.Base.Math._00 ); m_cached_local_transform_info_is_dirty = false; } return m_cached_local_transform; }
/// <summary>Node constructor.</summary> public Node() { Position = GameEngine2D.Base.Math._00; Rotation = Math._10; Scale = Math._11; Skew = GameEngine2D.Base.Math._00; Pivot = GameEngine2D.Base.Math._00; VertexZ = 0.0f; m_order = 0; m_children = new List< Node >(); Visible = true; m_parent = null; m_cached_local_transform_info_is_identity = true; // note: matrix might be identity even if this is false m_cached_local_transform_info_is_orthonormal = true; m_cached_local_transform_info_is_dirty = false; m_cached_local_transform = Matrix3.Identity; m_is_running = false; m_scheduler_and_action_manager_pause_flag = 0; // we make the Scheduler and ActionManager pause flags // intrusive to Node, so that we don't need to hash (hope // it's the correct behavior) // Director.Instance.DebugLog( " Node construtor " + DebugInfo() ); }
/// <summary> /// Add a sprite to batch rendering of sprites, must be called between BeginSprites and EndSprites. /// </summary> /// <param name="quad">The sprite geometry.</param> /// <param name="uv">Sprite UVs are specified directly using a TRS object.</param> /// <param name="mat">A per sprite transform matrix.</param> public void AddSprite( ref TRS quad, ref TRS uv, ref Matrix3 mat ) { Vector2 quadX = quad.X; Vector2 quadY = quad.Y; Vector2 uvX = uv.X; Vector2 uvY = uv.Y; m_v0 = new Vector4( transform_point( ref mat, quad.T ), uv.T ); m_v1 = new Vector4( transform_point( ref mat, quad.T + quadX ), uv.T + uvX ); m_v2 = new Vector4( transform_point( ref mat, quad.T + quadY ), uv.T + uvY ); m_v3 = new Vector4( transform_point( ref mat, quad.T + quadX + quadY ), uv.T + uvX + uvY ); add_quad(); }
Vector2 transform_point( ref Matrix3 mat, Vector2 pos ) { return mat.X.Xy * pos.X + mat.Y.Xy * pos.Y + mat.Z.Xy; }
/// <summary> /// Add a sprite to batch rendering of sprites, must be called between BeginSprites and EndSprites. /// </summary> /// <param name="quad">The sprite geometry.</param> /// <param name="tile_index">Sprite UVs are specified by a tile index.</param> /// <param name="mat">A per sprite transform matrix.</param> public void AddSprite( ref TRS quad, Vector2i tile_index, ref Matrix3 mat ) { Vector2 posX = quad.X; Vector2 posY = quad.Y; TextureInfo.CachedTileData uvs = m_current_texture_info.GetCachedTiledData( ref tile_index ); m_v0 = new Vector4( transform_point( ref mat, quad.T ), uvs.UV_00 ); m_v1 = new Vector4( transform_point( ref mat, quad.T + posX ), uvs.UV_10 ); m_v2 = new Vector4( transform_point( ref mat, quad.T + posY ), uvs.UV_01 ); m_v3 = new Vector4( transform_point( ref mat, quad.T + posX + posY ), uvs.UV_11 ); add_quad(); }
/// <summary>The update function.</summary> public void Update( float dt ) { m_observed_velocity = ( Emit.TransformForVelocityEstimate.Z - m_tracking_transform_prev.Z ).Xy / dt; m_observed_angular_velocity = ( m_tracking_transform_prev.X.Xy.Normalize().Angle( Emit.TransformForVelocityEstimate.X.Xy.Normalize() ) ) / dt; m_tracking_transform_prev = Emit.TransformForVelocityEstimate; // System.Console.WriteLine( m_observed_velocity ); // System.Console.WriteLine( Emit.TransformForVelocityEstimate ); m_elapsed += (double)dt; float emit_wait_time = FMath.Max( 0.0f, Emit.WaitTime * ( 1.0f + Emit.WaitTimeRelVar * m_random.NextFloatMinus1_1() ) ); m_emit_timer += dt; while ( m_emit_timer > emit_wait_time && !IsFull ) { init_auto_particle( m_particles[ m_particles_count ] ); ++m_particles_count; m_emit_timer -= emit_wait_time; // generate a new wait time emit_wait_time = FMath.Max( 0.0f, Emit.WaitTime * ( 1.0f + Emit.WaitTimeRelVar * m_random.NextFloatMinus1_1() ) ); } Vector2 global_forces = Simulation.Gravity * Simulation.GravityDirection + Simulation.Wind * Simulation.WindDirection; for ( int i=0; i < m_particles_count; ) { if ( m_particles[i].Dead ) { // this will shuffle the draw order but reduces the number of copies Common.Swap( ref m_particles[i], ref m_particles[m_particles_count-1] ); --m_particles_count; } else { Vector2 forces = global_forces; if ( Simulation.BrownianScale != 0.0f ) forces += m_random.NextVector2Minus1_1() * Simulation.BrownianScale; update( m_particles[i], dt, forces ); ++i; } } // Dump(); }
/// <summary>Equality test.</summary> public bool Equals( ref Matrix3 m ) { return Equals( ref m, 1.0e-6f ); }
/// <summary>Equality test.</summary> public bool Equals( ref Matrix3 m, float epsilon ) { if ( ! X.Equals( m.X, epsilon ) ) return false; if ( ! Y.Equals( m.Y, epsilon ) ) return false; if ( ! Z.Equals( m.Z, epsilon ) ) return false; return true; }
/// <summary>Fast build of a Matrix3 TRS matrix.</summary> public static void TranslationRotationScale( ref Matrix3 ret, Vector2 translation, Vector2 rotation, Vector2 scale ) { ret.X = new Vector3( rotation.X * scale.X, rotation.Y * scale.X, 0.0f ); ret.Y = new Vector3( -rotation.Y * scale.Y, rotation.X * scale.Y, 0.0f ); ret.Z = translation.Xy1; }