Example #1
0
        public VertexBuffer GetVertexBuffer(IMeshPart meshPart)
        {
            var e = getEntry(meshPart);

            if (e.VertexBuffer == null)
            {
                var geomData  = meshPart.GetGeometryData();
                var positions = geomData.GetSourceVector3(MeshPartGeometryData.Semantic.Position);
                var normals   = geomData.GetSourceVector3(MeshPartGeometryData.Semantic.Normal);
                var texcoords = geomData.GetSourceVector2(MeshPartGeometryData.Semantic.Texcoord); // This might not work when no texcoords

                var vertices = new TangentVertex[positions.Length];
                for (int j = 0; j < vertices.Length; j++)
                {
                    vertices[j].pos    = positions[j];
                    vertices[j].normal = normals[j];
                    if (texcoords != null)
                    {
                        vertices[j].uv = texcoords[j];
                    }
                    //TODO: tangent
                }

                var vb = new VertexBuffer(game.GraphicsDevice, typeof(TangentVertex), vertices.Length, BufferUsage.None);
                vb.SetData(vertices);

                e.VertexBuffer = vb;
            }

            return(e.VertexBuffer);
        }
Example #2
0
        /// <summary>
        /// Creates a static mesh directly from vertices (triangles only)
        /// </summary>
        public static StaticMesh FromVertices(Vector3[] vertices)
        {
            TangentVertex[] verts = new TangentVertex[vertices.Length];
            for (int i = 0; i < verts.Length; i++)
            {
                verts[i] = new TangentVertex(
                    vertices[i], Vector2.Zero, new Vector3(0, 1, 0),
                    Vector3.Zero, Vector3.Zero);
            }

            return(FromVertices(verts));
        }
        public static void CreatePlaneIndicesVertices(out TangentVertex[] vertices, out short[] indices)
        {
            vertices    = new TangentVertex[4];
            vertices[0] = new TangentVertex(new Vector3(-0.5f, 0, -0.5f), new Vector2(0, 0), Vector3.Up, Vector3.Zero);
            vertices[1] = new TangentVertex(new Vector3(0.5f, 0, -0.5f), new Vector2(1, 0), Vector3.Up, Vector3.Zero);
            vertices[2] = new TangentVertex(new Vector3(-0.5f, 0, 0.5f), new Vector2(0, 1), Vector3.Up, Vector3.Zero);
            vertices[3] = new TangentVertex(new Vector3(0.5f, 0, 0.5f), new Vector2(1, 1), Vector3.Up, Vector3.Zero);

            indices    = new short[6];
            indices[0] = 0;
            indices[1] = 1;
            indices[2] = 2;
            indices[3] = 2;
            indices[4] = 1;
            indices[5] = 3;
        }
Example #4
0
        private void drawConePrimitives(int segments)
        {
            Vector3 forward      = Vector3.Forward;
            Vector3 targetPlaneX = Vector3.Right;
            Vector3 targetPlaneY = Vector3.Up;

            var vertices = new TangentVertex[segments + 1];

            vertices[0] = new TangentVertex(Vector3.Zero, Vector2.Zero, -forward, Vector3.Zero);
            for (int i = 1; i < vertices.Length; i++)
            {
                float iAngle = MathHelper.TwoPi * (i - 1) / segments;
                var   pos    = forward + (float)Math.Cos(iAngle) * targetPlaneX + (float)Math.Sin(iAngle) * targetPlaneY;
                var   normal = (float)-Math.Sin(iAngle) * targetPlaneX + (float)Math.Cos(iAngle) * targetPlaneY;
                vertices[i] = new TangentVertex(pos, Vector2.Zero, normal, Vector3.Zero);
            }

            int[] indices = new int[segments * 3 * 2];
            for (int i = 0; i < segments; i++)
            {
                indices[i * 3 + 0] = 0;
                indices[i * 3 + 1] = i + 1;
                indices[i * 3 + 2] = (i + 1) % segments + 1;

                indices[segments * 3 + i * 3 + 0] = 1;
                indices[segments * 3 + i * 3 + 1] = (i + 1) % segments + 1;
                indices[segments * 3 + i * 3 + 2] = i + 1;
            }


            GraphicsDevice.VertexDeclaration = tangentVertexDeclaration;


            GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, vertices, 0, vertices.Length, indices,
                                                     0, indices.Length / 3);
        }
Example #5
0
        /// <summary>
        /// Create track columns
        /// </summary>
        /// <param name="points">Points</param>
        /// <param name="landscape">Landscape for getting the ground height</param>
        public TrackColumns(List <TrackVertex> points, Landscape landscape)
        {
            if (landscape == null)
            {
                return;
            }

            #region Find out column positions
            float         lastColumnsDistance     = ColumnsDistance;
            List <Matrix> columnPointSpacesTop    = new List <Matrix>();
            List <Matrix> columnPointSpacesBottom = new List <Matrix>();
            for (int num = 0; num < points.Count; num++)
            {
                // Distance of the current position to the next position
                float distance = Vector3.Distance(
                    points[(num + 1) % points.Count].pos, points[num].pos);

                // Uniform calculation of the distance for the columns,
                // so it doesn't matter if there is a gap of 2 or 200 m
                // Have we reach or go over the ColumnsDistance?
                if (lastColumnsDistance - distance <= 0)
                {
                    // Catmull interpolation, instead the linear interpolation, for a
                    // better position calculation, especially in curves
                    Vector3 p1 = points[num - 1 < 0 ? points.Count - 1 : num - 1].pos;
                    Vector3 p2 = points[num].pos;
                    Vector3 p3 = points[(num + 1) % points.Count].pos;
                    Vector3 p4 = points[(num + 2) % points.Count].pos;

                    Vector3 holderPoint = Vector3.CatmullRom(p1, p2, p3, p4,
                                                             lastColumnsDistance / distance);

                    // Just find out how much this point is pointing up
                    float draft = Vector3.Dot(points[num].up, new Vector3(0, 0, 1));
                    // And don't add if height is too small!
                    float columnHeight = holderPoint.Z -
                                         landscape.GetMapHeight(holderPoint.X, holderPoint.Y);

                    // Store the position for this holder
                    if (draft > 0.3f &&                    //< 0 MaxColumnGenerationAngel &&
                        columnHeight > MinimumColumnHeight)
                    {
                        columnPositions.Add(holderPoint);

                        // The unit vectors for our local point space
                        Vector3 right = points[num].right;
                        Vector3 dir   = points[num].dir;
                        Vector3 up    = points[num].up;

                        // Create the coordinate system for the current point by the 3 unit
                        // vectors.
                        Matrix pointSpace = Matrix.Identity;
                        pointSpace.M11 = right.X;
                        pointSpace.M12 = right.Y;
                        pointSpace.M13 = right.Z;
                        pointSpace.M21 = dir.X;
                        pointSpace.M22 = dir.Y;
                        pointSpace.M23 = dir.Z;
                        pointSpace.M31 = up.X;
                        pointSpace.M32 = up.Y;
                        pointSpace.M33 = up.Z;

                        // Remember point space
                        columnPointSpacesTop.Add(pointSpace);

                        // Same for bottom, but don't use up vector (let it stay default)
                        pointSpace = Matrix.Identity;
                        Vector3 upVector = new Vector3(0, 0, 1);
                        // Rebuild right vector (to make it 90 degree to our up vector)
                        Vector3 rightVector = Vector3.Cross(dir, upVector);
                        pointSpace.M11 = rightVector.X;
                        pointSpace.M12 = rightVector.Y;
                        pointSpace.M13 = rightVector.Z;
                        pointSpace.M21 = dir.X;
                        pointSpace.M22 = dir.Y;
                        pointSpace.M23 = dir.Z;
                        columnPointSpacesBottom.Add(pointSpace);
                    }                     // if (draft)

                    // We have just set a pile, the next pile will be set after
                    // reaching the next holder gap.
                    lastColumnsDistance += ColumnsDistance;
                }                 // if (lastColumnsDistance)

                // The distance we have to cover until the next position.
                // We subtract our current distance from the remaining gap distance,
                // which will then be checked in the next loop.
                lastColumnsDistance -= distance;
            }             // for (num)
            #endregion

            #region Generate vertex buffer
            columnVertices = new TangentVertex[
                columnPositions.Count * BaseColumnVertices.Length * 2];

            // Go through all columns
            for (int num = 0; num < columnPositions.Count; num++)
            {
                Vector3 pos = columnPositions[num];

                // Find out the current landscape height here
                Vector3 bottomPos = new Vector3(pos.X, pos.Y,
                                                landscape.GetMapHeight(pos.X, pos.Y) +
                                                ColumnGroundHeight);
                Vector3 topPos = new Vector3(pos.X, pos.Y,
                                             pos.Z - TopColumnSubHeight);
                // Calculate top v tex coord for this column
                float topTexV =
                    Vector3.Distance(topPos, bottomPos) / (MathHelper.Pi * 2);

                // Use the BaseColumnVertices twice, once for the bottom and then for the
                // top part of our generated column.
                for (int topBottom = 0; topBottom < 2; topBottom++)
                {
                    // Go to all BaseColumnVertices
                    for (int i = 0; i < BaseColumnVertices.Length; i++)
                    {
                        int vertIndex = num * BaseColumnVertices.Length * 2 +
                                        topBottom * BaseColumnVertices.Length + i;

                        // For the top positions, modify them them to fit directly
                        // on the bottom side of our road. Same for bottom, but don't
                        // modify the z value
                        Matrix transformMatrix = topBottom == 0 ?
                                                 columnPointSpacesBottom[num] : columnPointSpacesTop[num];

                        // We don't have to transform the vertices much, just adjust
                        // the z value and the v tex coord.
                        columnVertices[vertIndex] =
                            new TangentVertex(
                                (topBottom == 0 ? bottomPos : topPos) +
                                Vector3.Transform(BaseColumnVertices[i].pos, transformMatrix),
                                BaseColumnVertices[i].U, topBottom == 0 ? 0 : topTexV,
                                Vector3.Transform(BaseColumnVertices[i].normal, transformMatrix),
                                Vector3.Transform(-BaseColumnVertices[i].tangent,
                                                  transformMatrix));
                    }     // for (int)
                }         // for (topBottom)
            }             // for (num)

            // Create the vertex buffer from our vertices.
            columnVb = new VertexBuffer(
                BaseGame.Device,
                typeof(TangentVertex),
                columnVertices.Length,
                ResourceUsage.WriteOnly,
                ResourceManagementMode.Automatic);
            columnVb.SetData(columnVertices);
            #endregion

            #region GenerateIndexBuffer
            // Count of quads (polygons) we have for each column
            int   quadPolysPerColumn = BaseColumnVertices.Length - 1;
            int[] indices            =
                new int[(2 * 3 * quadPolysPerColumn) * columnPositions.Count];
            // Current vertex index
            int vertexIndex = 0;
            // Helper variable, current index of the indices list
            int indicesIndex = 0;
            for (int num = 0; num < columnPositions.Count; num++)
            {
                // Set all quads of the column
                for (int j = 0; j < quadPolysPerColumn; j++)
                {
                    indicesIndex = 3 * 2 * (num * quadPolysPerColumn + j);

                    // 1. Polygon
                    indices[indicesIndex]     = vertexIndex + j;
                    indices[indicesIndex + 1] =
                        vertexIndex + 1 + BaseColumnVertices.Length + j;
                    indices[indicesIndex + 2] = vertexIndex + 1 + j;

                    // 2. Polygon
                    indices[indicesIndex + 3] = indices[indicesIndex + 1];
                    indices[indicesIndex + 4] = indices[indicesIndex];
                    indices[indicesIndex + 5] =
                        vertexIndex + BaseColumnVertices.Length + j;
                }                 // for (int)

                // Go to next column
                vertexIndex += BaseColumnVertices.Length * 2;
            }             // for (num)

            // Create the index buffer from our indices.
            columnIb = new IndexBuffer(
                BaseGame.Device,
                typeof(int),
                indices.Length,
                ResourceUsage.WriteOnly,
                ResourceManagementMode.Automatic);
            columnIb.SetData(indices);
            #endregion
        }         // TrackColumns(points)
Example #6
0
        /// <summary>
        /// Add brake track
        /// </summary>
        /// <param name="position">Position</param>
        /// <param name="dir">Dir vector</param>
        /// <param name="right">Right vector</param>
        public void AddBrakeTrack(CarPhysics car)
        {
            Vector3 position = car.CarPosition + car.CarDirection * 1.25f;

            // Just skip if we setting to a similar location again.
            // This check is much faster and accurate for tracks on top of each
            // other than the foreach loop below, which is only useful to
            // put multiple tracks correctly behind each other!
            if (Vector3.DistanceSquared(position, lastAddedTrackPos) < 0.024f ||
                // Limit number of tracks to keep rendering fast.
                brakeTracksVertices.Count > MaxBrakeTrackVertices)
            {
                return;
            }

            lastAddedTrackPos = position;

            const float width   = 2.4f; // car is 2.6m width, we use 2.4m for tires
            const float length  = 4.5f; // Length of break tracks
            float       maxDist =
                (float)Math.Sqrt(width * width + length * length) / 2 - 0.35f;

            // Check if there is any track already set here or nearby?
            for (int num = 0; num < brakeTracksVertices.Count; num++)
            {
                if (Vector3.DistanceSquared(brakeTracksVertices[num].pos, position) <
                    maxDist * maxDist)
                {
                    // Then skip this brake track, don't put that much stuff on
                    // top of each other.
                    return;
                }
            }

            // Move position a little bit up (above the road)
            position += Vector3.Normalize(car.CarUpVector) * RaiseBreakTracksAmount;

            // Just add 6 new vertices to render (2 triangles)
            TangentVertex[] newVertices = new TangentVertex[]
            {
                // First triangle
                new TangentVertex(
                    position - car.CarRight * width / 2 - car.CarDirection * length / 2, 0, 0,
                    car.CarUpVector, car.CarRight),
                new TangentVertex(
                    position - car.CarRight * width / 2 + car.CarDirection * length / 2, 0, 5,
                    car.CarUpVector, car.CarRight),
                new TangentVertex(
                    position + car.CarRight * width / 2 + car.CarDirection * length / 2, 1, 5,
                    car.CarUpVector, car.CarRight),
                // Second triangle
                new TangentVertex(
                    position - car.CarRight * width / 2 - car.CarDirection * length / 2, 0, 0,
                    car.CarUpVector, car.CarRight),
                new TangentVertex(
                    position + car.CarRight * width / 2 + car.CarDirection * length / 2, 1, 5,
                    car.CarUpVector, car.CarRight),
                new TangentVertex(
                    position + car.CarRight * width / 2 - car.CarDirection * length / 2, 1, 0,
                    car.CarUpVector, car.CarRight),
            };

            brakeTracksVertices.AddRange(newVertices);
            brakeTracksVerticesArray = brakeTracksVertices.ToArray();
        }
        public static void CreateUnitBoxVerticesAndIndices(out TangentVertex[] vertices, out short[] indices)
        {
            vertices = new TangentVertex[4 * 6];

            int i;

            //Note: right handed axis

            // Front (topleft, topright, bottomleft, bottomright)
            i = 4 * 0;
            vertices[i].pos = new Vector3(0, 1, 1); i++;
            vertices[i].pos = new Vector3(1, 1, 1); i++;
            vertices[i].pos = new Vector3(0, 0, 1); i++;
            vertices[i].pos = new Vector3(1, 0, 1); i++;
            i -= 4;
            vertices[i].uv = new Vector2(0, 0); i++;
            vertices[i].uv = new Vector2(1, 0); i++;
            vertices[i].uv = new Vector2(0, 1); i++;
            vertices[i].uv = new Vector2(1, 1); i++;

            for (int j = i - 4; j < i; j++)
            {
                vertices[j].normal = Vector3.Backward;
            }

            // Back (topleft, topright, bottomleft, bottomright)
            i = 4 * 1;
            vertices[i].pos = new Vector3(1, 1, 0); i++;
            vertices[i].pos = new Vector3(0, 1, 0); i++;
            vertices[i].pos = new Vector3(1, 0, 0); i++;
            vertices[i].pos = new Vector3(0, 0, 0); i++;
            i -= 4;
            vertices[i].uv = new Vector2(0, 0); i++;
            vertices[i].uv = new Vector2(1, 0); i++;
            vertices[i].uv = new Vector2(0, 1); i++;
            vertices[i].uv = new Vector2(1, 1); i++;

            for (int j = i - 4; j < i; j++)
            {
                vertices[j].normal = Vector3.Forward;
            }


            // Left (topleft, topright, bottomleft, bottomright)
            i = 4 * 2;
            vertices[i].pos = new Vector3(0, 1, 0); i++;
            vertices[i].pos = new Vector3(0, 1, 1); i++;
            vertices[i].pos = new Vector3(0, 0, 0); i++;
            vertices[i].pos = new Vector3(0, 0, 1); i++;
            i -= 4;
            vertices[i].uv = new Vector2(0, 0); i++;
            vertices[i].uv = new Vector2(1, 0); i++;
            vertices[i].uv = new Vector2(0, 1); i++;
            vertices[i].uv = new Vector2(1, 1); i++;

            for (int j = i - 4; j < i; j++)
            {
                vertices[j].normal = Vector3.Left;
            }

            // Right (topleft, topright, bottomleft, bottomright)
            i = 4 * 3;
            vertices[i].pos = new Vector3(1, 1, 1); i++;
            vertices[i].pos = new Vector3(1, 1, 0); i++;
            vertices[i].pos = new Vector3(1, 0, 1); i++;
            vertices[i].pos = new Vector3(1, 0, 0); i++;
            i -= 4;
            vertices[i].uv = new Vector2(0, 0); i++;
            vertices[i].uv = new Vector2(1, 0); i++;
            vertices[i].uv = new Vector2(0, 1); i++;
            vertices[i].uv = new Vector2(1, 1); i++;

            for (int j = i - 4; j < i; j++)
            {
                vertices[j].normal = Vector3.Right;
            }

            // Top (topleft, topright, bottomleft, bottomright)
            i = 4 * 4;
            vertices[i].pos = new Vector3(0, 1, 0); i++;
            vertices[i].pos = new Vector3(1, 1, 0); i++;
            vertices[i].pos = new Vector3(0, 1, 1); i++;
            vertices[i].pos = new Vector3(1, 1, 1); i++;
            i -= 4;
            vertices[i].uv = new Vector2(0, 0); i++;
            vertices[i].uv = new Vector2(1, 0); i++;
            vertices[i].uv = new Vector2(0, 1); i++;
            vertices[i].uv = new Vector2(1, 1); i++;

            for (int j = i - 4; j < i; j++)
            {
                vertices[j].normal = Vector3.Up;
            }

            // Bottom (topleft, topright, bottomleft, bottomright)
            i = 4 * 5;
            vertices[i].pos = new Vector3(0, 0, 1); i++;
            vertices[i].pos = new Vector3(1, 0, 1); i++;
            vertices[i].pos = new Vector3(0, 0, 0); i++;
            vertices[i].pos = new Vector3(1, 0, 0); i++;
            i -= 4;
            vertices[i].uv = new Vector2(0, 1); i++;
            vertices[i].uv = new Vector2(1, 1); i++;
            vertices[i].uv = new Vector2(0, 0); i++;
            vertices[i].uv = new Vector2(1, 0); i++;

            for (int j = i - 4; j < i; j++)
            {
                vertices[j].normal = Vector3.Down;
            }

            indices = new short[6 * 6];
            i       = 0;
            for (short j = 0; j < 4 * 6; j += 4)
            {
                indices[i] = (short)(j + 0); i++;
                indices[i] = (short)(j + 1); i++;
                indices[i] = (short)(j + 2); i++;

                indices[i] = (short)(j + 1); i++;
                indices[i] = (short)(j + 3); i++;
                indices[i] = (short)(j + 2); i++;
            }
        }
        public void AddSphere(int segments, float radius, MeshMaterial material)
        {
            if (!parts.ContainsKey(material))
            {
                throw new InvalidOperationException("Material not created by the meshbuilder");
            }
            TangentVertex[] vertices;
            short[]         indices;
            // Source: http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/sphere_cylinder/

            // Maak ringen van vertices van onder naar boven


            int i = 0;

            float phi, theta;
            float phiStep, thetaStep;
            float phiStart, phiEnd, thetaStart, thetaEnd;

            phiStep   = MathHelper.TwoPi / segments;
            thetaStep = MathHelper.Pi / segments;

            phiStart   = 0;
            phiEnd     = MathHelper.TwoPi;
            thetaStart = -MathHelper.PiOver2 + thetaStep;
            thetaEnd   = MathHelper.PiOver2;

            int numRings       = (int)Math.Round((thetaEnd - thetaStart) / thetaStep);
            int numVertsOnRing = (int)Math.Round((phiEnd - phiStart) / phiStep);



            int numVertices = 1 + numRings * numVertsOnRing + 1;


            vertices = new TangentVertex[numVertices];

            // Bottom vertex: (0,-1,0)
            vertices[i].pos = new Microsoft.Xna.Framework.Vector3(0, -1, 0);
            i++;

            theta = thetaStart;
            for (int iRing = 0; iRing < numRings; iRing++, theta += thetaStep)
            {
                phi = 0;
                for (int iVert = 0; iVert < numVertsOnRing; iVert++, phi += phiStep)
                {
                    vertices[i].pos = new Microsoft.Xna.Framework.Vector3(
                        (float)Math.Cos(theta) * (float)Math.Cos(phi),
                        (float)Math.Sin(theta),
                        -(float)Math.Cos(theta) * (float)Math.Sin(phi));
                    i++;
                }
            }
            // Top vertex: (0,1,0)
            vertices[i].pos = new Microsoft.Xna.Framework.Vector3(0, 1, 0);
            i++;


            // Generate normals
            for (int j = 0; j < vertices.Length; j++)
            {
                vertices[j].normal = Microsoft.Xna.Framework.Vector3.Normalize(vertices[j].pos);
            }


            int numIndices = (numVertsOnRing * 2 * 3) * numRings;

            indices = new short[numIndices];
            i       = 0;

            // Triangle fan at bottom and top, elsewhere strips between the rings

            // Top and bottom fan

            for (int iVert = 0; iVert < numVertsOnRing - 1; iVert++)
            {
                // Bottom fan
                indices[i] = (short)(0); i++;
                indices[i] = (short)(1 + iVert); i++;
                indices[i] = (short)(1 + (iVert + 1)); i++;

                // Top fan
                indices[i] = (short)(numVertices - 1); i++;
                indices[i] = (short)(1 + (numRings - 1) * numVertsOnRing + (iVert + 1)); i++;
                indices[i] = (short)(1 + (numRings - 1) * numVertsOnRing + iVert); i++;
            }

            // Top and bottom final fan
            indices[i] = (short)(0); i++;
            indices[i] = (short)(1 + numVertsOnRing - 1); i++;
            indices[i] = (short)(1 + 0); i++;

            indices[i] = (short)(numVertices - 1); i++;
            indices[i] = (short)(1 + (numRings - 1) * numVertsOnRing + 0); i++;
            indices[i] = (short)(1 + (numRings - 1) * numVertsOnRing + numVertsOnRing - 1); i++;

            // Strips
            for (int iRing = 0; iRing < numRings - 1; iRing++)
            {
                for (int iVert = 0; iVert < numVertsOnRing - 1; iVert++)
                {
                    indices[i] = (short)(1 + numVertsOnRing * iRing + iVert); i++;
                    indices[i] = (short)(1 + numVertsOnRing * (iRing + 1) + iVert); i++;
                    indices[i] = (short)(1 + numVertsOnRing * iRing + (iVert + 1)); i++;

                    indices[i] = (short)(1 + numVertsOnRing * iRing + (iVert + 1)); i++;
                    indices[i] = (short)(1 + numVertsOnRing * (iRing + 1) + iVert); i++;
                    indices[i] = (short)(1 + numVertsOnRing * (iRing + 1) + (iVert + 1)); i++;
                }
                // Final gap:
                indices[i] = (short)(1 + numVertsOnRing * iRing + (numVertsOnRing - 1)); i++;
                indices[i] = (short)(1 + numVertsOnRing * (iRing + 1) + (numVertsOnRing - 1)); i++;
                indices[i] = (short)(1 + numVertsOnRing * iRing + (0)); i++;

                indices[i] = (short)(1 + numVertsOnRing * iRing + (0)); i++;
                indices[i] = (short)(1 + numVertsOnRing * (iRing + 1) + (numVertsOnRing - 1)); i++;
                indices[i] = (short)(1 + numVertsOnRing * (iRing + 1) + (0)); i++;
            }

            var mapping = new SphericalMapping();

            var data = parts[material];

            foreach (var index in indices)
            {
                data.Positions.Add(vertices[index].pos * radius);
                data.Normals.Add(vertices[index].normal);
                data.Texcoords.Add(mapping.Map(data.Positions[data.Positions.Count - 1].ToSlimDX()).xna() * 3);
            }
        }
        private static void LoadMesh(AssetImporterGltfMeshContext context, int meshIndex, Matrix worldMatrix)
        {
            Mesh mesh = context.Model.Meshes[meshIndex];

            for (int p = 0; p < mesh.Primitives.Length; p++)
            {
                var prim = mesh.Primitives[p];

                if (prim.Mode != MeshPrimitive.ModeEnum.TRIANGLES)
                {
                    throw new NotImplementedException("Modes other than TRIANGLES are not implemented (yet)");
                }

                Accessor positionAccessor = GetAccessorByType("POSITION", context.Model, prim);
                if (positionAccessor.Type != Accessor.TypeEnum.VEC3)
                {
                    throw new InvalidDataException("POSITION accessor must have type VEC3");
                }

                Accessor normalAccessor = GetAccessorByType("NORMAL", context.Model, prim);
                if (normalAccessor != null &&
                    normalAccessor.Type != Accessor.TypeEnum.VEC3)
                {
                    throw new InvalidDataException("NORMAL accessor must have type VEC3");
                }

                Accessor texcoordAccessor = GetAccessorByType("TEXCOORD_0", context.Model, prim);
                if (texcoordAccessor != null &&
                    texcoordAccessor.Type != Accessor.TypeEnum.VEC2)
                {
                    throw new InvalidDataException("TEXCOORD accessor must have type VEC2");
                }

                Accessor tangentAccessor = GetAccessorByType("TANGENT", context.Model, prim);
                if (tangentAccessor != null &&
                    tangentAccessor.Type != Accessor.TypeEnum.VEC4)
                {
                    throw new InvalidDataException("TANGENT accessor must have type VEC4");
                }

                TangentVertex[] vertices           = new TangentVertex[positionAccessor.Count];
                BufferView      positionBufferView = context.Model.BufferViews[positionAccessor.BufferView.Value];
                BufferView      normalsBufferView  = null;
                if (normalAccessor != null)
                {
                    normalsBufferView = context.Model.BufferViews[normalAccessor.BufferView.Value];
                }
                BufferView texCoordBufferView = null;
                if (texcoordAccessor != null)
                {
                    texCoordBufferView = context.Model.BufferViews[texcoordAccessor.BufferView.Value];
                }
                BufferView tangentBufferView = null;
                if (tangentAccessor != null)
                {
                    tangentBufferView = context.Model.BufferViews[tangentAccessor.BufferView.Value];
                }

                ReadOnlySpan <Vector3> positionSpan = MemoryMarshal.Cast <byte, Vector3>(
                    new ReadOnlySpan <byte>(context.RawBuffers[positionBufferView.Buffer], positionBufferView.ByteOffset + positionAccessor.ByteOffset, positionAccessor.Count * 12));
                ReadOnlySpan <Vector3> normalsSpan = null;
                if (normalsBufferView != null)
                {
                    normalsSpan = MemoryMarshal.Cast <byte, Vector3>(
                        new ReadOnlySpan <byte>(context.RawBuffers[normalsBufferView.Buffer], normalsBufferView.ByteOffset + normalAccessor.ByteOffset, normalAccessor.Count * 12));
                }
                ReadOnlySpan <Vector2> texCoordSpan = null;
                if (texCoordBufferView != null)
                {
                    texCoordSpan = MemoryMarshal.Cast <byte, Vector2>(
                        new ReadOnlySpan <byte>(context.RawBuffers[texCoordBufferView.Buffer], texCoordBufferView.ByteOffset + texcoordAccessor.ByteOffset, texcoordAccessor.Count * 8));
                }
                ReadOnlySpan <Vector4> tangentSpan = null;
                if (tangentBufferView != null)
                {
                    tangentSpan = MemoryMarshal.Cast <byte, Vector4>(
                        new ReadOnlySpan <byte>(context.RawBuffers[tangentBufferView.Buffer], tangentBufferView.ByteOffset + tangentAccessor.ByteOffset, tangentAccessor.Count * 16));
                }

                for (int v = 0; v < vertices.Length; v++)
                {
                    vertices[v].Position = positionSpan[v];

                    if (normalsSpan != null)
                    {
                        vertices[v].Normal = normalsSpan[v];
                    }

                    if (texCoordSpan != null)
                    {
                        vertices[v].TexCoord = texCoordSpan[v];
                    }

                    if (tangentSpan != null)
                    {
                        vertices[v].Tangent = new Vector3(tangentSpan[v].X, tangentSpan[v].Y, tangentSpan[v].Z);
                        if (normalsSpan != null)
                        {
                            vertices[v].BiTangent = Vector3.Cross(normalsSpan[v], vertices[v].Tangent) * tangentSpan[v].W;
                        }
                    }
                }

                StaticMesh staticMesh = null;

                if (prim.Indices == null)
                {
                    staticMesh = StaticMesh.FromVertices(vertices);
                }
                else
                {
                    int      primIndex     = prim.Indices.Value;
                    Accessor indexAccessor = GetAccessorByIndex(primIndex, context.Model);
                    if (indexAccessor != null)
                    {
                        if (indexAccessor.Type != Accessor.TypeEnum.SCALAR)
                        {
                            throw new InvalidDataException("Index accessor must have type SCALAR");
                        }

                        uint[] indices = new uint[indexAccessor.Count];

                        BufferView indexBufferView = context.Model.BufferViews[indexAccessor.BufferView.Value];
                        switch (indexAccessor.ComponentType)
                        {
                        case Accessor.ComponentTypeEnum.UNSIGNED_BYTE:
                        {
                            ReadOnlySpan <byte> indexSpan =
                                new ReadOnlySpan <byte>(context.RawBuffers[indexBufferView.Buffer], indexBufferView.ByteOffset + indexAccessor.ByteOffset, indexAccessor.Count);

                            for (int idx = 0; idx < indices.Length; idx++)
                            {
                                indices[idx] = (uint)indexSpan[idx];
                            }
                        }
                        break;

                        case Accessor.ComponentTypeEnum.UNSIGNED_SHORT:
                        {
                            ReadOnlySpan <ushort> indexSpan = MemoryMarshal.Cast <byte, ushort>(
                                new ReadOnlySpan <byte>(context.RawBuffers[indexBufferView.Buffer], indexBufferView.ByteOffset + indexAccessor.ByteOffset, indexAccessor.Count * 2));

                            for (int idx = 0; idx < indices.Length; idx++)
                            {
                                indices[idx] = (uint)indexSpan[idx];
                            }
                        }
                        break;

                        case Accessor.ComponentTypeEnum.UNSIGNED_INT:
                        {
                            ReadOnlySpan <uint> indexSpan = MemoryMarshal.Cast <byte, uint>(
                                new ReadOnlySpan <byte>(context.RawBuffers[indexBufferView.Buffer], indexBufferView.ByteOffset + indexAccessor.ByteOffset, indexAccessor.Count * 4));

                            indices = indexSpan.ToArray();
                        }
                        break;

                        default:
                            throw new NotImplementedException("ComponentType " + indexAccessor.ComponentType + " not implemented.");
                        }

                        staticMesh = StaticMesh.FromVertices(vertices, indices);
                    }
                }

                staticMesh.Name = mesh.Name + "_" + p + ".staticMesh";
                context.PackageToSaveIn.StoreAsset(staticMesh);

                Materials.Material material = CreateMaterialForMesh(prim, context.Model);
                staticMesh.Material = material;

                context.ImportedAssets.Add(staticMesh);
            }
        }
        public void TestRenderDefaultModelShader()
        {
            var shaders = new List <DefaultModelShader>();
            DefaultModelShader shader = null;
            VertexBuffer       vb     = null;

            VertexDeclaration decl = null;

            XNAGame game = new XNAGame();

            game.InitializeEvent += delegate
            {
                decl = TangentVertexExtensions.CreateVertexDeclaration(game);
                TangentVertex[] vertices = new TangentVertex[4];


                vertices[0] = new TangentVertex(Vector3.Zero, Vector2.Zero, Vector3.Up, Vector3.Zero);
                vertices[1] = new TangentVertex(Vector3.Forward, Vector2.UnitX, Vector3.Up, Vector3.Zero);
                vertices[2] = new TangentVertex(Vector3.Forward + Vector3.Right, Vector2.UnitX + Vector2.UnitY, Vector3.Up, Vector3.Zero);
                vertices[3] = new TangentVertex(Vector3.Right, Vector2.UnitY, Vector3.Up, Vector3.Zero);

                vb = new VertexBuffer(game.GraphicsDevice, typeof(TangentVertex), vertices.Length, BufferUsage.None);

                vb.SetData(vertices);
                shader = new DefaultModelShader(game, new EffectPool());

                DefaultModelShader s;

                Texture2D tex = Texture2D.FromFile(game.GraphicsDevice, File.OpenRead(TestFiles.WoodPlanksBareJPG));


                s = shader.Clone();
                s.DiffuseColor = Color.Red.ToVector4();
                s.Technique    = DefaultModelShader.TechniqueType.Colored;
                shaders.Add(s);

                s = shader.Clone();
                s.DiffuseTexture = tex;
                s.Technique      = DefaultModelShader.TechniqueType.Textured;
                shaders.Add(s);
            };

            game.DrawEvent += delegate
            {
                game.GraphicsDevice.RenderState.CullMode = CullMode.None;

                game.GraphicsDevice.VertexDeclaration = decl;

                shader.ViewProjection = game.Camera.ViewProjection;

                for (int i = 0; i < shaders.Count; i++)
                {
                    //shaders[i].ViewProjection = game.Camera.ViewProjection;
                    shaders[i].World = Matrix.CreateTranslation(Vector3.Right * i * 3) * Matrix.CreateScale(10);
                    shaders[i].DrawPrimitives(delegate()
                    {
                        game.GraphicsDevice.Vertices[0].SetSource(vb, 0,
                                                                  TangentVertex.SizeInBytes);
                        game.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleFan, 0, 2);
                    }
                                              );
                }
            };

            game.Run();
        }
Example #11
0
        /// <summary>
        /// Loads the static mesh from the compiled binary mesh
        /// </summary>
        public override void Deserialize(BinaryReader reader)
        {
            base.Deserialize(reader);

            // Read mesh data
            int NumTriangles = reader.ReadInt32();
            int vertLen      = reader.ReadInt32();

            objectVertices = new TangentVertex[vertLen];
            for (int i = 0; i < objectVertices.Length; i++)
            {
                objectVertices[i] = new TangentVertex(
                    new Vector3(reader.ReadSingle(), reader.ReadSingle(),
                                reader.ReadSingle()),
                    new Vector2(reader.ReadSingle(), reader.ReadSingle()),
                    new Vector3(reader.ReadSingle(), reader.ReadSingle(),
                                reader.ReadSingle()),
                    new Vector3(reader.ReadSingle(), reader.ReadSingle(),
                                reader.ReadSingle()),
                    new Vector3(reader.ReadSingle(), reader.ReadSingle(),
                                reader.ReadSingle()));
            }

            int indexLen = reader.ReadInt32();

            objectIndices = new uint[indexLen];
            for (int i = 0; i < objectIndices.Length; i++)
            {
                objectIndices[i] = reader.ReadUInt32();
            }

            // Read BoundingSphere
            BoundingSphere = new BoundingSphere(
                new Vector3(reader.ReadSingle(), reader.ReadSingle(),
                            reader.ReadSingle()),
                reader.ReadSingle());

            // Read MeshCameras
            int meshCameraCount = reader.ReadInt32();

            if (meshCameraCount == 0)
            {
                MeshCameras = null;
            }
            else
            {
                MeshCameras = new MeshCamera[meshCameraCount];
                for (int i = 0; i < meshCameraCount; i++)
                {
                    MeshCameras[i]             = new MeshCamera();
                    MeshCameras[i].Translation = new Vector3(
                        reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                    MeshCameras[i].CameraType = (MeshCameraType)reader.ReadInt32();
                }
            }

            // Create XNA buffers and fill them
            try
            {
                VertexBuffer newVertexBuffer = new VertexBuffer(AlkaronCoreGame.Core.GraphicsDevice,
                                                                TangentVertex.VertexDecl,
                                                                TangentVertex.SizeInBytes * objectVertices.Length,
                                                                BufferUsage.WriteOnly);

                IndexBuffer newIndexBuffer = new IndexBuffer(AlkaronCoreGame.Core.GraphicsDevice,
                                                             IndexElementSize.ThirtyTwoBits,
                                                             objectIndices.Length, BufferUsage.WriteOnly);

                if (newVertexBuffer != null)
                {
                    if (vertexBuffer != null)
                    {
                        vertexBuffer.Dispose();
                        vertexBuffer = null;
                    }

                    vertexBuffer = newVertexBuffer;
                }
                if (newIndexBuffer != null)
                {
                    if (indexBuffer != null)
                    {
                        indexBuffer.Dispose();
                        indexBuffer = null;
                    }

                    indexBuffer = newIndexBuffer;
                }
            }
            catch
            {
                return;
            }

            vertexBuffer.SetData <TangentVertex>(objectVertices);
            indexBuffer.SetData <uint>(objectIndices);

            CreateBoundingSphere();
        }
Example #12
0
        /// <summary>
        /// This code is also in Meshbuilder...
        /// </summary>
        /// <param name="segments"></param>
        /// <param name="vertices"></param>
        /// <param name="indices"></param>
        public static void CreateUnitSphereVerticesAndIndices(int segments, out TangentVertex[] vertices, out short[] indices)
        {
            // Source: http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/sphere_cylinder/



            // Maak ringen van vertices van onder naar boven


            int i = 0;

            float phi, theta;
            float phiStep, thetaStep;
            float phiStart, phiEnd, thetaStart, thetaEnd;

            phiStep   = MathHelper.TwoPi / segments;
            thetaStep = MathHelper.Pi / segments;

            phiStart   = 0;
            phiEnd     = MathHelper.TwoPi;
            thetaStart = -MathHelper.PiOver2 + thetaStep;
            thetaEnd   = MathHelper.PiOver2;

            int numRings       = (int)Math.Round((thetaEnd - thetaStart) / thetaStep);
            int numVertsOnRing = (int)Math.Round((phiEnd - phiStart) / phiStep);



            int numVertices = 1 + numRings * numVertsOnRing + 1;


            vertices = new TangentVertex[numVertices];

            // Bottom vertex: (0,-1,0)
            vertices[i].pos = new Vector3(0, -1, 0);
            i++;

            theta = thetaStart;
            for (int iRing = 0; iRing < numRings; iRing++, theta += thetaStep)
            {
                phi = 0;
                for (int iVert = 0; iVert < numVertsOnRing; iVert++, phi += phiStep)
                {
                    vertices[i].pos = new Vector3(
                        (float)Math.Cos(theta) * (float)Math.Cos(phi),
                        (float)Math.Sin(theta),
                        -(float)Math.Cos(theta) * (float)Math.Sin(phi));
                    //TODO: normals
                    i++;
                }
            }
            // Top vertex: (0,1,0)
            vertices[i].pos = new Vector3(0, 1, 0);
            i++;


            // Generate normals
            for (int j = 0; j < vertices.Length; j++)
            {
                vertices[j].normal = Vector3.Normalize(vertices[j].pos);
            }


            int numIndices = (numVertsOnRing * 2 * 3) * numRings;

            indices = new short[numIndices];
            i       = 0;

            // Triangle fan at bottom and top, elsewhere strips between the rings

            // Top and bottom fan

            for (int iVert = 0; iVert < numVertsOnRing - 1; iVert++)
            {
                // Bottom fan
                indices[i] = (short)(0); i++;
                indices[i] = (short)(1 + iVert); i++;
                indices[i] = (short)(1 + (iVert + 1)); i++;

                // Top fan
                indices[i] = (short)(numVertices - 1); i++;
                indices[i] = (short)(1 + (numRings - 1) * numVertsOnRing + (iVert + 1)); i++;
                indices[i] = (short)(1 + (numRings - 1) * numVertsOnRing + iVert); i++;
            }

            // Top and bottom final fan
            indices[i] = (short)(0); i++;
            indices[i] = (short)(1 + numVertsOnRing - 1); i++;
            indices[i] = (short)(1 + 0); i++;

            indices[i] = (short)(numVertices - 1); i++;
            indices[i] = (short)(1 + (numRings - 1) * numVertsOnRing + 0); i++;
            indices[i] = (short)(1 + (numRings - 1) * numVertsOnRing + numVertsOnRing - 1); i++;

            // Strips
            for (int iRing = 0; iRing < numRings - 1; iRing++)
            {
                for (int iVert = 0; iVert < numVertsOnRing - 1; iVert++)
                {
                    indices[i] = (short)(1 + numVertsOnRing * iRing + iVert); i++;
                    indices[i] = (short)(1 + numVertsOnRing * (iRing + 1) + iVert); i++;
                    indices[i] = (short)(1 + numVertsOnRing * iRing + (iVert + 1)); i++;

                    indices[i] = (short)(1 + numVertsOnRing * iRing + (iVert + 1)); i++;
                    indices[i] = (short)(1 + numVertsOnRing * (iRing + 1) + iVert); i++;
                    indices[i] = (short)(1 + numVertsOnRing * (iRing + 1) + (iVert + 1)); i++;
                }
                // Final gap:
                indices[i] = (short)(1 + numVertsOnRing * iRing + (numVertsOnRing - 1)); i++;
                indices[i] = (short)(1 + numVertsOnRing * (iRing + 1) + (numVertsOnRing - 1)); i++;
                indices[i] = (short)(1 + numVertsOnRing * iRing + (0)); i++;

                indices[i] = (short)(1 + numVertsOnRing * iRing + (0)); i++;
                indices[i] = (short)(1 + numVertsOnRing * (iRing + 1) + (numVertsOnRing - 1)); i++;
                indices[i] = (short)(1 + numVertsOnRing * (iRing + 1) + (0)); i++;
            }
        }