public Cylinder(int numSides) { VertexPNTTI[] vertices = new VertexPNTTI[numSides * 2]; int deltaTheta = 360 / numSides; float deltaTCX = 1.0f / (float)(numSides-1); for (int i = 0; i < numSides; i++) { float a = MathHelper.ToRadians(deltaTheta * i); Vector3 pos = new Vector3((float)Math.Cos(a), 0, (float)Math.Sin(a)); int index = i * 2; vertices[index].Position = pos; vertices[index].Texcoord = new Vector3(i * deltaTCX, 0, 1); //vertices[index].Normal += vertices[index + 1].Position = pos + Vector3.Up; vertices[index + 1].Texcoord = new Vector3(i * deltaTCX, 1, 1); } /* vertices[numSides * 2].Position = new Vector4(Vector3.Up * -1, 1.0f); vertices[numSides * 2 + 1].Position = new Vector4(Vector3.Up, 1.0f); */ ushort[] indices = new ushort[6 * numSides]; for (int i = 0; i < numSides; i++) { int index = i*6; int indexVert = i*2; indices[index] = (ushort)(indexVert + 1); indices[index + 1] = (ushort)indexVert; indices[index + 2] = (ushort)(indexVert + 2); indices[index + 3] = (ushort)(indexVert + 2); indices[index + 4] = (ushort)(indexVert + 3); indices[index + 5] = (ushort)(indexVert + 1); if (i == numSides - 1) { indices[index + 2] = (ushort)0; indices[index + 4] = (ushort)1; indices[index + 3] = (ushort)0; } } vertexBuffer = new VertexBuffer(GFX.Device, vertices.Length * VertexPNTTI.SizeInBytes, BufferUsage.WriteOnly); vertexBuffer.SetData<VertexPNTTI>(vertices); vertexCount = vertices.Length; indexBuffer = new IndexBuffer(GFX.Device, sizeof(ushort) * indices.Length, BufferUsage.WriteOnly, IndexElementSize.SixteenBits); indexBuffer.SetData<ushort>(indices); primitiveCount = indices.Length / 3; CreateInstancedBuffers(vertices, indices); }
void CreateInstancedBuffers(VertexPNTTI[] verts, ushort[] ib) { VertexPNTTI[] instVerts = new VertexPNTTI[verts.Length * GFXShaderConstants.NUM_INSTANCES]; for (int i = 0; i < GFXShaderConstants.NUM_INSTANCES; i++) { for (int j = 0; j < verts.Length; j++) { instVerts[i * verts.Length + j] = new VertexPNTTI(verts[j].Position, verts[j].Normal, verts[j].Texcoord, verts[j].Tangent, i); } } ushort[] instIB = new ushort[ib.Length * GFXShaderConstants.NUM_INSTANCES]; for (int i = 0; i < GFXShaderConstants.NUM_INSTANCES; i++) { for (int j = 0; j < ib.Length; j++) { instIB[i * ib.Length + j] = (ushort)(ib[j] + i * verts.Length); } } vertexBufferInstanced = new VertexBuffer(GFX.Device, instVerts.Length * VertexPNTTI.SizeInBytes, BufferUsage.None); vertexBufferInstanced.SetData<VertexPNTTI>(instVerts); indexBufferInstanced = new IndexBuffer(GFX.Device, sizeof(ushort) * instIB.Length, BufferUsage.None, IndexElementSize.SixteenBits); indexBufferInstanced.SetData<ushort>(instIB); }
/* public void Render(Matrix transform, SortedList<string, AnimationNode> animNodes, RenderView view, bool performCulling) { if (performCulling) { BoundingFrustum frustum = view.GetFrustum(); Matrix oldMat = frustum.Matrix; frustum.Matrix = transform * view.GetViewProjection(); Matrix[] transforms = new Matrix[nodes.Length]; for (int i = 0; i < nodes.Length; i++) transforms[i] = animNodes[nodes[i].Name].Transform; for (int i = 0; i < parts.Length; i++) { if (frustum.Contains(parts[i].bounds) != ContainmentType.Disjoint) { RenderElement element = parts[i].renderElement; element.Transform = transforms; element.IsAnimated = true; view.AddElement(parts[i].material, element); } } frustum.Matrix = oldMat; } else { Matrix[] transforms = new Matrix[nodes.Length]; for (int i = 0; i < nodes.Length; i++) transforms[i] = animNodes[nodes[i].Name].Transform; for (int i = 0; i < parts.Length; i++) { RenderElement element = parts[i].renderElement; element.Transform = transforms; element.IsAnimated = true; view.AddElement(parts[i].material, element); } } } */ void CreateInstanceData() { /* instanceTemp = new Vector4[GFXShaderConstants.INSTANCE_TEXTURE_SIZE*GFXShaderConstants.INSTANCE_TEXTURE_SIZE * 3]; instanceCount = 0; for (int i = 0; i < instanceTexture.Length; i++) instanceTexture[i] = new Texture2D(GFX.Device, GFXShaderConstants.INSTANCE_TEXTURE_SIZE, GFXShaderConstants.INSTANCE_TEXTURE_SIZE, 1, TextureUsage.None, SurfaceFormat.Vector4); */ VertexPNTTI[] vertData = new VertexPNTTI[vertexCount]; vertexBuffer.GetData<VertexPNTTI>(vertData); VertexPNTTI[] instVerts = new VertexPNTTI[vertexCount * GFXShaderConstants.NUM_INSTANCES]; for (int i = 0; i < GFXShaderConstants.NUM_INSTANCES; i++) { for (int j = 0; j < vertexCount; j++) { int index = i * vertexCount + j; instVerts[index] = vertData[j]; instVerts[index].Index = i; } } vertexBufferInstanced = new VertexBuffer(GFX.Device, instVerts.Length * VertexPNTTI.SizeInBytes, BufferUsage.None); vertexBufferInstanced.SetData<VertexPNTTI>(instVerts); for (int i = 0; i < parts.Length; i++) { parts[i].renderElementInstanced = parts[i].renderElement; IndexElementSize elementSize = parts[i].renderElement.IndexBuffer.IndexElementSize; IndexBuffer indexBufferInstanced; if (instVerts.Length > ushort.MaxValue) elementSize = IndexElementSize.ThirtyTwoBits; if (elementSize == IndexElementSize.SixteenBits) { ushort[] indexData = new ushort[parts[i].renderElement.PrimitiveCount * 3]; parts[i].renderElement.IndexBuffer.GetData<ushort>(indexData); ushort[] instIB = new ushort[indexData.Length * GFXShaderConstants.NUM_INSTANCES]; for (int k = 0; k < GFXShaderConstants.NUM_INSTANCES; k++) { for (int j = 0; j < indexData.Length; j++) { int newIndex = indexData[j] + k * vertexCount; if (newIndex > ushort.MaxValue) Console.WriteLine("This is very very bad!"); instIB[k * indexData.Length + j] = (ushort)newIndex; } } indexBufferInstanced = new IndexBuffer(GFX.Device, sizeof(ushort) * instIB.Length, BufferUsage.None, elementSize); indexBufferInstanced.SetData<ushort>(instIB); } else { ushort[] indexData = new ushort[parts[i].renderElement.PrimitiveCount * 3]; parts[i].renderElement.IndexBuffer.GetData<ushort>(indexData); uint[] instIB = new uint[indexData.Length * GFXShaderConstants.NUM_INSTANCES]; for (int k = 0; k < GFXShaderConstants.NUM_INSTANCES; k++) { for (int j = 0; j < indexData.Length; j++) { ulong index = (ulong)indexData[j] + (ulong)k * (ulong)vertexCount; if (index > ulong.MaxValue) Console.WriteLine("This is very very bad!"); instIB[k * indexData.Length + j] = (uint)(indexData[j] + k * vertexCount); } } indexBufferInstanced = new IndexBuffer(GFX.Device, sizeof(uint) * instIB.Length, BufferUsage.None, elementSize); indexBufferInstanced.SetData<uint>(instIB); } parts[i].renderElementInstanced.VertexDec = GFXVertexDeclarations.PNTTIDec; parts[i].renderElementInstanced.VertexStride = VertexPNTTI.SizeInBytes; parts[i].renderElementInstanced.IsAnimated = false; parts[i].renderElementInstanced.VertexBuffer = vertexBufferInstanced; parts[i].renderElementInstanced.IndexBuffer = indexBufferInstanced; } }
void LoadMS3D(string filename) { using (FileStream fs = new FileStream(filename, FileMode.Open)) { using (BinaryReader br = new BinaryReader(fs, System.Text.Encoding.Default)) { br.ReadChars(10); br.ReadInt32(); vertexCount = br.ReadUInt16(); ModelVertex[] vertices = new ModelVertex[vertexCount]; Vector3 minVert = Vector3.One * float.PositiveInfinity; Vector3 maxVert = Vector3.One * float.NegativeInfinity; for (int i = 0; i < vertexCount; i++) { br.ReadByte(); vertices[i].Position = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); minVert = Vector3.Min(minVert, vertices[i].Position); maxVert = Vector3.Max(maxVert, vertices[i].Position); vertices[i].BoneIndex = (int)br.ReadChar(); if (vertices[i].BoneIndex >= 255) vertices[i].BoneIndex = 0; vertices[i].Weight = 1; br.ReadByte(); } ushort triangleCount = br.ReadUInt16(); Triangle[] triList = new Triangle[triangleCount]; for (int i = 0; i < triangleCount; i++) { br.ReadUInt16(); //flag //Indices ushort v0 = br.ReadUInt16(); ushort v1 = br.ReadUInt16(); ushort v2 = br.ReadUInt16(); triList[i].vertex0 = v0; triList[i].vertex1 = v1; triList[i].vertex2 = v2; //Vertex 0 Normal vertices[v0].Normal += new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); //Vertex 1 Normal vertices[v1].Normal += new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); //Vertex 2 Normal vertices[v2].Normal += new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); //U vertices[v0].TexCoord.X = br.ReadSingle(); vertices[v1].TexCoord.X = br.ReadSingle(); vertices[v2].TexCoord.X = br.ReadSingle(); //V vertices[v0].TexCoord.Y = br.ReadSingle(); vertices[v1].TexCoord.Y = br.ReadSingle(); vertices[v2].TexCoord.Y = br.ReadSingle(); vertices[v0].Weight++; vertices[v1].Weight++; vertices[v2].Weight++; //Smoothing br.ReadByte(); //Group index br.ReadByte(); } for (int i = 0; i < vertexCount; i++) { vertices[i].Normal /= vertices[i].Weight; vertices[i].Weight = 1; } for (int i = 0; i < triangleCount; i++) { vertices[triList[i].vertex0].AddTangent(vertices[triList[i].vertex1], vertices[triList[i].vertex2]); vertices[triList[i].vertex1].AddTangent(vertices[triList[i].vertex0].Tangent, vertices[triList[i].vertex0].Tangent2); vertices[triList[i].vertex2].AddTangent(vertices[triList[i].vertex0].Tangent, vertices[triList[i].vertex0].Tangent2); //vertices[triList[i].vertex1].AddTangent(vertices[triList[i].vertex0], vertices[triList[i].vertex2]); //vertices[triList[i].vertex2].AddTangent(vertices[triList[i].vertex0], vertices[triList[i].vertex1]); } VertexPNTTI[] verts = new VertexPNTTI[vertexCount]; for (int i = 0; i < vertexCount; i++) { Vector3 N = vertices[i].Normal; N.Normalize(); Vector3 tangent = vertices[i].Tangent / vertices[i].Weight; tangent = (tangent - N * Vector3.Dot(N, tangent)); tangent.Normalize(); vertices[i].Tangent = tangent; vertices[i].Tangent2 /= vertices[i].Weight; vertices[i].Weight = 1; float binormSign = (Vector3.Dot(Vector3.Cross(N, tangent), vertices[i].Tangent2) < 0.0f) ? -1.0f : 1.0f; verts[i] = new VertexPNTTI(vertices[i].Position, vertices[i].Normal, vertices[i].TexCoord, vertices[i].Tangent, vertices[i].BoneIndex, binormSign); } vertexBuffer = new VertexBuffer(GFX.Device, vertexCount * VertexPNTTI.SizeInBytes, BufferUsage.None); vertexBuffer.SetData<VertexPNTTI>(verts); ushort groupCount = br.ReadUInt16(); parts = new ModelPart[groupCount]; int[] matIndices = new int[groupCount]; for (int i = 0; i < groupCount; i++) { br.ReadByte(); parts[i] = new ModelPart(); parts[i].name = new string(br.ReadChars(32)); //Group Name parts[i].name = parts[i].name.Replace("\0",string.Empty); ushort numTriangles = br.ReadUInt16(); //numTriangles parts[i].renderElement = new RenderElement(); parts[i].renderElement.PrimitiveCount = numTriangles; parts[i].renderElement.StartVertex = 0; parts[i].renderElement.VertexBuffer = vertexBuffer; parts[i].renderElement.VertexCount = vertexCount; parts[i].renderElement.VertexStride = VertexPNTTI.SizeInBytes; parts[i].renderElement.VertexDec = GFXVertexDeclarations.PNTTIDec; parts[i].bounds.Max = Vector3.Zero; parts[i].bounds.Min = Vector3.Zero; bool useIntIndices = (numTriangles >= ushort.MaxValue); IndexElementSize size = (useIntIndices) ? IndexElementSize.ThirtyTwoBits : IndexElementSize.SixteenBits; int stride = (useIntIndices) ? sizeof(uint) : sizeof(ushort); parts[i].renderElement.IndexBuffer = new IndexBuffer(GFX.Device, stride * numTriangles * 3, BufferUsage.None, size); List<ushort> ushortIndices = new List<ushort>(); List<uint> uintIndices = new List<uint>(); for (int l = 0; l < numTriangles; l++) { ushort t = br.ReadUInt16(); //triangle index if (useIntIndices) { uintIndices.Add((uint)triList[t].vertex2); uintIndices.Add((uint)triList[t].vertex1); uintIndices.Add((uint)triList[t].vertex0); } else { ushortIndices.Add((ushort)triList[t].vertex2); ushortIndices.Add((ushort)triList[t].vertex1); ushortIndices.Add((ushort)triList[t].vertex0); } parts[i].bounds.Max = Vector3.Max(parts[i].bounds.Max, vertices[triList[t].vertex0].Position); parts[i].bounds.Max = Vector3.Max(parts[i].bounds.Max, vertices[triList[t].vertex1].Position); parts[i].bounds.Max = Vector3.Max(parts[i].bounds.Max, vertices[triList[t].vertex2].Position); parts[i].bounds.Min = Vector3.Min(parts[i].bounds.Min, vertices[triList[t].vertex0].Position); parts[i].bounds.Min = Vector3.Min(parts[i].bounds.Min, vertices[triList[t].vertex1].Position); parts[i].bounds.Min = Vector3.Min(parts[i].bounds.Min, vertices[triList[t].vertex2].Position); } if (useIntIndices) parts[i].renderElement.IndexBuffer.SetData<uint>(uintIndices.ToArray()); else parts[i].renderElement.IndexBuffer.SetData<ushort>(ushortIndices.ToArray()); matIndices[i] = (int)br.ReadChar(); //Material index } meshBounds = new BoundingBox(parts[0].bounds.Min, parts[0].bounds.Max); for (int i = 1; i < parts.Length; i++) { meshBounds.Min = Vector3.Min(parts[i].bounds.Min, meshBounds.Min); meshBounds.Max = Vector3.Max(parts[i].bounds.Max, meshBounds.Max); } ushort MaterialCount = br.ReadUInt16(); string[] materialNames = new string[MaterialCount]; for (int i = 0; i < MaterialCount; i++) { materialNames[i] = new string(br.ReadChars(32)); materialNames[i] = materialNames[i].Replace("\0", string.Empty); for (int l = 0; l < 4; l++) br.ReadSingle(); for (int l = 0; l < 4; l++) br.ReadSingle(); for (int l = 0; l < 4; l++) br.ReadSingle(); for (int l = 0; l < 4; l++) br.ReadSingle(); br.ReadSingle(); br.ReadSingle(); br.ReadChar(); br.ReadChars(128); br.ReadChars(128); } CheckMissingMaterials(filename, matIndices, materialNames); for (int i = 0; i < groupCount; i++) { int matIndex = matIndices[i]; if (matIndex < 255) parts[i].material = ResourceManager.Inst.GetMaterial(materialNames[matIndex]); if (parts[i].material == null) parts[i].material = ResourceManager.Inst.GetMaterial("NULL"); } float fps = br.ReadSingle();//FPS br.ReadSingle();//current time int frameCount = br.ReadInt32(); //Total frames ushort boneCount = br.ReadUInt16(); nodes = new AnimationNode[boneCount]; if (boneCount > 0) { List<string> nodeParentNames = new List<string>(); for (int i = 0; i < boneCount; i++) { br.ReadByte(); //flag string name = new string(br.ReadChars(32)).Replace("\0", ""); string parentName = new string(br.ReadChars(32)).Replace("\0", ""); nodeParentNames.Add(parentName); Vector3 rotation = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Vector3 position = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); nodes[i] = new AnimationNode(name, position, rotation); namesToNodes.Add(name, nodes[i]); ushort keyRotCount = br.ReadUInt16(); //Key frame rot count ushort keyPosCount = br.ReadUInt16(); //Key frame pos count //nodes[i].rotationFrames = new ModelBoneAnimationFrame[keyRotCount]; //nodes[i].translationFrames = new ModelBoneAnimationFrame[keyPosCount]; /* for (int j = 0; j < keyRotCount; j++) { nodes[i].rotationFrames[j].time = br.ReadSingle() * fps; //time nodes[i].rotationFrames[j].Displacement = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); nodes[i].rotationFrames[j].boneName = name; } for (int j = 0; j < keyPosCount; j++) { nodes[i].translationFrames[j].time = br.ReadSingle() * fps; //time nodes[i].translationFrames[j].Displacement = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); nodes[i].translationFrames[j].boneName = name; }*/ int count = (keyRotCount + keyPosCount) * 4; for (int j = 0; j < count; j++) br.ReadSingle(); } List<AnimationNode> rootNodeList = new List<AnimationNode>(); for (int i = 0; i < nodes.Length; i++) { if (namesToNodes.ContainsKey(nodeParentNames[i])) { AnimationNode node = namesToNodes[nodeParentNames[i]]; node.children.Add(nodes[i]); } else rootNodeList.Add(nodes[i]); } rootNodes = rootNodeList.ToArray(); for (int i = 0; i < rootNodes.Length; i++) { Matrix identityMat = Matrix.Identity; rootNodes[i].ApplyTransform(ref identityMat); } Matrix[] inverseMats = new Matrix[nodes.Length]; Matrix[] invRotMats = new Matrix[nodes.Length]; for (int i = 0; i < inverseMats.Length; i++) { inverseMats[i] = Matrix.Invert(nodes[i].Transform); invRotMats[i] = MathUtils.Invert3x3(nodes[i].Transform); } if (nodesAreAnimated) { for (int i = 0; i < verts.Length; i++) { verts[i].Position = Vector3.Transform(verts[i].Position, inverseMats[(int)verts[i].Index]); verts[i].Normal = Vector3.TransformNormal(verts[i].Normal, inverseMats[(int)verts[i].Index]); verts[i].Tangent = Vector3.TransformNormal(verts[i].Tangent, inverseMats[(int)verts[i].Index]); } } vertexBuffer.SetData<VertexPNTTI>(verts); for (int i = 0; i < nodes.Length; i++) { Vector3 Rotation = nodes[i].Rotation; Matrix transform = Matrix.CreateRotationX(Rotation.X) * Matrix.CreateRotationY(Rotation.Y) * Matrix.CreateRotationZ(Rotation.Z); transform.Translation = nodes[i].Translation; nodes[i].Transform = transform; } } } } }
void CreateCollisionMesh(ModelPart collisionMesh) { SortedList<ushort, ushort> renamedVertexIndices = new SortedList<ushort, ushort>(); SortedList<ushort, ushort> renamedVertexIndicesCollision = new SortedList<ushort, ushort>(); RenderElement collisionElem = collisionMesh.renderElement; List<Vector3> collisionVerts = new List<Vector3>(); List<TriangleVertexIndices> collisionIndices = new List<TriangleVertexIndices>(collisionElem.PrimitiveCount); VertexPNTTI[] vertexData = new VertexPNTTI[vertexCount]; vertexBuffer.GetData<VertexPNTTI>(vertexData); ushort[] indexDataCollision = new ushort[collisionElem.PrimitiveCount * 3]; collisionElem.IndexBuffer.GetData<ushort>(indexDataCollision); for (int i = 0; i < collisionElem.PrimitiveCount; i++) { int index = i * 3; for(int j = 0; j < 3; j++) { ushort currIdx = indexDataCollision[index + j]; if(!renamedVertexIndicesCollision.ContainsKey(currIdx)) { renamedVertexIndicesCollision.Add(currIdx, (ushort)collisionVerts.Count); Vector3 pos; pos.X = vertexData[currIdx].Position.X; pos.Y = vertexData[currIdx].Position.Y; pos.Z = vertexData[currIdx].Position.Z; collisionVerts.Add(pos); } } ushort idx0 = indexDataCollision[index + 0]; ushort idx1 = indexDataCollision[index + 1]; ushort idx2 = indexDataCollision[index + 2]; collisionIndices.Add(new TriangleVertexIndices(renamedVertexIndicesCollision[idx2], renamedVertexIndicesCollision[idx1], renamedVertexIndicesCollision[idx0])); } /* this.collisionMesh = new TriangleMesh(); this.collisionMesh.CreateMesh(collisionVerts, collisionIndices, 0, 0); */ this.collisionMesh = new TriangleMesh(collisionVerts, collisionIndices); List<VertexPNTTI> newVertexData = new List<VertexPNTTI>(); for (int i = 0; i < parts.Length; i++) { RenderElement currElem = parts[i].renderElement; ushort[] indexData = new ushort[currElem.PrimitiveCount * 3]; currElem.IndexBuffer.GetData<ushort>(indexData); for (int j = 0; j < indexData.Length; j++) { if (!renamedVertexIndices.ContainsKey(indexData[j])) { renamedVertexIndices.Add(indexData[j], (ushort)newVertexData.Count); newVertexData.Add(vertexData[indexData[j]]); } indexData[j] = renamedVertexIndices[indexData[j]]; } currElem.IndexBuffer.SetData<ushort>(indexData); } vertexBuffer.Dispose(); vertexCount = newVertexData.Count; vertexBuffer = new VertexBuffer(GFX.Device, VertexPNTTI.SizeInBytes * newVertexData.Count, BufferUsage.None); vertexBuffer.SetData<VertexPNTTI>(newVertexData.ToArray()); for (int i = 0; i < parts.Length; i++) parts[i].renderElement.VertexBuffer = vertexBuffer; }