Exemple #1
0
        public static void WritePolygonFlipY(
            Vector3[] pts,
            List <Vector3> pos, List <Vector3> normals, List <uint> indices)
        {
            var flippedPts = new Vector3[pts.Length];

            for (int c = 0; c < pts.Length; ++c)
            {
                var p = pts[pts.Length - c - 1];
                flippedPts[c] = new Vector3(p.X, -p.Y, p.Z);
            }
            WritePolygon(flippedPts, pos, normals, indices);
        }
Exemple #2
0
        private bool IsEar(LinkedListNode <TriVx> node, Vec3F normal)
        {
            bool  isEar = true;
            TriVx v0    = PrevNode(node).Value;
            TriVx v1    = node.Value;
            TriVx v2    = NextNode(node).Value;

            foreach (TriVx v in node.List)
            {
                if (v.IsReflex && v != v0 && v != v1 && v != v2)
                {
                    // Chec for containment
                    if (IsLeftOf(v0, v1, v, normal) &&
                        IsLeftOf(v1, v2, v, normal) &&
                        IsLeftOf(v2, v0, v, normal))
                    {
                        isEar = false;
                    }
                }
            }
            return(isEar);
        }
Exemple #3
0
        public static void WritePolygon(
            Vector3[] pts,
            List <Vector3> pos, List <Vector3> normal, List <uint> indices)
        {
            // Calculate a normal for this face!
            ///////////////////////////////////////
            // We have good C++ code for fitting planes to faces.
            // But we don't have access to it from this code!

            var n = new Vector3(0.0f, 0.0f, 0.0f);

            for (uint c = 0; c < pts.Length - 2; ++c)
            {
                n += /*Vector3.Normalize*/ (Vector3.Cross(pts[c] - pts[c + 1], pts[c + 2] - pts[c + 1]));
            }

            // note that if we don't do the above normalize, then the contribution of
            // each triangle will be weighted by the length of the cross product (which is
            // proportional to the triangle area -- effectively weighting by triangle area).
            n = -Vector3.Normalize(n);

            var firstIndex = pos.Count;

            for (uint c = 0; c < pts.Length; ++c)
            {
                pos.Add(pts[c]);
                normal.Add(n);
            }

            for (uint c = 2; c < pts.Length; ++c)
            {
                indices.Add((uint)(firstIndex));
                indices.Add((uint)(firstIndex + c - 1));
                indices.Add((uint)(firstIndex + c));
            }
        }
Exemple #4
0
        private Vec3F[] CalcPointTangents()
        {
            int n = Count;

            Vec3F[] tangents = new Vec3F[n];

            for (int i = 1; i < n - 1; i++)
            {
                tangents[i] = CalcTangent(this[i - 1].Position, this[i].Position, this[i + 1].Position);
            }

            if (m_isClosed)
            {
                tangents[0]     = CalcTangent(this[n - 1].Position, this[0].Position, this[1].Position);
                tangents[n - 1] = CalcTangent(this[n - 2].Position, this[n - 1].Position, this[0].Position);
            }
            else
            {
                tangents[0]     = CalcEndTangents(this[0].Position, this[1].Position, tangents[1]);
                tangents[n - 1] = CalcEndTangents(this[n - 2].Position, this[n - 1].Position, tangents[n - 2]);
            }

            return(tangents);
        }
Exemple #5
0
        /// <summary>
        /// Creates Billboard matrix from the given parameters.</summary>
        public static void CreateBillboard(Matrix4F matrix, Vec3F objectPos, Vec3F camPos, Vec3F camUp, Vector3 camLook)
        {
            Vector3 look = objectPos - camPos;
            float   len  = look.LengthSquared;

            if (len < 0.0001f)
            {
                look = -camLook;
            }
            else
            {
                look.Normalize();
            }

            Vector3 right = Vec3F.Cross(camUp, look);

            right.Normalize();
            Vector3 up = Vec3F.Cross(look, right);

            matrix.M11 = right.X;
            matrix.M12 = right.Y;
            matrix.M13 = right.Z;
            matrix.M14 = 0f;
            matrix.M21 = up.X;
            matrix.M22 = up.Y;
            matrix.M23 = up.Z;
            matrix.M24 = 0f;
            matrix.M31 = look.X;
            matrix.M32 = look.Y;
            matrix.M33 = look.Z;
            matrix.M34 = 0f;
            matrix.M41 = objectPos.X;
            matrix.M42 = objectPos.Y;
            matrix.M43 = objectPos.Z;
            matrix.M44 = 1f;
        }
Exemple #6
0
Fichier : Box.cs Projet : zparr/ATF
 /// <summary>
 /// Constructor with min and max</summary>
 /// <param name="min">Minima of extents</param>
 /// <param name="max">Maxima of extents</param>
 public Box(Vec3F min, Vec3F max)
 {
     Min           = min;
     Max           = max;
     m_initialized = true;
 }
Exemple #7
0
 /// <summary>
 /// Sets sphere to given center and radius</summary>
 /// <param name="center">Center point</param>
 /// <param name="radius">Radius</param>
 public void Set(Vec3F center, float radius)
 {
     Center        = center;
     Radius        = radius;
     m_initialized = true;
 }
Exemple #8
0
 /// <summary>
 /// Cosntructor using center and radius</summary>
 /// <param name="center">Center point</param>
 /// <param name="radius">Radius</param>
 public Sphere3F(Vec3F center, float radius)
 {
     Center        = center;
     Radius        = radius;
     m_initialized = true;
 }
Exemple #9
0
 /// <summary>
 /// Creates Billboard matrix from the given parameters.</summary>        
 public static Matrix4F CreateBillboard(Vec3F objectPos, Vec3F camPos, Vec3F camUp, Vector3 camLook)
 {
     Matrix4F matrix = new Matrix4F();
     CreateBillboard(matrix, objectPos, camPos, camUp, camLook);
     return matrix;
 }
Exemple #10
0
        /// <summary>
        /// Create bi-polar sphere
        /// </summary>
        /// <param name="radius">radias of the sphere</param>
        /// <param name="slices">number of slices</param>
        /// <param name="stacks">number of stacks</param>
        /// <param name="pos">output positions</param>
        /// <param name="normal">output normals</param>
        /// <param name="tex">output texture coordinates</param>
        /// <param name="indices">output indices</param>
        public static void CreateSphere(float radius, uint slices, uint stacks,
                                        List <Vector3> pos, List <Vector3> normal, List <Vector2> tex, List <uint> indices)
        {
            if (radius <= 0)
            {
                throw new ArgumentOutOfRangeException("radius");
            }
            if (slices < 2 || stacks < 2)
            {
                throw new ArgumentException("invalid number slices or stacks");
            }

            // caches sin cos.
            float[] cosPhi  = new float[stacks];
            float[] sinPhi  = new float[stacks];
            float   phiStep = MathHelper.Pi / stacks;

            float[] cosTheta  = new float[slices];
            float[] sinTheta  = new float[slices];
            float   thetaStep = MathHelper.TwoPi / slices;

            float phi = 0;

            for (int s = 0; s < stacks; s++, phi += phiStep)
            {
                sinPhi[s] = (float)Math.Sin(phi);
                cosPhi[s] = (float)Math.Cos(phi);
            }

            float theta = 0;

            for (int s = 0; s < slices; s++, theta += thetaStep)
            {
                sinTheta[s] = (float)Math.Sin(theta);
                cosTheta[s] = (float)Math.Cos(theta);
            }

            uint numVerts = 2 + (stacks - 1) * slices;

            Vector3 northPole = new Vector3(0, radius, 0);

            pos.Add(northPole);                       // north pole.
            normal.Add(Vector3.Normalize(northPole)); // north pole.

            for (int s = 1; s < stacks; s++)
            {
                float y = radius * cosPhi[s];
                float r = radius * sinPhi[s];
                for (int l = 0; l < slices; l++)
                {
                    Vector3 p;
                    p.Y = y;
                    p.Z = r * cosTheta[l];
                    p.X = r * sinTheta[l];
                    pos.Add(p);
                    if (normal != null)
                    {
                        normal.Add(Vector3.Normalize(p));
                    }
                }
            }
            Vector3 southPole = new Vector3(0, -radius, 0);

            pos.Add(southPole);
            normal.Add(Vector3.Normalize(southPole));


            // 2l + (s-2) * 2l
            // 2l * ( 1 + s-2)
            // 2l * ( s- 1)
            //
            uint numTris = 2 * slices * (stacks - 1);


            // create index of north pole cap.
            for (uint l = 1; l < slices; l++)
            {
                indices.Add(l + 1);
                indices.Add(0);
                indices.Add(l);
            }
            indices.Add(1);
            indices.Add(0);
            indices.Add(slices);

            for (uint s = 0; s < (stacks - 2); s++)
            {
                uint l = 1;
                for (; l < slices; l++)
                {
                    indices.Add((s + 1) * slices + l + 1); // bottom right.
                    indices.Add(s * slices + l + 1);       // top right.
                    indices.Add(s * slices + l);           // top left.

                    indices.Add((s + 1) * slices + l);     // bottom left.
                    indices.Add((s + 1) * slices + l + 1); // bottom right.
                    indices.Add(s * slices + l);           // top left.
                }

                indices.Add((s + 1) * slices + 1); // bottom right.
                indices.Add(s * slices + 1);       // top right.
                indices.Add(s * slices + slices);  // top left.


                indices.Add((s + 1) * slices + slices); // bottom left.
                indices.Add((s + 1) * slices + 1);      // bottom right.
                indices.Add(s * slices + slices);       // top left.
            }

            // create index for south pole cap.
            uint baseIndex = slices * (stacks - 2);
            uint lastIndex = (uint)pos.Count - 1;

            for (uint l = 1; l < slices; l++)
            {
                indices.Add(baseIndex + l);
                indices.Add(lastIndex);
                indices.Add(baseIndex + l + 1);
            }
            indices.Add(baseIndex + slices);
            indices.Add(lastIndex);
            indices.Add(baseIndex + 1);
        }
Exemple #11
0
 /// <summary>
 /// Returns the signed distance along the ray from the ray's origin to the projection of 'p'
 /// onto this ray</summary>
 /// <param name="p">Point to be projected onto this ray</param>
 /// <returns>Signed distance along the ray, from the ray's origin to the projected point.
 /// A negative number means that 'p' falls "behind" the ray.</returns>
 public float GetDistanceToProjection(Vec3F p)
 {
     return(Vec3F.Dot(p - Origin, Direction));
 }
Exemple #12
0
 /// <summary>
 /// Constructor</summary>
 /// <param name="angles">Array of 3 floats to supply the Euler angles on
 /// the x, y, and z axes</param>
 /// <param name="order">Order that the rotations should be applied</param>
 public EulerAngles3F(float[] angles, EulerAngleOrder order)
 {
     m_Angles = new Vec3F(angles);
     m_Order  = order;
 }
Exemple #13
0
 private void UpdateEar(LinkedListNode <TriVx> node, List <LinkedListNode <TriVx> > ears, Vec3F normal)
 {
     if (IsEar(node, normal))
     {
         // If it's not already an ear add it to the ear list
         if (!node.Value.IsEar)
         {
             ears.Add(node);
             node.Value.IsEar = true;
         }
     }
     else
     {
         // Ok, it's not an ear - check if it is marked as one
         if (node.Value.IsEar)
         {
             ears.Remove(node);
             node.Value.IsEar = false;
         }
     }
 }
Exemple #14
0
        /// <summary>
        /// Finds the intersection point of the ray with the given convex polygon</summary>
        /// <param name="vertices">Polygon vertices</param>
        /// <param name="intersectionPoint">Intersection point</param>
        /// <returns>True iff the ray intersects the polygon</returns>
        public bool IntersectPolygon(Vec3F[] vertices, out Vec3F intersectionPoint)
        {
            Vec3F nearestVert, normal;

            return(IntersectPolygon(vertices, out intersectionPoint, out nearestVert, out normal, false));
        }
Exemple #15
0
        /// <summary>
        /// Moves this ray in a perpendicular direction from its current location so that 'point' will
        /// be on the infinite line that includes the new ray. This is almost like setting the origin
        /// to be 'point', except the current origin is moved in a strictly perpendicular direction.</summary>
        /// <param name="point">Point on infinite line that includes the new ray</param>
        public void MoveToIncludePoint(Vec3F point)
        {
            Vec3F x = ProjectPoint(point);

            Origin = Origin + (point - x);
        }
Exemple #16
0
 /// <summary>
 /// Constructs a 3D ray consisting of a point and a unit-vector direction</summary>
 /// <param name="origin">Ray origin</param>
 /// <param name="direction">Ray direction; must be a unit vector in order for
 /// IntersectPlane method to work</param>
 public Ray3F(Vec3F origin, Vec3F direction)
 {
     Origin    = origin;
     Direction = direction;
 }
Exemple #17
0
 /// <summary>
 /// Constructor</summary>
 /// <param name="angles">Euler angles on the x, y, and z axes</param>
 /// <param name="order">Order that the rotations should be applied</param>
 public EulerAngles3F(Vec3F angles, EulerAngleOrder order)
 {
     m_Angles = angles;
     m_Order  = order;
 }
Exemple #18
0
        private void BuildCurves()
        {
            m_curves.Clear();

            if (Count > 1)
            {
                if (Count == 2)
                {
                    BuildInitialCurveFrom2Points();
                }
                else
                {
                    Vec3F   zeroVec  = new Vec3F(0, 0, 0);
                    Vec3F[] tangents = CalcPointTangents();

                    for (int i = 1; i < Count; i++)
                    {
                        Vec3F chord  = this[i].Position - this[i - 1].Position;
                        float segLen = chord.Length * 0.333f;

                        Vec3F[] points = new Vec3F[4];
                        points[0] = this[i - 1].Position;
                        points[3] = this[i].Position;

                        // calc points[1]
                        if (this[i - 1].Tangent2 != zeroVec)
                        {
                            points[1] = this[i - 1].Position + this[i - 1].Tangent2;
                        }
                        else
                        {
                            Vec3F tangent = tangents[i - 1];
                            if (Vec3F.Dot(chord, tangent) < 0)
                            {
                                tangent = -tangent;
                            }

                            points[1] = this[i - 1].Position + (tangent * segLen);
                        }

                        // calc points[2]
                        if (this[i].Tangent1 != zeroVec)
                        {
                            points[2] = this[i].Position + this[i].Tangent1;
                        }
                        else
                        {
                            Vec3F tangent = tangents[i];
                            if (Vec3F.Dot(-chord, tangent) < 0)
                            {
                                tangent = -tangent;
                            }

                            points[2] = this[i].Position + (tangent * segLen);
                        }

                        BezierCurve curve = new BezierCurve(points);
                        m_curves.Add(curve);
                    }

                    // Calculate last curve if is closed
                    if (m_isClosed)
                    {
                        Vec3F[] points = new Vec3F[4];
                        points[0] = this[Count - 1].Position;
                        points[3] = this[0].Position;
                        float tanLen = (points[3] - points[0]).Length / 3.0f;

                        Vec3F v = m_curves[m_curves.Count - 1].ControlPoints[2] - points[0];
                        v         = v / v.Length;
                        points[1] = points[0] - (v * tanLen);

                        v         = m_curves[0].ControlPoints[1] - points[3];
                        v         = v / v.Length;
                        points[2] = points[3] - (v * tanLen);

                        BezierCurve curve = new BezierCurve(points);
                        m_curves.Add(curve);
                    }
                }
            }
        }
Exemple #19
0
        private bool IsLeftOf(TriVx v0, TriVx v1, TriVx v2, Vec3F normal)
        {
            Vec3F cross = Vec3F.Cross(v1.V - v0.V, v2.V - v0.V);

            return(Vec3F.Dot(cross, normal) > 0.0f);
        }
Exemple #20
0
        /// <summary>
        /// Finds the intersection point of the ray with the given convex polygon, if any. Returns the nearest
        /// vertex of the polygon to the intersection point. Can optionally backface cull the polygon.
        /// For backface culling, the front of the polygon is considered to be the side that has
        /// the vertices ordered counter-clockwise.</summary>
        /// <param name="vertices">Polygon vertices</param>
        /// <param name="intersectionPoint">Intersection point</param>
        /// <param name="nearestVert">Nearest polygon vertex to the point of intersection</param>
        /// <param name="normal">Normal unit-length vector, facing out from the side whose
        /// vertices are ordered counter-clockwise</param>
        /// <param name="backFaceCull">True if backface culling should be done</param>
        /// <returns>True iff the ray intersects the polygon</returns>
        public bool IntersectPolygon(Vec3F[] vertices, out Vec3F intersectionPoint,
                                     out Vec3F nearestVert, out Vec3F normal, bool backFaceCull)
        {
            bool intersects = true;
            int  sign       = 0;

            normal = new Vec3F();

            // First calc polygon normal
            for (int i = 2; i < vertices.Length; i++)
            {
                normal = Vec3F.Cross(vertices[i] - vertices[1], vertices[0] - vertices[1]);

                // Make sure that these 3 verts are not collinear
                float lengthSquared = normal.LengthSquared;
                if (lengthSquared != 0)
                {
                    normal *= (1.0f / (float)Math.Sqrt(lengthSquared));
                    break;
                }
            }

            if (backFaceCull)
            {
                if (Vec3F.Dot(normal, Direction) >= 0.0)
                {
                    intersectionPoint = new Vec3F();
                    nearestVert       = new Vec3F();
                    return(false);
                }
            }

            // Build plane and check if the ray intersects the plane.
            intersects = IntersectPlane(
                new Plane3F(normal, vertices[1]),
                out intersectionPoint);

            // Now check all vertices against intersection point
            for (int i = 0; i < vertices.Length && intersects; i++)
            {
                int i1 = i;
                int i0 = (i == 0 ? vertices.Length - 1 : i - 1);

                Vec3F cross = Vec3F.Cross(vertices[i1] - vertices[i0],
                                          intersectionPoint - vertices[i0]);

                // Check if edge and intersection vectors are collinear
                if (cross.LengthSquared == 0.0f)
                {
                    // check if point is on edge
                    intersects =
                        ((vertices[i1] - vertices[i0]).LengthSquared >=
                         (intersectionPoint - vertices[i0]).LengthSquared);

                    break;
                }
                else
                {
                    float dot = Vec3F.Dot(cross, normal);

                    if (i == 0)
                    {
                        sign = Math.Sign(dot);
                    }
                    else if (Math.Sign(dot) != sign)
                    {
                        intersects = false;
                    }
                }
            }

            // if we have a definite intersection, find the closest snap-to vertex.
            if (intersects)
            {
                nearestVert = vertices[0];
                float nearestDistSqr = (intersectionPoint - nearestVert).LengthSquared;
                for (int i = 1; i < vertices.Length; i++)
                {
                    float distSqr = (vertices[i] - intersectionPoint).LengthSquared;
                    if (distSqr < nearestDistSqr)
                    {
                        nearestDistSqr = distSqr;
                        nearestVert    = vertices[i];
                    }
                }
            }
            else
            {
                nearestVert = s_blankPoint;
            }

            return(intersects);
        }
Exemple #21
0
        public static void CreateCylinder(float rad1, float rad2, float height, uint slices, uint stacks,
                                          List <Vector3> pos, List <Vector3> normal, List <uint> indices)
        {
            float stackHeight = height / stacks;

            // Amount to increment radius as we move up each stack level from bottom to top.
            float radiusStep = (rad2 - rad1) / stacks;

            uint numRings = stacks + 1;

            // Compute vertices for each stack ring.
            for (uint i = 0; i < numRings; ++i)
            {
                float y = i * stackHeight;
                float r = rad1 + i * radiusStep;

                // Height and radius of next ring up.
                float y_next = (i + 1) * stackHeight;
                float r_next = rad1 + (i + 1) * radiusStep;

                // vertices of ring
                float dTheta = 2.0f * MathHelper.Pi / slices;
                for (uint j = 0; j <= slices; ++j)
                {
                    float c = (float)Math.Cos(j * dTheta);
                    float s = (float)Math.Sin(j * dTheta);

                    // tex coord if needed.
                    //float u = j/(float) slices;
                    //float v = 1.0f - (float) i/stacks;

                    // Partial derivative in theta direction to get tangent vector (this is a unit vector).
                    Vector3 T = new Vector3(-s, 0.0f, c);

                    // Compute tangent vector down the slope of the cone (if the top/bottom
                    // radii differ then we get a cone and not a true cylinder).
                    Vector3 P      = new Vector3(r * c, y, r * s);
                    Vector3 P_next = new Vector3(r_next * c, y_next, r_next * s);
                    Vector3 B      = P - P_next;
                    B.Normalize();


                    Vector3 N = Vector3.Cross(T, B);
                    N.Normalize();

                    P.Z *= -1;
                    N.Z *= -1;

                    pos.Add(P);
                    if (normal != null)
                    {
                        normal.Add(N);
                    }
                }
            }

            uint numRingVertices = slices + 1;

            // Compute indices for each stack.
            for (uint i = 0; i < stacks; ++i)
            {
                for (uint j = 0; j < slices; ++j)
                {
                    indices.Add(i * numRingVertices + j);
                    indices.Add((i + 1) * numRingVertices + j + 1);
                    indices.Add((i + 1) * numRingVertices + j);

                    indices.Add(i * numRingVertices + j);
                    indices.Add(i * numRingVertices + j + 1);
                    indices.Add((i + 1) * numRingVertices + j + 1);
                }
            }

            // build bottom cap.
            if (rad1 > 0)
            {
                uint baseIndex = (uint)pos.Count;


                // Duplicate cap vertices because the texture coordinates and normals differ.
                float y = 0;

                // vertices of ring
                float dTheta = 2.0f * MathHelper.Pi / slices;
                for (uint i = 0; i <= slices; ++i)
                {
                    float x = rad1 * (float)Math.Cos(i * dTheta);
                    float z = rad1 * (float)Math.Sin(i * dTheta);

                    // Map [-1,1]-->[0,1] for planar texture coordinates.
                    //float u = +0.5f * x / mBottomRadius + 0.5f;
                    //float v = -0.5f * z / mBottomRadius + 0.5f;
                    Vector3 p = new Vec3F(x, y, -z);
                    pos.Add(p);
                    if (normal != null)
                    {
                        normal.Add(new Vec3F(0.0f, -1.0f, 0.0f));
                    }
                }


                // cap center vertex
                pos.Add(new Vec3F(0.0f, y, 0.0f));
                if (normal != null)
                {
                    normal.Add(new Vec3F(0.0f, -1.0f, 0.0f));
                }
                // tex coord for center cap 0.5f, 0.5f


                // index of center vertex
                uint centerIndex = (uint)pos.Count - 1;

                for (uint i = 0; i < slices; ++i)
                {
                    indices.Add(centerIndex);
                    indices.Add(baseIndex + i + 1);
                    indices.Add(baseIndex + i);
                }
            }

            // build top cap.
            if (rad2 > 0)
            {
                uint baseIndex = (uint)pos.Count;

                // Duplicate cap vertices because the texture coordinates and normals differ.
                float y = height;

                // vertices of ring
                float dTheta = 2.0f * MathHelper.Pi / slices;
                for (uint i = 0; i <= slices; ++i)
                {
                    float x = rad2 * (float)Math.Cos(i * dTheta);
                    float z = rad2 * (float)Math.Sin(i * dTheta);

                    // Map [-1,1]-->[0,1] for planar texture coordinates.
                    //float u = +0.5f * x / mTopRadius + 0.5f;
                    //float v = -0.5f * z / mTopRadius + 0.5f;
                    pos.Add(new Vec3F(x, y, -z));
                    if (normal != null)
                    {
                        normal.Add(new Vec3F(0.0f, 1.0f, 0.0f));
                    }
                }

                // pos, norm, tex1 for cap center vertex
                pos.Add(new Vec3F(0.0f, y, 0.0f));
                if (normal != null)
                {
                    normal.Add(new Vec3F(0.0f, 1.0f, 0.0f));
                }
                // tex coord 0.5f, 0.5f


                // index of center vertex
                uint centerIndex = (uint)pos.Count - 1;
                for (uint i = 0; i < slices; ++i)
                {
                    indices.Add(centerIndex);
                    indices.Add(baseIndex + i);
                    indices.Add(baseIndex + i + 1);
                }
            }
        }
Exemple #22
0
 public TriVx(Vec3F v)
 {
     V = v;
 }
Exemple #23
0
 /// <summary>
 /// Constructor for a point in a bezier curve</summary>
 /// <param name="position">position of the point</param>
 /// <param name="incomingTangent">incoming tangent</param>
 /// <param name="outgoingTangent">outgoing tangent</param>
 public BezierPoint(Vec3F position, Vec3F incomingTangent, Vec3F outgoingTangent)
 {
     Position = position;
     Tangent1 = incomingTangent;
     Tangent2 = outgoingTangent;
 }
Exemple #24
0
        /// <summary>
        /// Triangulate the polygon</summary>
        /// <param name="normal">Polygon normal</param>
        /// <returns>List of triangles from the polygon</returns>
        public IList <Triangle3F> Triangulate(Vec3F normal)
        {
            List <Triangle3F> tris = new List <Triangle3F>();

            // Build TriVx array
            LinkedList <TriVx> polygon = new LinkedList <TriVx>();

            foreach (Vec3F v in Vertices)
            {
                polygon.AddLast(new TriVx(v));
            }

            if (polygon.Count < 3)
            {
                throw new InvalidOperationException("Polygon has less than 3 vertices");
            }

            List <LinkedListNode <TriVx> > ears = new List <LinkedListNode <TriVx> >();

            if (polygon.Count == 3)
            {
                // This is a triangle so just add any arbitrary vertex as an ear
                polygon.First.Value.IsEar = true;
                ears.Add(polygon.First);
            }
            else
            {
                LinkedListNode <TriVx> current = null;

                // Update reflex flag
                for (current = polygon.First; current != null; current = current.Next)
                {
                    current.Value.IsReflex = IsReflex(current, normal);
                }

                // Construct ears from all convex vertices
                for (current = polygon.First; current != null; current = current.Next)
                {
                    if (!current.Value.IsReflex && IsEar(current, normal))
                    {
                        current.Value.IsEar = true;
                        ears.Add(current);
                    }
                }
            }

            while (polygon.Count > 0 && ears.Count > 0)
            {
                LinkedListNode <TriVx> node = ears[0];
                LinkedListNode <TriVx> prev = PrevNode(node);
                LinkedListNode <TriVx> next = NextNode(node);

                tris.Add(new Triangle3F(prev.Value.V, node.Value.V, next.Value.V));

                if (polygon.Count == 3)
                {
                    polygon.Clear();
                }
                else
                {
                    ears.Remove(node);
                    polygon.Remove(node);

                    // Now test adjacent vertices
                    // If adjacent vertex is convex it remains convex, otherwise it needs testing
                    if (prev.Value.IsReflex)
                    {
                        prev.Value.IsReflex = IsReflex(prev, normal);
                    }

                    if (!prev.Value.IsReflex)
                    {
                        UpdateEar(prev, ears, normal);
                    }

                    // Do the same for next
                    if (next.Value.IsReflex)
                    {
                        next.Value.IsReflex = IsReflex(next, normal);
                    }

                    if (!next.Value.IsReflex)
                    {
                        UpdateEar(next, ears, normal);
                    }
                }
            }

            return(tris);
        }
Exemple #25
0
        /// <summary>
        /// Creates Billboard matrix from the given parameters.</summary>        
        public static void CreateBillboard(Matrix4F matrix, Vec3F objectPos, Vec3F camPos, Vec3F camUp, Vector3 camLook)
        {
            Vector3 look = camPos - objectPos;
            float len = look.LengthSquared;
            if (len < 0.0001f)
            {
                look = -camLook;
            }
            else
            {
                look.Normalize();
            }

            Vector3 right = Vec3F.Cross(camUp, look);
            right.Normalize();
            Vector3 up = Vec3F.Cross(look, right);

            matrix.M11 = right.X;
            matrix.M12 = right.Y;
            matrix.M13 = right.Z;
            matrix.M14 = 0f;
            matrix.M21 = up.X;
            matrix.M22 = up.Y;
            matrix.M23 = up.Z;
            matrix.M24 = 0f;
            matrix.M31 = look.X;
            matrix.M32 = look.Y;
            matrix.M33 = look.Z;
            matrix.M34 = 0f;
            matrix.M41 = objectPos.X;
            matrix.M42 = objectPos.Y;
            matrix.M43 = objectPos.Z;
            matrix.M44 = 1f;
        }
Exemple #26
0
        public static void CreateCylinder(float rad1, float rad2,float height, uint slices, uint stacks,
            List<Vector3> pos, List<Vector3> normal, List<uint> indices)
        {
            float stackHeight = height / stacks;

            // Amount to increment radius as we move up each stack level from bottom to top.
            float radiusStep = (rad2 - rad1) / stacks;

            uint numRings = stacks+1;

            // Compute vertices for each stack ring.
            for (uint i = 0; i < numRings; ++i)
            {
                float y = i*stackHeight;
                float r = rad1 + i*radiusStep;

                // Height and radius of next ring up.
                float y_next =  (i + 1)*stackHeight;
                float r_next = rad1 + (i + 1)*radiusStep;

                // vertices of ring
                float dTheta = 2.0f*MathHelper.Pi/slices;
                for (uint j = 0; j <= slices; ++j)
                {
                    float c = (float) Math.Cos(j*dTheta);
                    float s = (float) Math.Sin(j*dTheta);

                    // tex coord if needed.
                    //float u = j/(float) slices;
                    //float v = 1.0f - (float) i/stacks;

                    // Partial derivative in theta direction to get tangent vector (this is a unit vector).
                    Vector3 T = new Vector3(-s, 0.0f, c);

                    // Compute tangent vector down the slope of the cone (if the top/bottom
                    // radii differ then we get a cone and not a true cylinder).
                    Vector3 P = new Vector3(r*c, y, r*s);
                    Vector3 P_next = new Vector3(r_next*c, y_next, r_next*s);
                    Vector3 B = P - P_next;
                    B.Normalize();

                    Vector3 N = Vector3.Cross(T, B);
                    N.Normalize();

                    P.Z *= -1;
                    N.Z *= -1;

                    pos.Add(P);
                    if (normal != null)
                        normal.Add(N);
                }
            }

            uint numRingVertices = slices+1;

            // Compute indices for each stack.
            for(uint i = 0; i < stacks; ++i)
            {
                for (uint j = 0; j < slices; ++j)
                {
                    indices.Add(i*numRingVertices + j);
                    indices.Add((i + 1)*numRingVertices + j + 1);
                    indices.Add((i + 1) * numRingVertices + j);

                    indices.Add(i*numRingVertices + j);
                    indices.Add(i*numRingVertices + j + 1);
                    indices.Add((i + 1) * numRingVertices + j + 1);
                }
            }

            // build bottom cap.
            if(rad1 > 0)
            {
                uint baseIndex = (uint) pos.Count;

                // Duplicate cap vertices because the texture coordinates and normals differ.
                float y = 0;

                // vertices of ring
                float dTheta = 2.0f * MathHelper.Pi / slices;
                for (uint i = 0; i <= slices; ++i)
                {
                    float x = rad1 * (float)Math.Cos(i * dTheta);
                    float z = rad1 * (float)Math.Sin(i * dTheta);

                    // Map [-1,1]-->[0,1] for planar texture coordinates.
                    //float u = +0.5f * x / mBottomRadius + 0.5f;
                    //float v = -0.5f * z / mBottomRadius + 0.5f;
                    Vector3 p = new Vec3F(x,y,-z);
                    pos.Add(p);
                    if(normal != null)
                        normal.Add(new Vec3F(0.0f, -1.0f, 0.0f));
                }

                // cap center vertex
                pos.Add( new Vec3F(0.0f, y, 0.0f));
                if(normal != null)
                        normal.Add(new Vec3F(0.0f, -1.0f, 0.0f));
                // tex coord for center cap 0.5f, 0.5f

                // index of center vertex
                uint centerIndex = (uint)pos.Count - 1;

                for (uint i = 0; i < slices; ++i)
                {
                    indices.Add(centerIndex);
                    indices.Add(baseIndex + i + 1);
                    indices.Add(baseIndex + i);

                }
            }

            // build top cap.
            if(rad2 > 0)
            {
                uint baseIndex = (uint) pos.Count;

                // Duplicate cap vertices because the texture coordinates and normals differ.
                float y =  height;

                // vertices of ring
                float dTheta = 2.0f * MathHelper.Pi / slices;
                for (uint i = 0; i <= slices; ++i)
                {
                    float x = rad2 * (float)Math.Cos(i * dTheta);
                    float z = rad2 * (float)Math.Sin(i * dTheta);

                    // Map [-1,1]-->[0,1] for planar texture coordinates.
                    //float u = +0.5f * x / mTopRadius + 0.5f;
                    //float v = -0.5f * z / mTopRadius + 0.5f;
                    pos.Add(new Vec3F(x, y, -z));
                    if(normal != null)
                        normal.Add( new Vec3F(0.0f, 1.0f, 0.0f) );
                }

                // pos, norm, tex1 for cap center vertex
                pos.Add( new Vec3F(0.0f, y, 0.0f));
                if(normal != null)
                    normal.Add(new Vec3F(0.0f, 1.0f, 0.0f));
                // tex coord 0.5f, 0.5f

                // index of center vertex
                uint centerIndex = (uint)pos.Count - 1;
                for (uint i = 0; i < slices; ++i)
                {
                    indices.Add(centerIndex);
                    indices.Add(baseIndex + i);
                    indices.Add(baseIndex + i + 1);
                }

            }
        }
Exemple #27
0
 /// <summary>
 /// Tests if point is inside this sphere</summary>
 /// <param name="pt">Point</param>
 /// <returns>True iff pt is inside this sphere</returns>
 public bool Contains(Vec3F pt)
 {
     return((pt - Center).Length < Radius);
 }
Exemple #28
0
        /// <summary>
        /// Create bi-polar sphere
        /// </summary>
        /// <param name="radius">radias of the sphere</param>
        /// <param name="slices">number of slices</param>
        /// <param name="stacks">number of stacks</param>
        /// <param name="pos">output positions</param>
        /// <param name="normal">output normals</param>
        /// <param name="tex">output texture coordinates</param>
        /// <param name="indices">output indices</param>
        public static void CreateSphere(float radius, uint slices, uint stacks,
          List<Vector3> pos, List<Vector3> normal, List<Vector2> tex, List<uint> indices)
        {
            if (radius <= 0)
                throw new ArgumentOutOfRangeException("radius");
            if (slices < 2 || stacks < 2)
                throw new ArgumentException("invalid number slices or stacks");

            // caches sin cos.
            float[] cosPhi = new float[stacks];
            float[] sinPhi = new float[stacks];
            float phiStep = MathHelper.Pi / stacks;

            float[] cosTheta = new float[slices];
            float[] sinTheta = new float[slices];
            float thetaStep = MathHelper.TwoPi / slices;

            float phi = 0;
            for (int s = 0; s < stacks; s++, phi += phiStep)
            {
                sinPhi[s] = (float)Math.Sin(phi);
                cosPhi[s] = (float)Math.Cos(phi);
            }

            float theta = 0;
            for (int s = 0; s < slices; s++, theta += thetaStep)
            {
                sinTheta[s] = (float)Math.Sin(theta);
                cosTheta[s] = (float)Math.Cos(theta);
            }

            uint numVerts = 2 + (stacks - 1) * slices;

            Vector3 northPole = new Vector3(0, radius, 0);
            pos.Add(northPole); // north pole.
            normal.Add(Vector3.Normalize(northPole)); // north pole.

            for (int s = 1; s < stacks; s++)
            {
                float y = radius * cosPhi[s];
                float r = radius * sinPhi[s];
                for (int l = 0; l < slices; l++)
                {
                    Vector3 p;
                    p.Y = y;
                    p.Z = r * cosTheta[l];
                    p.X = r * sinTheta[l];
                    pos.Add(p);
                    if(normal != null)
                        normal.Add(Vector3.Normalize(p));
                }
            }
            Vector3 southPole = new Vector3(0, -radius, 0);
            pos.Add(southPole);
            normal.Add(Vector3.Normalize(southPole));

            // 2l + (s-2) * 2l
            // 2l * ( 1 + s-2)
            // 2l * ( s- 1)
            //
            uint numTris = 2 * slices * (stacks - 1);

            // create index of north pole cap.
            for (uint l = 1; l < slices; l++)
            {
                indices.Add(l + 1);
                indices.Add(0);
                indices.Add(l);
            }
            indices.Add(1);
            indices.Add(0);
            indices.Add(slices);

            for (uint s = 0; s < (stacks - 2); s++)
            {
                uint l = 1;
                for (; l < slices; l++)
                {
                    indices.Add( (s + 1) * slices + l + 1); // bottom right.
                    indices.Add( s * slices + l + 1); // top right.
                    indices.Add(s * slices + l); // top left.

                    indices.Add( (s + 1) * slices + l); // bottom left.
                    indices.Add( (s + 1) * slices + l + 1); // bottom right.
                    indices.Add( s * slices + l); // top left.

                }

                indices.Add( (s + 1) * slices + 1); // bottom right.
                indices.Add( s * slices + 1); // top right.
                indices.Add( s * slices + slices); // top left.

                indices.Add( (s + 1) * slices + slices); // bottom left.
                indices.Add( (s + 1) * slices + 1); // bottom right.
                indices.Add( s * slices + slices); // top left.

            }

            // create index for south pole cap.
            uint baseIndex = slices * (stacks - 2);
            uint lastIndex = (uint)pos.Count - 1;
            for (uint l = 1; l < slices; l++)
            {
                indices.Add( baseIndex + l);
                indices.Add( lastIndex);
                indices.Add( baseIndex + l + 1);
            }
            indices.Add(baseIndex + slices);
            indices.Add(lastIndex);
            indices.Add(baseIndex + 1);
        }
Exemple #29
0
 /// <summary>
 /// Constructs a sphere from another sphere</summary>
 /// <param name="sphere">Other sphere</param>
 public Sphere3F(Sphere3F sphere)
 {
     Center        = sphere.Center;
     Radius        = sphere.Radius;
     m_initialized = true;
 }
Exemple #30
0
        public static void WritePolygon(
            Vector3[] pts,
            List<Vector3> pos, List<Vector3> normal, List<uint> indices)
        {
            // Calculate a normal for this face!
                ///////////////////////////////////////
                // We have good C++ code for fitting planes to faces.
                // But we don't have access to it from this code!

            var n = new Vector3(0.0f, 0.0f, 0.0f);
            for (uint c=0; c<pts.Length - 2; ++c)
                n += /*Vector3.Normalize*/(Vector3.Cross(pts[c] - pts[c + 1], pts[c + 2] - pts[c + 1]));

                // note that if we don't do the above normalize, then the contribution of
                // each triangle will be weighted by the length of the cross product (which is
                // proportional to the triangle area -- effectively weighting by triangle area).
            n = -Vector3.Normalize(n);

            var firstIndex = pos.Count;
            for (uint c = 0; c < pts.Length; ++c)
            {
                pos.Add(pts[c]);
                normal.Add(n);
            }

            for (uint c = 2; c < pts.Length; ++c)
            {
                indices.Add((uint)(firstIndex));
                indices.Add((uint)(firstIndex + c-1));
                indices.Add((uint)(firstIndex + c));
            }
        }
Exemple #31
0
Fichier : Box.cs Projet : zparr/ATF
        /// <summary>
        /// Tests if specified ray intersects the box</summary>
        /// <param name="ray">The ray</param>
        /// <returns>True iff ray intersects box</returns>
        public bool Intersects(Ray3F ray)
        {
            // http://www.gametutorials.com/gtstore/pc-429-9-ray-and-aabb-collision.aspx
            // Compute the ray delta
            Vec3F rayDelta = ray.Direction * 100000f;

            // First we check to see if the origin of the ray is
            // inside the AABB.  If it is, the ray intersects the AABB so
            // we'll return true.  We start by assuming the ray origin is
            // inside the AABB
            bool inside = true;

            // This stores the distance from either the min or max (x,y,z) to the ray's
            // origin (x,y,z) respectively, divided by the length of the ray.  The largest
            // value has the delta time of a possible intersection.
            float xt, yt, zt;

            // Test the X component of the ray's origin to see if we are inside or not
            if (ray.Origin.X < Min.X)
            {
                xt = Min.X - ray.Origin.X;

                if (xt > rayDelta.X) // If the ray is moving away from the AABB, there is no intersection
                {
                    return(false);
                }

                xt    /= rayDelta.X;
                inside = false;
            }
            else if (ray.Origin.X > Max.X)
            {
                xt = Max.X - ray.Origin.X;

                if (xt < rayDelta.X) // If the ray is moving away from the AABB, there is no intersection
                {
                    return(false);
                }

                xt    /= rayDelta.X;
                inside = false;
            }
            else
            {
                // Later on we use the "xt", "yt", and "zt" variables to determine which plane (either
                // xy, xz, or yz) we may collide with.  Since the x component of the ray
                // origin is in between, the AABB's left and right side (which reside in the yz plane),
                // we know we don't have to test those sides so we set this to a negative value.
                xt = -1.0f;
            }

            // Test the X component of the ray's origin to see if we are inside or not
            if (ray.Origin.Y < Min.Y)
            {
                yt = Min.Y - ray.Origin.Y;

                if (yt > rayDelta.Y) // If the ray is moving away from the AABB, there is no intersection
                {
                    return(false);
                }

                yt    /= rayDelta.Y;
                inside = false;
            }
            else if (ray.Origin.Y > Max.Y)
            {
                yt = Max.Y - ray.Origin.Y;

                if (yt < rayDelta.Y) // If the ray is moving away from the AABB, there is no intersection
                {
                    return(false);
                }

                yt    /= rayDelta.Y;
                inside = false;
            }
            else
            {
                // Later on we use the "xt", "yt", and "zt" variables to determine which plane (either
                // xy, xz, or yz) we may collide with.  Since the y component of the ray
                // origin is in between, the AABB's top and bottom side (which reside in the xz plane),
                // we know we don't have to test those sides so we set this to a negative value.
                yt = -1.0f;
            }

            if (ray.Origin.Z < Min.Z)
            {
                zt = Min.Z - ray.Origin.Z;

                if (zt > rayDelta.Z) // If the ray is moving away from the AABB, there is no intersection
                {
                    return(false);
                }

                zt    /= rayDelta.Z;
                inside = false;
            }
            else if (ray.Origin.Z > Max.Z)
            {
                zt = Max.Z - ray.Origin.Z;

                if (zt < rayDelta.Z) // If the ray is moving away from the AABB, there is no intersection
                {
                    return(false);
                }

                zt    /= rayDelta.Z;
                inside = false;
            }
            else
            {
                // Later on we use the "xt", "yt", and "zt" variables to determine which plane (either
                // xy, xz, or yz) we may collide with.  Since the z component of the ray
                // origin is in between, the AABB's front and back side (which reside in the xy plane),
                // we know we don't have to test those sides so we set this to a negative value.
                zt = -1.0f;
            }

            // If the origin inside the AABB
            if (inside)
            {
                return(true); // The ray intersects the AABB
            }
            // Otherwise we have some checking to do...

            // We want to test the AABB planes with largest value out of xt, yt, and zt.  So
            // first we determine which value is the largest.

            float t = xt;

            if (yt > t)
            {
                t = yt;
            }

            if (zt > t)
            {
                t = zt;
            }

            // **NOTE** Normally comparing two floating point numbers won't necessarily work, however,
            //            since we set to explicitly to equal either xt, yt, or zt above, the equality test
            //            will pass

            if (t == xt) // If the ray intersects with the AABB's YZ plane
            {
                // Compute intersection values
                float y = ray.Origin.Y + rayDelta.Y * t;
                float z = ray.Origin.Z + rayDelta.Z * t;

                // Test to see if collision takes place within the bounds of the AABB
                if (y < Min.Y || y > Max.Y)
                {
                    return(false);
                }
                else if (z < Min.Z || z > Max.Z)
                {
                    return(false);
                }
            }
            else if (t == yt) // Intersects with the XZ plane
            {
                // Compute intersection values
                float x = ray.Origin.X + rayDelta.X * t;
                float z = ray.Origin.Z + rayDelta.Z * t;

                // Test to see if collision takes place within the bounds of the AABB
                if (x < Min.X || x > Max.X)
                {
                    return(false);
                }
                else if (z < Min.Z || z > Max.Z)
                {
                    return(false);
                }
            }
            else // Intersects with the XY plane
            {
                // Compute intersection values
                float x = ray.Origin.X + rayDelta.X * t;
                float y = ray.Origin.Y + rayDelta.Y * t;

                // Test to see if collision takes place within the bounds of the AABB
                if (x < Min.X || x > Max.X)
                {
                    return(false);
                }
                else if (y < Min.Y || y > Max.Y)
                {
                    return(false);
                }
            }

            // The ray intersects the AABB
            return(true);
        }
Exemple #32
0
 public static void WritePolygonFlipY(
     Vector3[] pts,
     List<Vector3> pos, List<Vector3> normals, List<uint> indices)
 {
     var flippedPts = new Vector3[pts.Length];
     for (int c = 0; c < pts.Length; ++c)
     {
         var p = pts[pts.Length - c - 1];
         flippedPts[c] = new Vector3(p.X, -p.Y, p.Z);
     }
     WritePolygon(flippedPts, pos, normals, indices);
 }
Exemple #33
0
 /// <summary>
 /// Construct triangle from 3 vertices</summary>
 /// <param name="v0">Vertex 0</param>
 /// <param name="v1">Vertex 1</param>
 /// <param name="v2">Vertex 2</param>
 public Triangle3F(Vec3F v0, Vec3F v1, Vec3F v2)
 {
     V0 = v0;
     V1 = v1;
     V2 = v2;
 }
Exemple #34
0
 private void CalcPlaneNormal(int planeIndex, Vec3F u1, Vec3F u2)
 {
     m_planes[planeIndex].Normal = Vec3F.Cross(u1, u2);
     m_planes[planeIndex].Normal.Normalize();
     m_planes[planeIndex].Distance = 0;
 }
Exemple #35
0
        /// <summary>
        /// Creates Billboard matrix from the given parameters.</summary>
        public static Matrix4F CreateBillboard(Vec3F objectPos, Vec3F camPos, Vec3F camUp, Vector3 camLook)
        {
            Matrix4F matrix = new Matrix4F();

            CreateBillboard(matrix, objectPos, camPos, camUp, camLook);
            return(matrix);
        }
Exemple #36
0
 /// <summary>
 /// Transforms by this matrix a vector that is perpendicular to some geometry or that is the component of a 3D plane.
 /// Points may be transformed using Transform(). Directional vectors like those in rays can be
 /// transformed by TransformVector(), and normals need to be tranformed by TransformNormal().</summary>
 /// <param name="n">The normal vector to some geometry</param>
 /// <param name="transposeOfInverse">The transpose of the inverse of this matrix, for performance reasons</param>
 /// <param name="result">The normal vector after being transformed by this matrix</param>
 public void TransformNormal(Vec3F n, Matrix4F transposeOfInverse, out Vec3F result)
 {
     transposeOfInverse.Transform(n, out result);
 }