/// <summary> /// Creates a model with VertexBuffer and IndexBuffer. /// </summary> /// <param name="customMesh">A mesh defined with VertexBuffer and IndexBuffer</param> public PrimitiveModel(CustomMesh customMesh) { offsetTransform = Matrix.Identity; offsetToOrigin = false; vertices = new List <Vector3>(); indices = new List <int>(); this.customMesh = customMesh; shader = new SimpleEffectShader(); afterEffectShaders = new List <IShader>(); customShapeParameters = ""; #if !WINDOWS_PHONE shaderName = TypeDescriptor.GetClassName(shader); #endif useLighting = true; shadowAttribute = ShadowAttribute.None; showBoundingBox = false; useVertexColor = false; technique = ""; if (customMesh != null) { CalculateMinimumBoundingBox(); triangleCount = customMesh.NumberOfPrimitives; } }
/// <summary> /// Actually builds the text /// </summary> /// <returns> The custom mesh that has all of the geometry information</returns> private void CreateText() { customMesh = new CustomMesh(); CreateShape(); foreach (VertexPositionNormalTexture aVertex in basicTextIn3D.Vertices) { vertices.Add(aVertex.Position); } if (styleToUse == UI3DRenderer.Text3DStyle.Fill) { for (int i = 0; i < basicTextIn3D.Vertices.Length; ++i) { basicTextIn3D.Vertices[i].Normal = -basicTextIn3D.Vertices[i].Normal; } } foreach (short index in basicTextIn3D.Indices) { indices.Add((int)index); } customMesh.VertexDeclaration = VertexPositionNormalTexture.VertexDeclaration; customMesh.VertexBuffer = new VertexBuffer(State.Device, typeof(VertexPositionNormalTexture), basicTextIn3D.Vertices.Length, BufferUsage.None); customMesh.VertexBuffer.SetData(basicTextIn3D.Vertices); customMesh.IndexBuffer = new IndexBuffer(State.Device, typeof(short), basicTextIn3D.Indices.Length, BufferUsage.None); customMesh.IndexBuffer.SetData(basicTextIn3D.Indices); customMesh.NumberOfVertices = basicTextIn3D.Vertices.Length; customMesh.NumberOfPrimitives = basicTextIn3D.Indices.Length / 3; customMesh.PrimitiveType = basicTextIn3D.PrimitiveType; if (vertices.Count == 0) { throw new GoblinException("Corrupted model vertices. Failed to calculate MBB."); } else { boundingBox = BoundingBox.CreateFromPoints(vertices); boundingSphere = BoundingSphere.CreateFromPoints(vertices); if (offsetTransform.Equals(Matrix.Identity)) { offsetTransform.Translation = (boundingBox.Min + boundingBox.Max) / 2; } } triangleCount = indices.Count / 3; }
private static CustomMesh CreateLayer(Vector2 dimension) { CustomMesh mesh = new CustomMesh(); VertexPositionNormalTexture[] vertices = new VertexPositionNormalTexture[4]; Vector2 halfExtent = dimension / 2; Vector3 v0 = Vector3Helper.Get(-halfExtent.X, 0, -halfExtent.Y); Vector3 v1 = Vector3Helper.Get(-halfExtent.X, 0, halfExtent.Y); Vector3 v2 = Vector3Helper.Get(halfExtent.X, 0, halfExtent.Y); Vector3 v3 = Vector3Helper.Get(halfExtent.X, 0, -halfExtent.Y); vertices[0].Position = v0; vertices[1].Position = v1; vertices[2].Position = v2; vertices[3].Position = v3; for (int i = 0; i < vertices.Length; i++) vertices[i].Normal = Vector3.UnitY; vertices[1].TextureCoordinate = new Vector2(0, 1); vertices[0].TextureCoordinate = new Vector2(0, 0); vertices[2].TextureCoordinate = new Vector2(1, 1); vertices[3].TextureCoordinate = new Vector2(1, 0); mesh.VertexDeclaration = new VertexDeclaration(State.Device, VertexPositionNormalTexture.VertexElements); mesh.VertexBuffer = new VertexBuffer(State.Device, VertexPositionNormalTexture.SizeInBytes * vertices.Length, BufferUsage.None); mesh.VertexBuffer.SetData(vertices); short[] indices = new short[6]; indices[0] = 0; indices[1] = 2; indices[2] = 1; indices[3] = 2; indices[4] = 0; indices[5] = 3; mesh.IndexBuffer = new IndexBuffer(State.Device, typeof(short), 6, BufferUsage.None); mesh.IndexBuffer.SetData(indices); mesh.SizeInBytes = VertexPositionNormalTexture.SizeInBytes; mesh.NumberOfVertices = 4; mesh.NumberOfPrimitives = 2; return mesh; }
/// <summary> /// Copies only the geometry (Mesh, customMesh, AnimatedMesh, /// MinimumBoundingBox, MinimumBoundingSphere, TriangleCount and Transforms) /// </summary> /// <param name="model">A source model from which to copy</param> public virtual void CopyGeometry(IModel model) { if (!(model is PrimitiveModel)) { return; } PrimitiveModel srcModel = (PrimitiveModel)model; vertices.AddRange(((IPhysicsMeshProvider)model).Vertices); indices.AddRange(((IPhysicsMeshProvider)model).Indices); customMesh = srcModel.customMesh; triangleCount = srcModel.TriangleCount; boundingBox = srcModel.MinimumBoundingBox; boundingSphere = srcModel.MinimumBoundingSphere; }
private static CustomMesh CreateShape(float xDim, float yDim, float zDim) { // Create a primitive mesh for creating our custom pyramid shape CustomMesh pyramid = new CustomMesh(); // Even though we really need 5 vertices to create a pyramid shape, since // we want to assign different normals for points with same position to have // more accurate lighting effect, we will use 16 vertices. VertexPositionNormal[] verts = new VertexPositionNormal[16]; Vector3 vBase0 = new Vector3(-xDim / 2, 0, zDim / 2); Vector3 vBase1 = new Vector3(xDim / 2, 0, zDim / 2); Vector3 vBase2 = new Vector3(xDim / 2, 0, -zDim / 2); Vector3 vBase3 = new Vector3(-xDim / 2, 0, -zDim / 2); Vector3 vTop = new Vector3(0, yDim, 0); verts[0].Position = vTop; verts[1].Position = vBase1; verts[2].Position = vBase0; verts[3].Position = vTop; verts[4].Position = vBase2; verts[5].Position = vBase1; verts[6].Position = vTop; verts[7].Position = vBase3; verts[8].Position = vBase2; verts[9].Position = vTop; verts[10].Position = vBase0; verts[11].Position = vBase3; verts[12].Position = vBase0; verts[13].Position = vBase1; verts[14].Position = vBase2; verts[15].Position = vBase3; verts[0].Normal = verts[1].Normal = verts[2].Normal = CalcNormal(vTop, vBase1, vBase0); verts[3].Normal = verts[4].Normal = verts[5].Normal = CalcNormal(vTop, vBase2, vBase1); verts[6].Normal = verts[7].Normal = verts[8].Normal = CalcNormal(vTop, vBase3, vBase2); verts[9].Normal = verts[10].Normal = verts[11].Normal = CalcNormal(vTop, vBase0, vBase3); verts[12].Normal = verts[13].Normal = verts[14].Normal = verts[15].Normal = CalcNormal(vBase0, vBase1, vBase3); pyramid.VertexBuffer = new VertexBuffer(State.Device, typeof(VertexPositionNormal), 16, BufferUsage.None); pyramid.VertexDeclaration = VertexPositionNormal.VertexDeclaration; pyramid.VertexBuffer.SetData(verts); pyramid.NumberOfVertices = 16; short[] indices = new short[18]; indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 3; indices[4] = 4; indices[5] = 5; indices[6] = 6; indices[7] = 7; indices[8] = 8; indices[9] = 9; indices[10] = 10; indices[11] = 11; indices[12] = 12; indices[13] = 13; indices[14] = 15; indices[15] = 13; indices[16] = 14; indices[17] = 15; pyramid.IndexBuffer = new IndexBuffer(State.Device, typeof(short), 18, BufferUsage.WriteOnly); pyramid.IndexBuffer.SetData(indices); pyramid.PrimitiveType = PrimitiveType.TriangleList; pyramid.NumberOfPrimitives = 6; return pyramid; }
private void CreateObject() { // Create a primitive mesh for creating our custom pyramid shape CustomMesh pyramid = new CustomMesh(); // Even though we really need 5 vertices to create a pyramid shape, since // we want to assign different normals for points with same position to have // more accurate lighting effect, we will use 16 vertices. // Also, we want to have position, normal, and texture information in our // vertices, we'll use VertexPositionNormalTexture format. There are other // types of Vertex format as well depending on your needs. VertexPositionNormalTexture[] verts = new VertexPositionNormalTexture[16]; // Create a pyramid with 8x8 base and height of 6 Vector3 vBase0 = new Vector3(-4, 0, 4); Vector3 vBase1 = new Vector3(4, 0, 4); Vector3 vBase2 = new Vector3(4, 0, -4); Vector3 vBase3 = new Vector3(-4, 0, -4); Vector3 vTop = new Vector3(0, 6, 0); verts[0].Position = vTop; verts[1].Position = vBase1; verts[2].Position = vBase0; verts[3].Position = vTop; verts[4].Position = vBase2; verts[5].Position = vBase1; verts[6].Position = vTop; verts[7].Position = vBase3; verts[8].Position = vBase2; verts[9].Position = vTop; verts[10].Position = vBase0; verts[11].Position = vBase3; verts[12].Position = vBase0; verts[13].Position = vBase1; verts[14].Position = vBase2; verts[15].Position = vBase3; verts[0].Normal = verts[1].Normal = verts[2].Normal = CalcNormal(vTop, vBase1, vBase0); verts[3].Normal = verts[4].Normal = verts[5].Normal = CalcNormal(vTop, vBase2, vBase1); verts[6].Normal = verts[7].Normal = verts[8].Normal = CalcNormal(vTop, vBase3, vBase2); verts[9].Normal = verts[10].Normal = verts[11].Normal = CalcNormal(vTop, vBase0, vBase3); verts[12].Normal = verts[13].Normal = verts[14].Normal = verts[15].Normal = CalcNormal(vBase0, vBase1, vBase3); Vector2 texCoordTop = new Vector2(0.5f, 0); Vector2 texCoordLeftBase = new Vector2(0, 1); Vector2 texCoordRightBase = new Vector2(1, 1); verts[0].TextureCoordinate = texCoordTop; verts[1].TextureCoordinate = texCoordLeftBase; verts[2].TextureCoordinate = texCoordRightBase; verts[3].TextureCoordinate = texCoordTop; verts[4].TextureCoordinate = texCoordLeftBase; verts[5].TextureCoordinate = texCoordRightBase; verts[6].TextureCoordinate = texCoordTop; verts[7].TextureCoordinate = texCoordLeftBase; verts[8].TextureCoordinate = texCoordRightBase; verts[9].TextureCoordinate = texCoordTop; verts[10].TextureCoordinate = texCoordLeftBase; verts[11].TextureCoordinate = texCoordRightBase; verts[12].TextureCoordinate = new Vector2(1, 1); verts[13].TextureCoordinate = new Vector2(1, 0); verts[14].TextureCoordinate = new Vector2(0, 0); verts[15].TextureCoordinate = new Vector2(0, 1); pyramid.VertexBuffer = new VertexBuffer(graphics.GraphicsDevice, typeof(VertexPositionNormalTexture), 16, BufferUsage.None); pyramid.VertexDeclaration = VertexPositionNormalTexture.VertexDeclaration; pyramid.VertexBuffer.SetData(verts); pyramid.NumberOfVertices = 16; short[] indices = new short[18]; indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 3; indices[4] = 4; indices[5] = 5; indices[6] = 6; indices[7] = 7; indices[8] = 8; indices[9] = 9; indices[10] = 10; indices[11] = 11; indices[12] = 12; indices[13] = 13; indices[14] = 15; indices[15] = 13; indices[16] = 14; indices[17] = 15; pyramid.IndexBuffer = new IndexBuffer(graphics.GraphicsDevice, typeof(short), 18, BufferUsage.WriteOnly); pyramid.IndexBuffer.SetData(indices); pyramid.PrimitiveType = PrimitiveType.TriangleList; pyramid.NumberOfPrimitives = 6; PrimitiveModel pyramidModel = new PrimitiveModel(pyramid); GeometryNode pyramidNode = new GeometryNode(); pyramidNode.Model = pyramidModel; Material pyramidMaterial = new Material(); pyramidMaterial.Diffuse = Color.White.ToVector4(); pyramidMaterial.Specular = Color.White.ToVector4(); pyramidMaterial.SpecularPower = 10; pyramidMaterial.Texture = Content.Load<Texture2D>("brick_wall_14"); pyramidNode.Material = pyramidMaterial; scene.RootNode.AddChild(pyramidNode); }
/// <summary> /// Creates a model with VertexBuffer and IndexBuffer. /// </summary> /// <param name="customMesh">A mesh defined with VertexBuffer and IndexBuffer</param> public PrimitiveModel(CustomMesh customMesh) { offsetTransform = Matrix.Identity; offsetToOrigin = false; vertices = new List<Vector3>(); indices = new List<int>(); this.customMesh = customMesh; shader = new SimpleEffectShader(); afterEffectShaders = new List<IShader>(); customShapeParameters = ""; #if !WINDOWS_PHONE shaderName = TypeDescriptor.GetClassName(shader); #endif useLighting = true; shadowAttribute = ShadowAttribute.None; showBoundingBox = false; useVertexColor = false; technique = ""; if (customMesh != null) { CalculateMinimumBoundingBox(); triangleCount = customMesh.NumberOfPrimitives; } }
/// <summary> /// Copies only the geometry (Mesh, customMesh, AnimatedMesh, /// MinimumBoundingBox, MinimumBoundingSphere, TriangleCount and Transforms) /// </summary> /// <param name="model">A source model from which to copy</param> public virtual void CopyGeometry(IModel model) { if (!(model is PrimitiveModel)) return; PrimitiveModel srcModel = (PrimitiveModel)model; vertices.AddRange(((IPhysicsMeshProvider)model).Vertices); indices.AddRange(((IPhysicsMeshProvider)model).Indices); customMesh = srcModel.customMesh; triangleCount = srcModel.TriangleCount; boundingBox = srcModel.MinimumBoundingBox; boundingSphere = srcModel.MinimumBoundingSphere; }
/// <summary> /// Actually builds the text /// </summary> /// <returns> The custom mesh that has all of the geometry information</returns> private void CreateText() { customMesh = new CustomMesh(); CreateShape(); foreach (VertexPositionNormalTexture aVertex in basicTextIn3D.Vertices) { vertices.Add(aVertex.Position); } if(styleToUse == UI3DRenderer.Text3DStyle.Fill) for (int i = 0; i < basicTextIn3D.Vertices.Length; ++i) basicTextIn3D.Vertices[i].Normal = -basicTextIn3D.Vertices[i].Normal; foreach (short index in basicTextIn3D.Indices) { indices.Add((int)index); } customMesh.VertexDeclaration = VertexPositionNormalTexture.VertexDeclaration; customMesh.VertexBuffer = new VertexBuffer(State.Device, typeof(VertexPositionNormalTexture), basicTextIn3D.Vertices.Length, BufferUsage.None); customMesh.VertexBuffer.SetData(basicTextIn3D.Vertices); customMesh.IndexBuffer = new IndexBuffer(State.Device, typeof(short), basicTextIn3D.Indices.Length, BufferUsage.None); customMesh.IndexBuffer.SetData(basicTextIn3D.Indices); customMesh.NumberOfVertices = basicTextIn3D.Vertices.Length; customMesh.NumberOfPrimitives = basicTextIn3D.Indices.Length / 3; customMesh.PrimitiveType = basicTextIn3D.PrimitiveType; if (vertices.Count == 0) { throw new GoblinException("Corrupted model vertices. Failed to calculate MBB."); } else { boundingBox = BoundingBox.CreateFromPoints(vertices); boundingSphere = BoundingSphere.CreateFromPoints(vertices); if(offsetTransform.Equals(Matrix.Identity)) offsetTransform.Translation = (boundingBox.Min + boundingBox.Max) / 2; } triangleCount = indices.Count / 3; }
private static CustomMesh CreateBox(Vector3 dimension, Vector2 textCoord) { CustomMesh mesh = new CustomMesh(); // Even though we only need 8 vertices to create a cube/box geometry, because // XNA uses vertex normals instead of face normals, we need 3 duplicate vertices // on each of the 8 corners of the cube/box geometry, so that each of them // can have different normals depending on the face the vertex belongs to. // Also, because we want to texture map as well as illuminate the model with // lights, we use a vertex structure that contains position, normal, and texture // coornidate information. VertexPositionNormalTexture[] vertices = new VertexPositionNormalTexture[24]; Vector3 halfExtent = dimension / 2; // Create 8 vertex positions that will be assigned to those 24 vertices Vector3 v0 = new Vector3(-halfExtent.X, -halfExtent.Y, -halfExtent.Z); Vector3 v1 = new Vector3(halfExtent.X, -halfExtent.Y, -halfExtent.Z); Vector3 v2 = new Vector3(-halfExtent.X, halfExtent.Y, -halfExtent.Z); Vector3 v3 = new Vector3(halfExtent.X, halfExtent.Y, -halfExtent.Z); Vector3 v4 = new Vector3(halfExtent.X, halfExtent.Y, halfExtent.Z); Vector3 v5 = new Vector3(-halfExtent.X, halfExtent.Y, halfExtent.Z); Vector3 v6 = new Vector3(halfExtent.X, -halfExtent.Y, halfExtent.Z); Vector3 v7 = new Vector3(-halfExtent.X, -halfExtent.Y, halfExtent.Z); // Since there are 6 different face directions for a cube/box geometry, // we create 6 normal vectors to assign to the faces Vector3 nZ = new Vector3(0, 0, -1); Vector3 pZ = new Vector3(0, 0, 1); Vector3 nX = new Vector3(-1, 0, 0); Vector3 pX = new Vector3(1, 0, 0); Vector3 nY = new Vector3(0, -1, 0); Vector3 pY = new Vector3(0, 1, 0); Vector2 t0 = new Vector2(0, 0); Vector2 t1 = new Vector2(textCoord.X, 0); Vector2 t2 = new Vector2(0, textCoord.Y); Vector2 t3 = new Vector2(textCoord.X, textCoord.Y); // Assign the 8 positions to the 24 vertices vertices[0].Position = v0; vertices[1].Position = v1; vertices[2].Position = v2; vertices[3].Position = v3; vertices[4].Position = v0; vertices[5].Position = v7; vertices[6].Position = v2; vertices[7].Position = v5; vertices[8].Position = v4; vertices[9].Position = v5; vertices[10].Position = v7; vertices[11].Position = v6; vertices[12].Position = v4; vertices[13].Position = v3; vertices[14].Position = v1; vertices[15].Position = v6; vertices[16].Position = v2; vertices[17].Position = v4; vertices[18].Position = v5; vertices[19].Position = v3; vertices[20].Position = v0; vertices[21].Position = v1; vertices[22].Position = v6; vertices[23].Position = v7; // Assign the texture coordinates to only those faces we care about texture mapping vertices[4].TextureCoordinate = t3; vertices[5].TextureCoordinate = t1; vertices[6].TextureCoordinate = t2; vertices[7].TextureCoordinate = t0; vertices[12].TextureCoordinate = t1; vertices[13].TextureCoordinate = t3; vertices[14].TextureCoordinate = t2; vertices[15].TextureCoordinate = t0; // Assign the appropriate normal vectors to each of the triangle faces for (int i = 0; i < 4; i++) vertices[i].Normal = nZ; for (int i = 4; i < 8; i++) vertices[i].Normal = nX; for (int i = 8; i < 12; i++) vertices[i].Normal = pZ; for (int i = 12; i < 16; i++) vertices[i].Normal = pX; for (int i = 16; i < 20; i++) vertices[i].Normal = pY; for (int i = 20; i < 24; i++) vertices[i].Normal = nY; mesh.VertexDeclaration = VertexPositionNormalTexture.VertexDeclaration; mesh.VertexBuffer = new VertexBuffer(State.Device, typeof(VertexPositionNormalTexture), 24, BufferUsage.None); mesh.VertexBuffer.SetData(vertices); // Since there are 12 triangle faces (6 rectangle faces, and each rectangle face contains // 2 triangle faces), we need 36 indices (12 triangles * 3 vertices/triangle) short[] indices = new short[36]; indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 2; indices[4] = 1; indices[5] = 3; indices[6] = 4; indices[7] = 6; indices[8] = 5; indices[9] = 6; indices[10] = 7; indices[11] = 5; indices[12] = 11; indices[13] = 10; indices[14] = 9; indices[15] = 11; indices[16] = 9; indices[17] = 8; indices[18] = 14; indices[19] = 15; indices[20] = 13; indices[21] = 15; indices[22] = 12; indices[23] = 13; indices[24] = 19; indices[25] = 17; indices[26] = 18; indices[27] = 19; indices[28] = 18; indices[29] = 16; indices[30] = 21; indices[31] = 20; indices[32] = 23; indices[33] = 21; indices[34] = 23; indices[35] = 22; mesh.IndexBuffer = new IndexBuffer(State.Device, typeof(short), 36, BufferUsage.None); mesh.IndexBuffer.SetData(indices); mesh.NumberOfVertices = 24; mesh.NumberOfPrimitives = 12; return mesh; }