Beispiel #1
0
        /// <summary>
        /// Extends sphere to enclose another sphere</summary>
        /// <param name="sphere">Sphere to enclose</param>
        /// <returns>Extended sphere</returns>
        public Sphere3F Extend(Sphere3F sphere)
        {
            if (!m_initialized)
            {
                Center        = sphere.Center;
                Radius        = sphere.Radius;
                m_initialized = true;
            }
            else if (!Contains(sphere))
            {
                if (Center == sphere.Center)
                {
                    Radius = sphere.Radius;
                }
                else
                {
                    Vec3F normal = Vec3F.Normalize(sphere.Center - Center);
                    Vec3F p1     = sphere.Center + (normal * sphere.Radius);
                    Vec3F p2     = Center - (normal * Radius);
                    Radius = (p2 - p1).Length / 2.0f;
                    Center = (p1 + p2) / 2.0f;
                }
            }

            return(this);
        }
Beispiel #2
0
        /// <summary>
        /// Returns the point on this ray resulting from projecting 'point' onto this ray.
        /// This is also the same as finding the closest point on this ray to 'point'.</summary>
        /// <param name="point">Point to project onto this ray</param>
        /// <returns>Closest point on this ray to 'point'</returns>
        public Vec3F ProjectPoint(Vec3F point)
        {
            Vec3F normalizedDir = Vec3F.Normalize(Direction);
            float distToX       = Vec3F.Dot(point - Origin, normalizedDir);
            Vec3F x             = Origin + distToX * normalizedDir;

            return(x);
        }
Beispiel #3
0
 /// <summary>
 /// Constructor</summary>
 /// <param name="angle">Angle of rotation</param>
 /// <param name="axis">Axis of rotation. The resulting axis has length of 1.</param>
 public AngleAxisF(float angle, Vec3F axis)
 {
     Angle  = angle;
     Axis.X = axis.X;
     Axis.Y = axis.Y;
     Axis.Z = axis.Z;
     Axis.Normalize();
 }
Beispiel #4
0
        /// <summary>
        /// Constructs a plane from 3 non-linear points on the plane, such that
        /// Normal * p = Distance</summary>
        /// <param name="p1">First point</param>
        /// <param name="p2">Second point</param>
        /// <param name="p3">Third point</param>
        public Plane3F(Vec3F p1, Vec3F p2, Vec3F p3)
        {
            Vec3F d12    = p2 - p1;
            Vec3F d13    = p3 - p1;
            Vec3F normal = Vec3F.Cross(d12, d13);

            Normal   = Vec3F.Normalize(normal);
            Distance = Vec3F.Dot(Normal, p1);
        }
Beispiel #5
0
        /// <summary>
        /// Transforms the given plane by this matrix</summary>
        /// <param name="p">Input plane</param>
        /// <param name="transposeOfInverse">Transpose of the inverse of this matrix, for performance reasons</param>
        /// <param name="result">Output plane</param>
        public void Transform(Plane3F p, Matrix4F transposeOfInverse, out Plane3F result)
        {
            Vec3F normal = p.Normal;
            Vec3F point  = p.PointOnPlane();

            TransformNormal(normal, transposeOfInverse, out normal);
            Transform(point, out point);
            normal.Normalize();
            result = new Plane3F(normal, point);
        }
Beispiel #6
0
        /// <summary>
        /// Transforms the given plane by this matrix</summary>
        /// <param name="p">Input plane</param>
        /// <param name="result">Output plane</param>
        public void Transform(Plane3F p, out Plane3F result)
        {
            Vec3F normal = p.Normal;
            Vec3F point  = p.PointOnPlane();

            TransformNormal(normal, out normal);
            Transform(point, out point);
            normal.Normalize();
            result = new Plane3F(normal, point);
        }
Beispiel #7
0
        /// <summary>
        /// Extends sphere to enclose point</summary>
        /// <param name="pt">Point to enclose</param>
        /// <returns>Extended sphere</returns>
        public Sphere3F Extend(Vec3F pt)
        {
            if (!m_initialized)
            {
                Center        = pt;
                Radius        = 0;
                m_initialized = true;
            }
            else if (!Contains(pt))
            {
                Vec3F normal = Vec3F.Normalize(pt - Center);
                Vec3F p      = Center - (normal * Radius);
                Radius = (pt - p).Length / 2.0f;
                Center = pt + p / 2.0f;
            }

            return(this);
        }
Beispiel #8
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;
        }
Beispiel #9
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));
            }
        }
Beispiel #10
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);
                }
            }
        }
Beispiel #11
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);
        }
Beispiel #12
0
 /// <summary>
 /// Transforms the ray by the given matrix. The Direction member will be normalized. There are
 /// no particular restrictions on M. Any transformation done to a point in world space or
 /// object space can be done on this ray, including any combination of rotations, translations,
 /// uniform scales, non-uniform scales, etc.</summary>
 /// <param name="M">Transformation matrix</param>
 public void Transform(Matrix4F M)
 {
     M.Transform(Origin, out Origin);
     M.TransformVector(Direction, out Direction);
     Direction.Normalize();
 }