public void CanInitializePropertiesByConstructor() { SubMesh subMesh = new SubMesh(); Assert.That(subMesh.Faces, Is.Not.Null.And.Empty); Assert.That(subMesh.Normals, Is.Not.Null.And.Empty); Assert.That(subMesh.Textures, Is.Not.Null.And.Empty); Assert.That(subMesh.Vertices, Is.Not.Null.And.Empty); }
// Use this for initialization void Start() { this.block = this.GetComponent<BlockObject>(); if ( block != null ) { var mesh = this.GetComponentInChildren<MeshFilter>(); if ( meshLookup.ContainsKey(mesh.sharedMesh) == false ) { SubMesh[] subMesh = new SubMesh[6]; Vector3[] directions = new Vector3[]{ Vector3.up, Vector3.down, Vector3.left, Vector3.right, Vector3.forward, Vector3.back}; for ( int i = 0; i < directions.Length; i++ ) { subMesh[i] = new SubMesh(); List<int> triangles = new List<int>(); for ( int t = 0; t < mesh.sharedMesh.triangles.Length; t+=3) { int indexA = mesh.sharedMesh.triangles[t+0]; int indexB = mesh.sharedMesh.triangles[t+1]; int indexC = mesh.sharedMesh.triangles[t+2]; Vector3 a = mesh.sharedMesh.vertices[indexA]; Vector3 b = mesh.sharedMesh.vertices[indexB]; Vector3 c = mesh.sharedMesh.vertices[indexC]; Vector3 normal = Vector3.Cross( (c-a), (c-b)); float angle = Vector3.Angle(directions[i], normal); if ( Mathf.Approximately( angle, 0) ) { triangles.Add( indexA); triangles.Add( indexB); triangles.Add( indexC); } } subMesh[i].triangles = triangles.ToArray(); meshLookup[mesh.sharedMesh] = subMesh; } } SubMesh[] submesh = meshLookup[mesh.sharedMesh]; mesh.mesh.triangles = submesh[4].triangles; } }
public MeshBuilderHelper(String name, String resourcegroup, bool usesharedvertices, uint vertexstart, uint vertexcount) { mName = name; mResourceGroup = resourcegroup; mVertextStart = vertexstart; mVertexCount = vertexcount; if (MeshManager.Singleton.ResourceExists(name)) throw (new ArgumentNullException("mesh name already used")); mMeshPtr = MeshManager.Singleton.CreateManual(mName, mResourceGroup); mSubMesh = mMeshPtr.CreateSubMesh(); mSubMesh.useSharedVertices = usesharedvertices; mSubMesh.vertexData = new VertexData(); mSubMesh.vertexData.vertexStart = mVertextStart; mSubMesh.vertexData.vertexCount = mVertexCount; offset = 0; mIndexType = HardwareIndexBuffer.IndexType.IT_16BIT; }
// public Item( SubMesh subMesh ) { this.subMesh = subMesh; subMesh.GetSomeGeometry( out positions, out indices ); Bounds bounds = Bounds.Cleared; foreach( Vec3 pos in positions ) bounds.Add( pos ); bounds.Expand( bounds.GetSize() * .001f ); OctreeContainer.InitSettings initSettings = new OctreeContainer.InitSettings(); initSettings.InitialOctreeBounds = bounds; initSettings.OctreeBoundsRebuildExpand = Vec3.Zero; initSettings.MinNodeSize = bounds.GetSize() / 50; octreeContainer = new OctreeContainer( initSettings ); for( int nTriangle = 0; nTriangle < indices.Length / 3; nTriangle++ ) { Vec3 vertex0 = positions[ indices[ nTriangle * 3 + 0 ] ]; Vec3 vertex1 = positions[ indices[ nTriangle * 3 + 1 ] ]; Vec3 vertex2 = positions[ indices[ nTriangle * 3 + 2 ] ]; Bounds triangleBounds = new Bounds( vertex0 ); triangleBounds.Add( vertex1 ); triangleBounds.Add( vertex2 ); int octreeIndex = octreeContainer.AddObject( triangleBounds, 1 ); } }
public void Rebuild() { if (!IsValid()) { Debug.LogError("The card definition is not valid. " + this.name); return; } Stock.Validate(); Dictionary <Texture2D, SubMesh> table = new Dictionary <Texture2D, SubMesh>(); CardMesh card = new CardMesh(); CardShape paper = Definition.Atlas.FindById(Definition.Stock.Paper); if (paper == null) { Debug.LogError("Paper does not exist in atlas = " + Definition.Atlas.name + "::" + Definition.Stock.Paper); return; } SubMesh data = GetMesh(card, table, paper); float x = Stock.Size.x * Stock.Scale / 2; float y = Stock.Size.y * Stock.Scale / 2; float bx = Mathf.Max(Stock.CornerSize, Stock.Border.x) * Stock.Scale; float by = Mathf.Max(Stock.CornerSize, Stock.Border.y) * Stock.Scale; //float cx = x-bx; //float cy = y-by; // 4 5 // B 0 1 6 // C D // A 3 2 7 // 9 8 float crad = Stock.CornerSize; Vector2 cxy = new Vector2(crad, crad); Vector3[] v = RectPoints(Stock.Size * Stock.Scale, Stock.Scale * cxy); Vector3 c0 = new Vector3(-x + bx, +y - by, 0); Vector3 c1 = new Vector3(+x - bx, +y - by, 0); Vector3 c2 = new Vector3(+x - bx, -y + by, 0); Vector3 c3 = new Vector3(-x + bx, -y + by, 0); if (Stock.Smooth > 0) { // middle Square4(data, paper, v[0], v[1], v[2], v[3], Color.white, false, false); // top Square4(data, paper, v[4], v[5], v[1], v[0], Color.white, false, false); // right Square4(data, paper, v[1], v[6], v[7], v[2], Color.white, false, false); // bottom Square4(data, paper, v[3], v[2], v[8], v[9], Color.white, false, false); // left Square4(data, paper, v[11], v[0], v[3], v[10], Color.white, false, false); BuildCorner3(data, paper, v[0], v[11], v[4]); BuildCorner3(data, paper, v[1], v[5], v[6]); BuildCorner3(data, paper, v[2], v[7], v[8]); BuildCorner3(data, paper, v[3], v[9], v[10]); } else // simple rectangle { Vector3 p1 = new Vector3(-x, +y, 0); Vector3 p2 = new Vector3(+x, +y, 0); Vector3 p3 = new Vector3(+x, -y, 0); Vector3 p4 = new Vector3(-x, -y, 0); Square4(data, paper, p1, p2, p3, p4, Color.white, false, false); } Vector2 textSize = Stock.TextSize * Stock.Scale; float s1 = Stock.BigSymbolSize * Stock.Scale; float s2 = Stock.SymbolSize * Stock.Scale; float s3 = Stock.CornerSymbolSize * Stock.Scale; //float symW = s2; //float symH = s2; //float rimX = Mathf.Max(textSize.x,symW); //float rimY = Mathf.Max(textSize.y,symH); CardShape symbol = Atlas.FindById(Definition.Symbol); if (symbol == null && !string.IsNullOrEmpty(Definition.Symbol)) { Debug.LogError(string.Format("Symbol shape '{0}' is not defined in atlas.", Definition.Symbol)); } // Full Image is used by cards like ACE/JOKER that might want a fully unique face image // Half Image is used by cards like JQK where half image is flipped and reflected for the top/bottom of the face image // Pattern is used to form standard layout of suit symbols for 2-10 cards CardShape fullImage = Definition.FullImage ? Atlas.FindById(Definition.Image) : null; CardShape halfImage = !Definition.FullImage ? Atlas.FindById(Definition.Image) : null; if (fullImage != null) { SubMesh core = GetMesh(card, table, fullImage); //Square4 (core,fullImage,v[0],v[1],v[2],v[3],Color.white,false,false); Square4(core, fullImage, c0, c1, c2, c3, Color.white, false, false); } else if (halfImage != null) { SubMesh core = GetMesh(card, table, halfImage); Vector3 lift = new Vector3(0, 0, -0.01f); Square4(core, halfImage, v[0] + lift, v[1] + lift, v[13] + lift, v[12] + lift, Color.white, false, false); Square4(core, halfImage, v[12] + lift, v[13] + lift, v[2] + lift, v[3] + lift, Color.white, true, true); } else if (Definition.Pattern != 0 && symbol != null) { if (Definition.Pattern >= 1 && Definition.Pattern < patternBits.Length) { SubMesh core = GetMesh(card, table, symbol); int bits = patternBits[Definition.Pattern]; float x0 = -x + bx; float x1 = +x - bx; float y0 = +y - by; float y1 = -y + by; for (int b = 0; b < 17; b++) { if ((bits & (1 << b)) != 0) { float px = Mathf.Lerp(x0, x1, patternPos[b].x); float py = Mathf.Lerp(y0, y1, patternPos[b].y); Vector2 symSize = (Definition.Pattern == 1) ? new Vector2(s1, s1) : new Vector2(s2, s2); if (Stock.AlwaysUpright || patternUpper[b]) { Square(core, symbol, new Vector3(px, py, -0.01f), symSize, Color.white); } else { SquareFlip(core, symbol, new Vector3(px, py, -0.01f), symSize, Color.white, true, true); } } } } else { Debug.LogError(string.Format("Pattern value '{0}' is not valid.", Definition.Pattern)); } } // Text is used for number/letter in corner of card (ex. A for Ace) CardShape text = Atlas.FindById(Definition.Text); if (text == null && !string.IsNullOrEmpty(Definition.Text)) { Debug.LogError(string.Format("Text shape '{0}' is not defined in atlas.", Definition.Text)); } if (text != null) { float tx = Stock.TextOffset.x * Stock.Scale; float ty = Stock.TextOffset.y * Stock.Scale; SubMesh sub = GetMesh(card, table, text); float x0 = -x + tx; // + (bx+rimX)*0.5f; float x1 = +x - tx; // - (bx+rimX)*0.5f; float y0 = +y - ty; //by; float y1 = -y + ty; //by; Color color = GetSymbolColor(Definition.Symbol); Square(sub, text, new Vector3(x0, y0, -0.01f), textSize, color); if (Stock.AlwaysUpright) { Square(sub, text, new Vector3(x1, y1, -0.01f), textSize, color); } else { SquareFlip(sub, text, new Vector3(x1, y1, -0.01f), textSize, color, true, true); } } // Symbol is used for corner suit icons (heart,diamond,spade,club) if (symbol != null) { float sx = Stock.SymbolOffset.x * Stock.Scale; float sy = Stock.SymbolOffset.y * Stock.Scale; SubMesh sub = GetMesh(card, table, symbol); //float gapY = s3/3; float x0 = -x + sx; //(bx+rimX)*0.5f; float x1 = +x - sx; //(bx+rimX)*0.5f; float y0 = +y - sy; //by - textSize.y - gapY - rad; float y1 = -y + sy; //by + textSize.y + gapY + rad; Color color = GetSymbolColor(Definition.Symbol); Vector2 halfSym = new Vector2(s3, s3); // Top-left corner symbol Square(sub, symbol, new Vector3(x0, y0, -0.01f), halfSym, color); // Bottom-right symbol can be up-right or upside-down depending on preferences if (Stock.AlwaysUpright) { Square(sub, symbol, new Vector3(x1, y1, -0.01f), halfSym, color); } else { SquareFlip(sub, symbol, new Vector3(x1, y1, -0.01f), halfSym, color, true, true); } } if (Stock.TwoSided) { BuildBack(card, table, paper); /* * CardShape back = Atlas.FindById(Stock.Back); * if (back != null) * { * Vector3 [] v = RectPoints(Stock.Size*Stock.Scale,Stock.BackBorder*Stock.Scale); * * SubMesh core = GetMesh(card,table,back); * // middle * if (Stock.HalfBack) * { * Square4(core,back,v[1],v[0],v[12],v[13],Color.white,false,false); * Square4(core,back,v[13],v[12],v[3],v[2],Color.white,true,true); * } * else * { * Square4(core,back,v[1],v[0],v[3],v[2],Color.white,false,false); * } * // top * Square4(core,paper,v[5],v[4],v[0],v[1],Color.white,false,false); * // back-left * Square5(core,paper,v[2],v[7],v[6],v[1],v[13],Color.white,false); * // bottom * Square4(core,paper,v[2],v[3],v[9],v[8],Color.white,false,false); * // back-right * Square5(core,paper,v[0],v[11],v[10],v[3],v[12],Color.white,false); * * BuildCorner3(core, paper, v[1],v[6],v[5]); * BuildCorner3(core, paper, v[2],v[8],v[7]); * BuildCorner3(core, paper, v[3],v[10],v[9]); * BuildCorner3(core, paper, v[0],v[4],v[11]); * } */ } Mesh mesh = SetupMesh(); mesh.vertices = card.GetCombinedVertices().ToArray(); mesh.triangles = data.IndexList.ToArray(); mesh.uv = card.GetCombinedTexCoords().ToArray(); mesh.colors = card.GetCombinedColors().ToArray(); if (card.MeshList.Count > 1) { mesh.subMeshCount = card.MeshList.Count; int vbase = 0; for (int i = 1; i < card.MeshList.Count; ++i) { SubMesh sub = card.MeshList[i]; int[] tris = sub.IndexList.ToArray(); vbase += card.MeshList[i - 1].VertexList.Count; for (int t = 0; t < tris.Length; ++t) { tris[t] += vbase; } mesh.SetTriangles(tris, i); } } mesh.RecalculateBounds(); mesh.Optimize(); mesh.RecalculateNormals(); this.GetComponent <Renderer>().sharedMaterials = card.Materials.ToArray(); // Setup Collider this.gameObject.AddComponent <BoxCollider2D>(); // Mark as not clicked this.Clicked = false; }
private void VerticesToOutline(List <Vector2f[]> outlines, Vector3f[] vertices, SubMesh submesh) { int triangleCount = submesh.IndexCount / 3; List <Vector3i> triangles = new List <Vector3i>(triangleCount); using (MemoryStream memStream = new MemoryStream(m_indexBuffer)) { using (BinaryReader reader = new BinaryReader(memStream)) { memStream.Position = submesh.FirstByte; for (int i = 0; i < triangleCount; i++) { int x = reader.ReadInt16(); int y = reader.ReadInt16(); int z = reader.ReadInt16(); triangles.Add(new Vector3i(x, y, z)); } } } MeshOutlineGenerator outlineGenerator = new MeshOutlineGenerator(vertices, triangles); List <Vector2f[]> outline = outlineGenerator.GenerateOutlines(); outlines.AddRange(outline); }
public override void DoPostProcess() { base.DoPostProcess(); shaders = new shader[gbxmodelValues.Shaders.Count]; for (int i = 0; i < shaders.Length; i++) { shaders[i] = OpenShader(gbxmodelValues.Shaders[i].Shader.Value, gbxmodelValues.Shaders[i].Shader.TagGroup); } meshes = new EnhancedMesh[gbxmodelValues.Geometries.Count][]; for (int i = 0; i < meshes.Length; i++) { meshes[i] = new EnhancedMesh[gbxmodelValues.Geometries[i].Parts.Count]; for (int j = 0; j < meshes[i].Length; j++) { ushort[] strip = new ushort[gbxmodelValues.Geometries[i].Parts[j].Triangles.Count * 3]; Vertex[] vertices = new Vertex[gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices.Count]; for (int k = 0; k < vertices.Length; k++) { vertices[k].position.X = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Position.X; vertices[k].position.Y = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Position.Y; vertices[k].position.Z = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Position.Z; vertices[k].normal.X = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Normal.I; vertices[k].normal.Y = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Normal.J; vertices[k].normal.Z = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Normal.K; vertices[k].u1 = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].TextureCoords.X * ((gbxmodelValues.BaseMap.Value == 0.0f) ? 1.0f : gbxmodelValues.BaseMap.Value); vertices[k].v1 = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].TextureCoords.Y * ((gbxmodelValues.BaseMap2.Value == 0.0f) ? 1.0f : gbxmodelValues.BaseMap2.Value); vertices[k].u2 = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Node0Weight.Value; vertices[k].v2 = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Node1Weight.Value; vertices[k].nodeIndex1 = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Node0Index.Value; vertices[k].nodeIndex2 = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Node1Index.Value; bounds.Update(vertices[k].position.X, vertices[k].position.Y, vertices[k].position.Z); } for (int k = 0; k < gbxmodelValues.Geometries[i].Parts[j].Triangles.Count; k++) { strip[k * 3] = (ushort)gbxmodelValues.Geometries[i].Parts[j].Triangles[k].Vertex0Index.Value; strip[k * 3 + 1] = (ushort)gbxmodelValues.Geometries[i].Parts[j].Triangles[k].Vertex1Index.Value; strip[k * 3 + 2] = (ushort)gbxmodelValues.Geometries[i].Parts[j].Triangles[k].Vertex2Index.Value; } try { SubMesh[] sub = new SubMesh[1]; sub[0] = new SubMesh(0, (ushort)(strip.Length - 2), 0); meshes[i][j] = new EnhancedMesh(vertices, strip, sub, true, false, true); meshes[i][j].DefaultShader = shaders[gbxmodelValues.Geometries[i].Parts[j].ShaderIndex.Value]; } catch (Exception ex) { LogError("Model tag {0}.{1} failed to create Mesh: {2}", Name, "gbxmodel", ex.Message); } //instances.Add(new ObjectInstance(meshes[i][j], new Vector3(gbxmodelValues.Geometries[i].Parts[j].Centroid.X, gbxmodelValues.Geometries[i].Parts[j].Centroid.Y, gbxmodelValues.Geometries[i].Parts[j].Centroid.Z))); //instances.Add(new PartInstance(meshes[i][j], new Vector3(gbxmodelValues.Geometries[i].Parts[j].Centroid.X, gbxmodelValues.Geometries[i].Parts[j].Centroid.Y, gbxmodelValues.Geometries[i].Parts[j].Centroid.Z))); } } int[] regionPermutationCounts = new int[gbxmodelValues.Regions.Count]; for (int i = 0; i < gbxmodelValues.Regions.Count; i++) { regionPermutationCounts[i] = gbxmodelValues.Regions[i].Permutations.Count; } superLow = new InstanceCollection[regionPermutationCounts.Length][]; low = new InstanceCollection[regionPermutationCounts.Length][]; medium = new InstanceCollection[regionPermutationCounts.Length][]; high = new InstanceCollection[regionPermutationCounts.Length][]; superHigh = new InstanceCollection[regionPermutationCounts.Length][]; for (int i = 0; i < regionPermutationCounts.Length; i++) { superLow[i] = new InstanceCollection[regionPermutationCounts[i]]; low[i] = new InstanceCollection[regionPermutationCounts[i]]; medium[i] = new InstanceCollection[regionPermutationCounts[i]]; high[i] = new InstanceCollection[regionPermutationCounts[i]]; superHigh[i] = new InstanceCollection[regionPermutationCounts[i]]; } int geometry; for (int i = 0; i < regionPermutationCounts.Length; i++) { for (int j = 0; j < regionPermutationCounts[i]; j++) { geometry = gbxmodelValues.Regions[i].Permutations[j].SuperLow.Value; superLow[i][j] = new InstanceCollection(); for (int k = 0; k < meshes[geometry].Length; k++) { superLow[i][j].Add(new PartInstance(meshes[geometry][k], meshes[geometry][k].DefaultShader, new Vector3(gbxmodelValues.Geometries[geometry].Parts[k].Centroid.X, gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Y, gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Z), meshes[geometry][k].BoundingBox)); } geometry = gbxmodelValues.Regions[i].Permutations[j].Low.Value; low[i][j] = new InstanceCollection(); for (int k = 0; k < meshes[geometry].Length; k++) { low[i][j].Add(new PartInstance(meshes[geometry][k], meshes[geometry][k].DefaultShader, new Vector3(gbxmodelValues.Geometries[geometry].Parts[k].Centroid.X, gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Y, gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Z), meshes[geometry][k].BoundingBox)); } geometry = gbxmodelValues.Regions[i].Permutations[j].Medium.Value; medium[i][j] = new InstanceCollection(); for (int k = 0; k < meshes[geometry].Length; k++) { medium[i][j].Add(new PartInstance(meshes[geometry][k], meshes[geometry][k].DefaultShader, new Vector3(gbxmodelValues.Geometries[geometry].Parts[k].Centroid.X, gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Y, gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Z), meshes[geometry][k].BoundingBox)); } geometry = gbxmodelValues.Regions[i].Permutations[j].High.Value; high[i][j] = new InstanceCollection(); for (int k = 0; k < meshes[geometry].Length; k++) { high[i][j].Add(new PartInstance(meshes[geometry][k], meshes[geometry][k].DefaultShader, new Vector3(gbxmodelValues.Geometries[geometry].Parts[k].Centroid.X, gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Y, gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Z), meshes[geometry][k].BoundingBox)); } geometry = gbxmodelValues.Regions[i].Permutations[j].SuperHigh.Value; superHigh[i][j] = new InstanceCollection(); for (int k = 0; k < meshes[geometry].Length; k++) { superHigh[i][j].Add(new PartInstance(meshes[geometry][k], meshes[geometry][k].DefaultShader, new Vector3(gbxmodelValues.Geometries[geometry].Parts[k].Centroid.X, gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Y, gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Z), meshes[geometry][k].BoundingBox)); } } } }
private unsafe void createCube(string name, Mogre.Vector3 gpose, double d) { MeshPtr msh = MeshManager.Singleton.CreateManual(name, "General"); SubMesh sub1 = msh.CreateSubMesh("1"); const float sqrt13 = 0.577350269f; /* sqrt(1/3) */ const int nVertices = 8; const int vbufCount = 3 * 2 * nVertices; float[] vertices = new float[vbufCount] { (float)(gpose.x - d / 2), (float)(gpose.y + d / 2), (float)(gpose.z - d / 2), //0 position -sqrt13, sqrt13, -sqrt13, //0 normal A (float)(gpose.x + d / 2), (float)(gpose.y + d / 2), (float)(gpose.z - d / 2), //1 position sqrt13, sqrt13, -sqrt13, //1 normal B (float)(gpose.x + d / 2), (float)(gpose.y - d / 2), (float)(gpose.z - d / 2), //2 position sqrt13, -sqrt13, -sqrt13, //2 normal F (float)(gpose.x - d / 2), (float)(gpose.y - d / 2), (float)(gpose.z - d / 2), //3 position -sqrt13, -sqrt13, -sqrt13, //3 normal H (float)(gpose.x - d / 2), (float)(gpose.y + d / 2), (float)(gpose.z + d / 2), -sqrt13, sqrt13, sqrt13, //4 normal C (float)(gpose.x + d / 2), (float)(gpose.y + d / 2), (float)(gpose.z + d / 2), sqrt13, sqrt13, sqrt13, //5 normal D (float)(gpose.x + d / 2), (float)(gpose.y - d / 2), (float)(gpose.z + d / 2), sqrt13, -sqrt13, sqrt13, //6 normal E (float)(gpose.x - d / 2), (float)(gpose.y - d / 2), (float)(gpose.z + d / 2), -sqrt13, -sqrt13, sqrt13, //7 normal G }; const int ibufCount = 36; ushort[] faces = new ushort[ibufCount] { //back 0, 2, 3, 0, 1, 2, //right 1, 6, 2, 1, 5, 6, //front 4, 6, 5, 4, 7, 6, //left 0, 7, 4, 0, 3, 7, //top 0, 5, 1, 0, 4, 5, //bottom 2, 7, 3, 2, 6, 7 }; sub1.vertexData = new VertexData(); sub1.vertexData.vertexCount = nVertices; VertexDeclaration decl = sub1.vertexData.vertexDeclaration; uint offset = 0; //position decl.AddElement(0, offset, VertexElementType.VET_FLOAT3, VertexElementSemantic.VES_POSITION); offset += VertexElement.GetTypeSize(VertexElementType.VET_FLOAT3); //normal decl.AddElement(0, offset, VertexElementType.VET_FLOAT3, VertexElementSemantic.VES_NORMAL); offset += VertexElement.GetTypeSize(VertexElementType.VET_FLOAT3); HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager.Singleton.CreateVertexBuffer(offset, sub1.vertexData.vertexCount, HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY); VertexBufferBinding bind = sub1.vertexData.vertexBufferBinding; void *pVertices; fixed(float *pFVertice = vertices) { pVertices = (void *)pFVertice; } vbuf.WriteData(0, vbuf.SizeInBytes, pVertices, true); bind.SetBinding(0, vbuf); void *pFaces; fixed(ushort *pUFaces = faces) { pFaces = (void *)pUFaces; } HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager.Singleton.CreateIndexBuffer(HardwareIndexBuffer.IndexType.IT_16BIT, ibufCount, HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY); ibuf.WriteData(0, ibuf.SizeInBytes, pFaces, true); sub1.useSharedVertices = false; sub1.indexData.indexBuffer = ibuf; sub1.indexData.indexCount = ibufCount; sub1.indexData.indexStart = 0; sub1.SetMaterialName("Examples/10PointBlock"); msh._setBounds(new AxisAlignedBox(-100, -100, -100, 100, 100, 100)); msh._setBoundingSphereRadius(Mogre.Math.Sqrt(3 * 100 * 100)); msh.Load(); }
public static void CalculateSubMeshVertexRangeAndBounds(Version version, Mesh mesh, ref SubMesh submesh) { UpdateSubMeshVertexRange(version, mesh, ref submesh); RecalculateSubmeshBounds(version, mesh, ref submesh); }
private static CollisionShape ExtractBox_Old(SubMesh subMesh) { if (DoLog) { Log(""); Log(string.Format("Extracting box for submesh {0}", subMesh.Name)); } MeshTriangle[] triangles = ExtractSubmeshTriangles(subMesh); int count = triangles.Length; Plane[] planesUnsorted = new Plane[6]; int planeCount = 0; // Iterate through the triangles. For each triangle, // determine the plane it belongs to, and find the plane // in the array of planes, or if it's not found, add it. for (int i = 0; i < count; i++) { MeshTriangle t = triangles[i]; bool found = false; Plane p = new Plane(t.vertPos[0], t.vertPos[1], t.vertPos[2]); NormalizePlane(ref p); if (DoLog) { Log(string.Format(" {0} => plane {1}", t.ToString(), p.ToString())); } for (int j = 0; j < planeCount; j++) { Plane pj = planesUnsorted[j]; if (SamePlane(pj, p)) { if (DoLog) { Log(string.Format(" plane {0} same as plane {1}", p.ToString(), pj.ToString())); } found = true; break; } } if (!found) { if (planeCount < 6) { if (DoLog) { Log(string.Format(" plane[{0}] = plane {1}", planeCount, p.ToString())); } planesUnsorted[planeCount++] = p; } else { Debug.Assert(false, string.Format("In the definition of box {0}, more than 6 planes were found", subMesh.Name)); } } } Debug.Assert(planeCount == 6, string.Format("In the definition of box {0}, fewer than 6 planes were found", subMesh.Name)); // Now recreate the planes array, making sure that // opposite faces are 3 planes apart Plane[] planes = new Plane[6]; bool[] planeUsed = new bool[6]; for (int i = 0; i < 6; i++) { planeUsed[i] = false; } int planePair = 0; for (int i = 0; i < 6; i++) { if (!planeUsed[i]) { Plane p1 = planesUnsorted[i]; planes[planePair] = p1; planeUsed[i] = true; for (int j = 0; j < 6; j++) { Plane p2 = planesUnsorted[j]; if (!planeUsed[j] && !Orthogonal(p2, p1)) { planes[3 + planePair++] = p2; planeUsed[j] = true; break; } } } } Debug.Assert(planePair == 3, "Didn't find 3 pairs of parallel planes"); // Make sure that the sequence of planes follows the // right-hand rule if (planes[0].Normal.Cross(planes[1].Normal).Dot(planes[3].Normal) < 0) { // Swap the first two plane pairs Plane p = planes[0]; planes[0] = planes[1]; planes[1] = p; p = planes[0 + 3]; planes[0 + 3] = planes[1 + 3]; planes[1 + 3] = p; Debug.Assert(planes[0].Normal.Cross(planes[1].Normal).Dot(planes[3].Normal) > 0, "Even after swapping, planes don't obey the right-hand rule"); } // Now we have our 6 planes, sorted so that opposite // planes are 3 planes apart, and so they obey the // right-hand rule. This guarantees that corners // correspond. Find the 8 intersections that define the // corners. Vector3[] corners = new Vector3[8]; int cornerCount = 0; for (int i = 0; i <= 3; i += 3) { Plane p1 = planes[i]; for (int j = 1; j <= 4; j += 3) { Plane p2 = planes[j]; for (int k = 2; k <= 5; k += 3) { Plane p3 = planes[k]; Vector3 corner = -1 * ((p1.D * (p2.Normal.Cross(p3.Normal)) + p2.D * (p3.Normal.Cross(p1.Normal)) + p3.D * (p1.Normal.Cross(p2.Normal))) / p1.Normal.Dot(p2.Normal.Cross(p3.Normal))); Debug.Assert(cornerCount < 8, string.Format("In the definition of box {0}, more than 8 corners were found", subMesh.Name)); if (DoLog) { Log(string.Format(" corner#{0}: {1}", cornerCount, corner.ToString())); } corners[cornerCount++] = corner; } } } Debug.Assert(cornerCount == 8, string.Format("In the definition of box {0}, fewer than 8 corners were found", subMesh.Name)); // We know that corners correspond. Now find the center Vector3 center = (corners[0] + corners[7]) / 2; Debug.Assert((center - (corners[1] + corners[5]) / 2.0f).Length > geometryEpsilon || (center - (corners[2] + corners[6]) / 2.0f).Length > geometryEpsilon || (center - (corners[3] + corners[7]) / 2.0f).Length > geometryEpsilon, string.Format("In the definition of box {0}, center definition {0} is not consistent", subMesh.Name, center.ToString())); // Find the extents Vector3 extents = new Vector3(Math.Abs((corners[1] - corners[0]).Length / 2.0f), Math.Abs((corners[3] - corners[1]).Length / 2.0f), Math.Abs((corners[4] - corners[0]).Length / 2.0f)); if (DoLog) { Log(string.Format(" extents {0}", extents.ToString())); } // Find the axes Vector3[] axes = new Vector3[3] { (corners[1] - corners[0]).ToNormalized(), (corners[3] - corners[1]).ToNormalized(), (corners[4] - corners[0]).ToNormalized() }; if (DoLog) { for (int i = 0; i < 3; i++) { Log(string.Format(" axis[{0}] {1}", i, axes[i])); } } // Now, is it an obb or an aabb? Figure out if the axes // point in the same direction as the basis vectors, and // if so, the order of the axes int[] mapping = new int[3] { -1, -1, -1 }; int foundMapping = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (axes[i].Cross(Primitives.UnitBasisVectors[j]).Length < geometryEpsilon) { mapping[i] = j; foundMapping++; break; } } } CollisionShape shape; if (foundMapping == 3) { // It's an AABB, so build the min and max vectors, in // the order that matches the unit basis vector order Vector3 min = Vector3.Zero; Vector3 max = Vector3.Zero; for (int i = 0; i < 3; i++) { float e = extents[i]; int j = mapping[i]; min[j] = center[j] - e; max[j] = center[j] + e; } shape = new CollisionAABB(min, max); } else { Vector3 ruleTest = axes[0].Cross(axes[1]); if (axes[2].Dot(ruleTest) < 0) { axes[2] = -1 * axes[2]; } // Return the OBB shape = new CollisionOBB(center, axes, extents); } if (DoLog) { Log(string.Format("Extraction result: {0}", shape)); } return(shape); }
private void ReadSubMesh(XmlReader reader, Mesh mesh) { var subReader = reader.ReadSubtree(); var subMesh = new SubMesh(); subMesh.BoundingSphereRadius = 0; bool hasBones = false; int vertexCount = 0; Vertex[] vertices = null; subMesh.Material = reader.GetAttribute("material"); while (subReader.Read()) { if (subReader.NodeType != XmlNodeType.Element) continue; // Read faces if (subReader.Name == "faces") { int faceCount = StringConverter.Parse<int>(subReader.GetAttribute("count")); subMesh.TriangleCount = faceCount; using (var memStream = new MemoryStream(faceCount * sizeof(int) * 3)) { using (var writer = new BinaryWriter(memStream)) { for (int i = 0; i < faceCount; i++) { subReader.ReadToFollowing("face"); writer.Write(StringConverter.Parse<int>(subReader.GetAttribute("v1"))); writer.Write(StringConverter.Parse<int>(subReader.GetAttribute("v2"))); writer.Write(StringConverter.Parse<int>(subReader.GetAttribute("v3"))); } subMesh.Indices = memStream.GetBuffer(); } } } // Read geometry else if (subReader.Name == "geometry") { if (vertexCount == 0) { vertexCount = StringConverter.Parse<int>(subReader.GetAttribute("vertexcount")); vertices = new Vertex[vertexCount]; } var geometryReader = subReader.ReadSubtree(); // Read vertex buffers while (geometryReader.Read()) { if (geometryReader.NodeType != XmlNodeType.Element || geometryReader.Name != "vertexbuffer") continue; for (int i = 0; i < vertexCount; i++) { var vertex = vertices[i]; if (!geometryReader.ReadToFollowing("vertex")) break; var vertexReader = geometryReader.ReadSubtree(); while (vertexReader.Read()) { if (vertexReader.NodeType != XmlNodeType.Element) continue; if (vertexReader.Name == "position") vertex.Position = ReadVector3(geometryReader); else if (vertexReader.Name == "normal") vertex.Normal = ReadVector3(geometryReader); else if (vertexReader.Name == "tangent") vertex.Tangent = ReadVector3(geometryReader); else if (vertexReader.Name == "texcoord") vertex.TexCoord = ReadUV(geometryReader); } vertices[i] = vertex; var length = vertex.Position.Length; if (subMesh.BoundingSphereRadius < length) subMesh.BoundingSphereRadius = length; } } } // Read bone assignments else if (subReader.Name == "boneassignments") { hasBones = true; var bonesReader = subReader.ReadSubtree(); while (bonesReader.Read()) { if (bonesReader.NodeType != XmlNodeType.Element || bonesReader.Name != "vertexboneassignment") continue; var index = StringConverter.Parse<int>(bonesReader.GetAttribute("vertexindex")); var vertex = vertices[index]; var boneIndex = StringConverter.Parse<float>(bonesReader.GetAttribute("boneindex")); var boneWeight = StringConverter.Parse<float>(bonesReader.GetAttribute("weight")); if (vertex.BoneCount == 0) { vertex.BoneIndex.X = boneIndex; vertex.BoneWeight.X = boneWeight; } else if (vertex.BoneCount == 1) { vertex.BoneIndex.Y = boneIndex; vertex.BoneWeight.Y = boneWeight; } else if (vertex.BoneCount == 2) { vertex.BoneIndex.Z = boneIndex; vertex.BoneWeight.Z = boneWeight; } else if (vertex.BoneCount == 3) { vertex.BoneIndex.W = boneIndex; vertex.BoneWeight.W = boneWeight; } vertex.BoneCount++; vertices[index] = vertex; } } } if (hasBones) { subMesh.VertexFormat = new Renderer.VertexFormat(new Renderer.VertexFormatElement[] { new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.Position, Renderer.VertexPointerType.Float, 3, 0), new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.Normal, Renderer.VertexPointerType.Float, 3, sizeof(float) * 3), new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.Tangent, Renderer.VertexPointerType.Float, 3, sizeof(float) * 6), new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.TexCoord, Renderer.VertexPointerType.Float, 2, sizeof(float) * 9), new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.BoneIndex, Renderer.VertexPointerType.Float, 4, sizeof(float) * 11), new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.BoneWeight, Renderer.VertexPointerType.Float, 4, sizeof(float) * 15), }); } else { subMesh.VertexFormat = new Renderer.VertexFormat(new Renderer.VertexFormatElement[] { new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.Position, Renderer.VertexPointerType.Float, 3, 0), new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.Normal, Renderer.VertexPointerType.Float, 3, sizeof(float) * 3), new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.Tangent, Renderer.VertexPointerType.Float, 3, sizeof(float) * 6), new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.TexCoord, Renderer.VertexPointerType.Float, 2, sizeof(float) * 9), }); } using (var memStream = new MemoryStream(vertexCount * subMesh.VertexFormat.Size)) { using (var writer = new BinaryWriter(memStream)) { for (int i = 0; i < vertexCount; i++) { writer.Write(vertices[i].Position); writer.Write(vertices[i].Normal); writer.Write(vertices[i].Tangent); writer.Write(vertices[i].TexCoord); if (hasBones) { writer.Write(vertices[i].BoneIndex); writer.Write(vertices[i].BoneWeight); } } subMesh.Vertices = memStream.GetBuffer(); } } mesh.SubMeshes.Add(subMesh); }
public WaterMesh(String meshName, float planeSize, int cmplx) // najak R-F // Assign Fields to the Initializer values { this.meshName = meshName; this.size = planeSize; this.cmplx = cmplx; // Number of Rows/Columns in the Water Grid representation cmplxAdj = (float)Math.Pow((cmplx / 64f), 1.4f) * 2; numFaces = 2 * (int)Math.Pow(cmplx, 2); // Each square is split into 2 triangles. numVertices = (int)Math.Pow((cmplx + 1), 2); // Vertex grid is (Complexity+1) squared // Allocate and initialize space for calculated Normals vNorms = new Vector3[cmplx + 1, cmplx + 1]; // vertex Normals for each grid point fNorms = new Vector3[cmplx, cmplx, 2]; // face Normals for each triangle // Create mesh and submesh to represent the Water mesh = (Mesh)MeshManager.Instance.CreateManual(meshName); subMesh = mesh.CreateSubMesh(); subMesh.useSharedVertices = false; // Construct metadata to describe the buffers associated with the water submesh subMesh.vertexData = new VertexData(); subMesh.vertexData.vertexStart = 0; subMesh.vertexData.vertexCount = numVertices; // Define local variables to point to the VertexData Properties VertexDeclaration vdecl = subMesh.vertexData.vertexDeclaration; // najak: seems like metadata VertexBufferBinding vbind = subMesh.vertexData.vertexBufferBinding; // najak: pointer to actual buffer //najak: Set metadata to describe the three vertex buffers that will be accessed. vdecl.AddElement(0, 0, VertexElementType.Float3, VertexElementSemantic.Position); vdecl.AddElement(1, 0, VertexElementType.Float3, VertexElementSemantic.Normal); vdecl.AddElement(2, 0, VertexElementType.Float2, VertexElementSemantic.TexCoords); // Prepare buffer for positions - todo: first attempt, slow // Create the Position Vertex Buffer and Bind it index 0 - Write Only posVBuf = HwBufMgr.CreateVertexBuffer(3 * 4, numVertices, BufferUsage.DynamicWriteOnly); vbind.SetBinding(0, posVBuf); // Prepare buffer for normals - write only // Create the Normals Buffer and Bind it to index 1 - Write only normVBuf = HwBufMgr.CreateVertexBuffer(3 * 4, numVertices, BufferUsage.DynamicWriteOnly); vbind.SetBinding(1, normVBuf); // Prepare Texture Coordinates buffer (static, written only once) // Creates a 2D buffer of 2D coordinates: (Complexity X Complexity), pairs. // Each pair indicates the normalized coordinates of the texture to map to. // (0,1.00), (0.02, 1.00), (0.04, 1.00), ... (1.00,1.00) // (0,0.98), (0.02, 0.98), (0.04, 1.00), ... (1.00,0.98) // ... // (0,0.00), (0.02, 0.00), (0.04, 0.00), ... (1.00,0.00) // This construct is simple and is used to calculate the Texture map. // Todo: Write directly to the buffer, when Axiom supports this in safe manner float[,,] tcBufDat = new float[cmplx + 1, cmplx + 1, 2]; for (int i = 0; i <= cmplx; i++) { // 2D column iterator for texture map for (int j = 0; j <= cmplx; j++) { // 2D row iterator for texture map // Define the normalized(0..1) X/Y-coordinates for this element of the 2D grid tcBufDat[i, j, 0] = (float)i / cmplx; tcBufDat[i, j, 1] = 1.0f - ((float)j / (cmplx)); } } // Now Create the actual hardware buffer to contain the Texture Coordinate 2d map. // and Bind it to buffer index 2 tcVBuf = HwBufMgr.CreateVertexBuffer(2 * 4, numVertices, BufferUsage.StaticWriteOnly); tcVBuf.WriteData(0, tcVBuf.Size, tcBufDat, true); vbind.SetBinding(2, tcVBuf); // Create a Graphics Buffer on non-shared vertex indices (3 points for each triangle). // Since the water grid consist of [Complexity x Complexity] squares, each square is // split into 2 right triangles 45-90-45. That is how the water mesh is constructed. // Therefore the number of faces = 2 * Complexity * Complexity ushort[,,] idxBuf = new ushort[cmplx, cmplx, 6]; for (int i = 0; i < cmplx; i++) // iterate the rows { for (int j = 0; j < cmplx; j++) // iterate the columns // Define 4 corners of each grid { ushort p0 = (ushort)(i * (cmplx + 1) + j); // top left point on square ushort p1 = (ushort)(i * (cmplx + 1) + j + 1); // top right ushort p2 = (ushort)((i + 1) * (cmplx + 1) + j); // bottom left ushort p3 = (ushort)((i + 1) * (cmplx + 1) + j + 1); // bottom right // Split Square Grid element into 2 adjacent triangles. idxBuf[i, j, 0] = p2; idxBuf[i, j, 1] = p1; idxBuf[i, j, 2] = p0; // top-left triangle idxBuf[i, j, 3] = p2; idxBuf[i, j, 4] = p3; idxBuf[i, j, 5] = p1; // bottom-right triangle } } // Copy Index Buffer to the Hardware Index Buffer HardwareIndexBuffer hdwrIdxBuf = HwBufMgr.CreateIndexBuffer(IndexType.Size16, 3 * numFaces, BufferUsage.StaticWriteOnly, true); hdwrIdxBuf.WriteData(0, numFaces * 3 * 2, idxBuf, true); // Set index buffer for this submesh subMesh.indexData.indexBuffer = hdwrIdxBuf; subMesh.indexData.indexStart = 0; subMesh.indexData.indexCount = 3 * numFaces; //Prepare Vertex Position Buffers (Note: make 3, since each frame is function of previous two) vBufs = new Vector3[3][, ]; for (int b = 0; b < 3; b++) { vBufs[b] = new Vector3[cmplx + 1, cmplx + 1]; for (int y = 0; y <= cmplx; y++) { for (int x = 0; x <= cmplx; x++) { vBufs[b][y, x].x = (float)(x) / (float)(cmplx) * (float)size; vBufs[b][y, x].y = 0; vBufs[b][y, x].z = (float)(y) / (float)(cmplx) * (float)size; } } } curBufNum = 0; vBuf = vBufs[curBufNum]; posVBuf.WriteData(0, posVBuf.Size, vBufs[0], true); AxisAlignedBox meshBounds = new AxisAlignedBox(new Vector3(0, 0, 0), new Vector3(size, 0, size)); mesh.BoundingBox = meshBounds; // mesh->_setBounds(meshBounds); // najak: can't find _setBounds() mesh.Load(); mesh.Touch(); } // end WaterMesh Constructor
public Model(SubMesh mesh) { _subMesh = mesh; }
// Get the mesh information for the given mesh. // Code found on this forum link: http://www.ogre3d.org/wiki/index.php/RetrieveVertexData private static unsafe void GetMeshInformation(MeshPtr mesh, out Vector3[] vertices, out int[] indices, Vector3 position, Quaternion orient, Vector3 scale) { bool addedShared = false; int currentOffset = 0, sharedOffset = 0, nextOffset = 0, indexOffset = 0; int vertexCount = 0, indexCount = 0; // Calculate how many vertices and indices we're going to need for (ushort i = 0; i < mesh.NumSubMeshes; ++i) { SubMesh submesh = mesh.GetSubMesh(i); // We only need to add the shared vertices once if (submesh.useSharedVertices) { if (!addedShared) { vertexCount += (int)mesh.sharedVertexData.vertexCount; addedShared = true; } } else { vertexCount += (int)submesh.vertexData.vertexCount; } // Add the indices indexCount += (int)submesh.indexData.indexCount; } // Allocate space for the vertices and indices vertices = new Vector3[vertexCount]; indices = new int[indexCount]; addedShared = false; // Run through the submeshes again, adding the data into the arrays for (ushort i = 0; i < mesh.NumSubMeshes; ++i) { SubMesh submesh = mesh.GetSubMesh(i); VertexData vertexData = submesh.useSharedVertices ? mesh.sharedVertexData : submesh.vertexData; if ((!submesh.useSharedVertices) || (submesh.useSharedVertices && !addedShared)) { if (submesh.useSharedVertices) { addedShared = true; sharedOffset = currentOffset; } VertexElement posElem = vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.VES_POSITION); System.Diagnostics.Debug.Assert(posElem.Type == VertexElementType.VET_FLOAT3); using (HardwareVertexBufferSharedPtr vbuf = vertexData.vertexBufferBinding.GetBuffer(posElem.Source)) { byte * vertex = (byte *)vbuf.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); float *preal; for (uint j = 0; j < vertexData.vertexCount; ++j, vertex += vbuf.VertexSize) { posElem.BaseVertexPointerToElement(vertex, &preal); Vector3 pt = new Vector3(preal[0], preal[1], preal[2]); vertices[currentOffset + j] = (orient * (pt * scale)) + position; } vbuf.Unlock(); } nextOffset += (int)vertexData.vertexCount; } IndexData indexData = submesh.indexData; using (HardwareIndexBufferSharedPtr ibuf = indexData.indexBuffer) { bool use32bitindexes = ibuf.Type == HardwareIndexBuffer.IndexType.IT_32BIT; int * plong = (int *)ibuf.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); ushort *pshort = (ushort *)plong; int offset = submesh.useSharedVertices ? sharedOffset : currentOffset; if (use32bitindexes) { for (uint k = 0; k < indexData.indexCount; ++k) { indices[indexOffset++] = plong[k] + offset; } } else { for (uint k = 0; k < indexData.indexCount; ++k) { indices[indexOffset++] = pshort[k] + offset; } } ibuf.Unlock(); } currentOffset = nextOffset; } }
public static void ExtractCollisionShapes(Mesh mesh, string path) { PhysicsData physicsData = null; List <string> deleteEm = new List <string>(); int count = mesh.SubMeshCount; for (int i = 0; i < count; i++) { SubMesh subMesh = mesh.GetSubMesh(i); CollisionShape shape = null; string targetName = null; bool cv = String.Compare(subMesh.Name.Substring(0, 5), "mvcv_", false) == 0; bool rg = String.Compare(subMesh.Name.Substring(0, 5), "mvrg_", false) == 0; int firstIndex = 0; if (cv) { firstIndex = 5; } else if (rg) { string rest = subMesh.Name.Substring(5); firstIndex = rest.IndexOf("_") + 1 + 5; } if (cv || rg) { // It's probably a collision volume - - check the // shape type to make sure if (String.Compare(subMesh.Name.Substring(firstIndex, 4), "obb_", false) == 0) { shape = ExtractBox(subMesh); } else if (String.Compare(subMesh.Name.Substring(firstIndex, 5), "aabb_", false) == 0) { shape = ExtractBox(subMesh); } else if (String.Compare(subMesh.Name.Substring(firstIndex, 7), "sphere_", false) == 0) { shape = ExtractSphere(subMesh); } else if (String.Compare(subMesh.Name.Substring(firstIndex, 8), "capsule_", false) == 0) { shape = ExtractCapsule(subMesh); } if (shape != null) { targetName = GetTargetSubmesh(mesh, subMesh.Name); } } if (shape != null) { deleteEm.Add(subMesh.Name); if (physicsData == null) { physicsData = new PhysicsData(); } physicsData.AddCollisionShape(targetName, shape); } } for (int i = 0; i < deleteEm.Count; i++) { mesh.RemoveSubMesh(deleteEm[i]); } if (physicsData != null) { PhysicsSerializer serializer = new PhysicsSerializer(); serializer.ExportPhysics(physicsData, path + ".physics"); } if (DoLog) { CloseLog(); } }
// Take a different approach, based on an idea of Robin's: // Find the farthest point pair, and use that to identify the // triangles with one of the points as a vertex. Then take // the normals of the triangles, adjust to object the // right-hand rule, and they are the axes. Compute the center // from the average of the farthest points, and extents by // dotting farthest - center with the axes. private static CollisionShape ExtractBox(SubMesh subMesh) { if (DoLog) { Log(""); Log(string.Format("Extracting box for submesh {0}", subMesh.Name)); } MeshTriangle[] triangles = ExtractSubmeshTriangles(subMesh); int count = triangles.Length; // Find the two farthest vertices across all triangle Vector3[] farthestPoints = new Vector3[2] { Vector3.Zero, Vector3.Zero }; float farthestDistanceSquared = 0.0f; for (int i = 0; i < count; i++) { MeshTriangle t1 = triangles[i]; for (int j = 0; j < 3; j++) { Vector3 p1 = t1.vertPos[j]; for (int r = i; r < count; r++) { MeshTriangle t2 = triangles[r]; for (int s = 0; s < 3; s++) { Vector3 p2 = t2.vertPos[s]; Vector3 diff = (p1 - p2); float d = diff.LengthSquared; // if (DoLog) // Log(string.Format(" TriVert {0} {1} {2} / {3} {4} {5} dist {6}", i, j, p1, r, s, p2, d)); if (d > farthestDistanceSquared) { if (DoLog) { Log(string.Format(" Largest! TriVert {0} {1} {2} / {3} {4} {5} dist {6}", i, j, p1, r, s, p2, d)); } farthestDistanceSquared = d; farthestPoints[0] = p1; farthestPoints[1] = p2; } } } } } // The center is the average of the farthest points Vector3 center = (farthestPoints[0] + farthestPoints[1]) * 0.5f; if (DoLog) { Log(string.Format("The farthest points are {0} and {1}", farthestPoints[0], farthestPoints[1])); Log(string.Format("The center is {0}", center)); } // Now find the three triangles that have the // farthestPoints[0] as a vertex Vector3[] axes = new Vector3[] { Vector3.Zero, Vector3.Zero, Vector3.Zero }; int foundCount = 0; for (int i = 0; i < count; i++) { MeshTriangle t = triangles[i]; for (int j = 0; j < 3; j++) { Vector3 p = t.vertPos[j]; if ((p - farthestPoints[0]).LengthSquared < geometryEpsilon) { Vector3 side1 = t.vertPos[1] - t.vertPos[0]; Vector3 side2 = t.vertPos[2] - t.vertPos[1]; Vector3 axis = side1.Cross(side2).ToNormalized(); // Ignore this triangle if his normal matches one we already have bool ignore = false; for (int k = 0; k < foundCount; k++) { if (Math.Abs(axis.Cross(axes[k]).LengthSquared) < geometryEpsilon) { ignore = true; break; } } if (!ignore) { Debug.Assert(foundCount < 3, "Found more than three triangles with distinct normals and vertex = farthest point"); axes[foundCount] = axis; foundCount++; } } } } // Put the axes in coordinate order for (int i = 0; i < 3; i++) { float largest = float.MinValue; int largestIndex = i; for (int j = 0; j < 3; j++) { float v = Math.Abs(axes[j][i]); if (v > largest) { largestIndex = j; largest = v; } } if (largestIndex != i) { Vector3 t = axes[i]; axes[i] = axes[largestIndex]; axes[largestIndex] = t; } if (axes[i][i] < 0) { axes[i] = -axes[i]; } } // Put the axes in right-hand-rule order if (axes[0].Cross(axes[1]).Dot(axes[2]) < 0) { axes[2] = -axes[2]; } Debug.Assert(axes[0].Cross(axes[1]).Dot(axes[2]) > 0, "After swapping axes, still don't obey right-hand rule"); // The extents are just the abs of the dot products of // farthest point minus the center with the axes Vector3 f = farthestPoints[0] - center; Vector3 extents = new Vector3(Math.Abs(f.Dot(axes[0])), Math.Abs(f.Dot(axes[1])), Math.Abs(f.Dot(axes[2]))); if (DoLog) { for (int i = 0; i < 3; i++) { Log(string.Format(" axis[{0}] {1}, extent[{2}] {3}", i, axes[i], i, extents[i])); } int[] sign = new int[3] { 0, 0, 0 }; for (int i = -1; i < 2; i += 2) { sign[0] = i; for (int j = -1; j < 2; j += 2) { sign[1] = j; for (int k = -1; k < 2; k += 2) { sign[2] = k; Vector3 corner = center; for (int a = 0; a < 3; a++) { corner += axes[a] * extents[a] * sign[a]; } Log(string.Format(" corner[{0},{1},{2}] = {3}", i, j, k, corner)); } } } } // Now, is it an obb or an aabb? Figure out if the axes // point in the same direction as the basis vectors, and // if so, the order of the axes int[] mapping = new int[3] { -1, -1, -1 }; int foundMapping = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (Math.Abs(axes[i].Dot(Primitives.UnitBasisVectors[j]) - 1.0f) < .0001f) { if (DoLog) { Log(string.Format(" foundMapping[{0}], basis vector {1}", i, Primitives.UnitBasisVectors[j])); } mapping[i] = j; foundMapping++; break; } } } CollisionShape shape; if (foundMapping == 3) { // It's an AABB, so build the min and max vectors, in // the order that matches the unit basis vector order Vector3 min = Vector3.Zero; Vector3 max = Vector3.Zero; for (int i = 0; i < 3; i++) { float e = extents[i]; int j = mapping[i]; min[j] = center[j] - e; max[j] = center[j] + e; } shape = new CollisionAABB(min, max); } else { // Return the OBB shape = new CollisionOBB(center, axes, extents); } if (DoLog) { Log(string.Format("Extraction result: {0}", shape)); } return(shape); }
private static SubMesh Convert(IExportContainer container, Mesh instanceMesh, ref SubMesh origin) { SubMesh instance = new SubMesh(); instance.FirstByte = origin.FirstByte; instance.IndexCount = origin.IndexCount; instance.Topology = origin.GetTopology(container.Version); if (SubMesh.HasTriangleCount(container.ExportVersion)) { instance.TriangleCount = origin.TriangleCount; } if (SubMesh.HasBaseVertex(container.ExportVersion)) { instance.BaseVertex = GetBaseVertex(container, ref origin); } if (SubMesh.HasVertex(container.ExportVersion)) { SetVertex(container, instanceMesh, ref origin, ref instance); } return(instance); }
unsafe void UpdateGeometry(float time) { //generate geometry Vertex[] vertices = new Vertex[tesselation * tesselation]; ushort[] indices = new ushort[(tesselation - 1) * (tesselation - 1) * 6]; { //vertices int vertexPosition = 0; for (int y = 0; y < tesselation; y++) { for (int x = 0; x < tesselation; x++) { Vertex vertex = new Vertex(); Vec2 pos2 = new Vec2( (float)x / (float)(tesselation - 1) - .5f, (float)y / (float)(tesselation - 1) - .5f); float posZ = MathFunctions.Sin(pos2.Length() * 30 - time * 2) / 2; MathFunctions.Clamp(ref posZ, -5f, .5f); vertex.position = new Vec3(pos2.X, pos2.Y, posZ) * Scale; vertex.normal = Vec3.Zero; vertex.texCoord = new Vec2(pos2.X + .5f, pos2.Y + .5f); //vertex.tangents = Vec4.Zero; vertices[vertexPosition] = vertex; vertexPosition++; } } //indices int indexPosition = 0; for (int y = 0; y < tesselation - 1; y++) { for (int x = 0; x < tesselation - 1; x++) { indices[indexPosition] = (ushort)(tesselation * y + x); indexPosition++; indices[indexPosition] = (ushort)(tesselation * y + x + 1); indexPosition++; indices[indexPosition] = (ushort)(tesselation * (y + 1) + x + 1); indexPosition++; indices[indexPosition] = (ushort)(tesselation * (y + 1) + x + 1); indexPosition++; indices[indexPosition] = (ushort)(tesselation * (y + 1) + x); indexPosition++; indices[indexPosition] = (ushort)(tesselation * y + x); indexPosition++; } } //calculate vertex normals fixed(Vertex *pVertices = vertices) { int triangleCount = indices.Length / 3; for (int n = 0; n < triangleCount; n++) { int index0 = indices[n * 3 + 0]; int index1 = indices[n * 3 + 1]; int index2 = indices[n * 3 + 2]; Vec3 pos0 = pVertices[index0].position; Vec3 pos1 = pVertices[index1].position; Vec3 pos2 = pVertices[index2].position; Vec3 normal = Vec3.Cross(pos1 - pos0, pos2 - pos0); normal.Normalize(); pVertices[index0].normal += normal; pVertices[index1].normal += normal; pVertices[index2].normal += normal; } //normalize for (int n = 0; n < vertices.Length; n++) { pVertices[n].normal = pVertices[n].normal.GetNormalize(); } } } SubMesh subMesh = mesh.SubMeshes[0]; //copy data to vertex buffer { HardwareVertexBuffer vertexBuffer = subMesh.VertexData.VertexBufferBinding.GetBuffer(0); IntPtr buffer = vertexBuffer.Lock(HardwareBuffer.LockOptions.Discard); fixed(Vertex *pVertices = vertices) { NativeUtils.CopyMemory(buffer, (IntPtr)pVertices, vertices.Length * sizeof(Vertex)); } vertexBuffer.Unlock(); } //copy data to index buffer { HardwareIndexBuffer indexBuffer = subMesh.IndexData.IndexBuffer; IntPtr buffer = indexBuffer.Lock(HardwareBuffer.LockOptions.Discard); fixed(ushort *pIndices = indices) { NativeUtils.CopyMemory(buffer, (IntPtr)pIndices, indices.Length * sizeof(ushort)); } indexBuffer.Unlock(); } ////calculate mesh tangent vectors //mesh.BuildTangentVectors( VertexElementSemantic.Tangent, 0, 0, true ); }
private static MeshTriangle[] ExtractSubmeshTriangles(SubMesh subMesh) { int[] vertIdx = new int[3]; Vector3[] vertPos = new Vector3[3]; VertexElement posElem = subMesh.vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Position); HardwareVertexBuffer posBuffer = posBuffer = subMesh.vertexData.vertexBufferBinding.GetBuffer(posElem.Source); IntPtr indexPtr = subMesh.indexData.indexBuffer.Lock(BufferLocking.ReadOnly); IntPtr posPtr = posBuffer.Lock(BufferLocking.ReadOnly); int posOffset = posElem.Offset / sizeof(float); int posStride = posBuffer.VertexSize / sizeof(float); int numFaces = subMesh.indexData.indexCount / 3; MeshTriangle[] triangles = new MeshTriangle[numFaces]; unsafe { int * pIdxInt32 = null; short *pIdxShort = null; float *pVPos = (float *)posPtr.ToPointer(); if (subMesh.indexData.indexBuffer.Type == IndexType.Size32) { pIdxInt32 = (int *)indexPtr.ToPointer(); } else { pIdxShort = (short *)indexPtr.ToPointer(); } // loop through all faces to calculate the tangents for (int n = 0; n < numFaces; n++) { for (int i = 0; i < 3; i++) { // get indices of vertices that form a polygon in the position buffer if (subMesh.indexData.indexBuffer.Type == IndexType.Size32) { vertIdx[i] = pIdxInt32[3 * n + i]; } else { vertIdx[i] = pIdxShort[3 * n + i]; } vertPos[i].x = pVPos[vertIdx[i] * posStride + posOffset]; vertPos[i].y = pVPos[vertIdx[i] * posStride + posOffset + 1]; vertPos[i].z = pVPos[vertIdx[i] * posStride + posOffset + 2]; } triangles[n] = new MeshTriangle(vertPos[0], vertPos[1], vertPos[2]); } } posBuffer.Unlock(); subMesh.indexData.indexBuffer.Unlock(); if (DoLog) { int count = triangles.Length; Log(string.Format(" extracted {0} triangles", count)); for (int i = 0; i < count; i++) { Log(string.Format(" {0}", triangles[i].ToString())); } } return(triangles); }
private void CreateGrassMesh() { // Each grass section is 3 planes at 60 degrees to each other // Normals point straight up to simulate correct lighting Mesh msh = MeshManager.Singleton.CreateManual(GRASS_MESH_NAME, ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME, null); SubMesh sm = msh.CreateSubMesh(); sm.useSharedVertices = false; sm.vertexData = new VertexData(); sm.vertexData.vertexStart = 0; sm.vertexData.vertexCount = 12; VertexDeclaration dcl = sm.vertexData.vertexDeclaration; uint offset = 0; dcl.AddElement(0, offset, VertexElementType.VET_FLOAT3, VertexElementSemantic.VES_POSITION); offset += VertexElement.GetTypeSize(VertexElementType.VET_FLOAT3); dcl.AddElement(0, offset, VertexElementType.VET_FLOAT3, VertexElementSemantic.VES_NORMAL); offset += VertexElement.GetTypeSize(VertexElementType.VET_FLOAT3); dcl.AddElement(0, offset, VertexElementType.VET_FLOAT2, VertexElementSemantic.VES_TEXTURE_COORDINATES); offset += VertexElement.GetTypeSize(VertexElementType.VET_FLOAT2); HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager.Singleton.CreateVertexBuffer(offset, 12, HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY); int i; unsafe { float *pData = (float *)(vbuf.Lock(HardwareBuffer.LockOptions.HBL_DISCARD)); Vector3 baseVec = new Vector3(GRASS_WIDTH / 2, 0, 0); Vector3 vec = baseVec; Quaternion rot = new Quaternion(); rot.FromAngleAxis(Math.DegreesToRadians(60), Vector3.UNIT_Y); for (i = 0; i < 3; ++i) { //position *pData++ = -vec.x; *pData++ = GRASS_HEIGHT; *pData++ = -vec.z; // normal *pData++ = 0; *pData++ = 1; *pData++ = 0; // uv *pData++ = 0; *pData++ = 0; // position *pData++ = vec.x; *pData++ = GRASS_HEIGHT; *pData++ = vec.z; // normal *pData++ = 0; *pData++ = 1; *pData++ = 0; // uv *pData++ = 1; *pData++ = 0; // position *pData++ = -vec.x; *pData++ = 0; *pData++ = -vec.z; // normal *pData++ = 0; *pData++ = 1; *pData++ = 0; // uv *pData++ = 0; *pData++ = 1; // position *pData++ = vec.x; *pData++ = 0; *pData++ = vec.z; // normal *pData++ = 0; *pData++ = 1; *pData++ = 0; // uv *pData++ = 1; *pData++ = 1; vec = rot * vec; } //for } //unsafe vbuf.Unlock(); sm.vertexData.vertexBufferBinding.SetBinding(0, vbuf); sm.indexData.indexCount = 6 * 3; sm.indexData.indexBuffer = HardwareBufferManager.Singleton.CreateIndexBuffer(HardwareIndexBuffer.IndexType.IT_16BIT, 6 * 3, HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY); unsafe { ushort *pI = (ushort *)(sm.indexData.indexBuffer.Lock(HardwareBuffer.LockOptions.HBL_DISCARD)); for (i = 0; i < 3; ++i) { int off = i * 4; * pI++ = (ushort)(off); * pI++ = (ushort)(off + 3); * pI++ = (ushort)(off + 1); *pI++ = (ushort)(off + 0); *pI++ = (ushort)(off + 2); *pI++ = (ushort)(off + 3); } } sm.indexData.indexBuffer.Unlock(); sm.SetMaterialName(GRASS_MATERIAL); msh.Load(); }
/// <summary> /// createGrassMesh /// This demonstrates how to create a manual mesh /// only use static members of MeshBuilderHelper to help set vertex and index data. /// </summary> void createGrassMesh() { OgreDotNet.MeshPtr mp = MeshManager.Instance.CreateManual(GRASS_MESH_NAME, "General"); SubMesh sm = mp.Get().CreateSubMesh(); sm.useSharedVertices = false; sm.vertexData = new VertexData(); sm.vertexData.vertexStart = 0; sm.vertexData.vertexCount = 12; //mIndexType = HardwareIndexBuffer::IT_16BIT; VertexDeclaration dcl = sm.vertexData.vertexDeclaration; UInt32 offset = 0; UInt32 offPos = dcl.addElement(0, offset, VertexElementType.VET_FLOAT3, VertexElementSemantic.VES_POSITION).getOffset(); offset = VertexElement.getTypeSize(VertexElementType.VET_FLOAT3); UInt32 offNorm = dcl.addElement(0, offset, VertexElementType.VET_FLOAT3, VertexElementSemantic.VES_NORMAL).getOffset(); offset += VertexElement.getTypeSize(VertexElementType.VET_FLOAT3); UInt32 offUV = dcl.addElement(0, offset, VertexElementType.VET_FLOAT2, VertexElementSemantic.VES_TEXTURE_COORDINATES).getOffset(); offset += VertexElement.getTypeSize(VertexElementType.VET_FLOAT2); UInt32 vertexsize = offset; mLog.LogMessage(string.Format("createGrassMesh vertexsize={0}", vertexsize)); HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager.getSingleton().createVertexBuffer( vertexsize, 12, HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY); IntPtr pV = vbuf.Get().Lock(HardwareBuffer.LockOptions.HBL_DISCARD); Vector3 vec = new Vector3(GRASS_WIDTH / 2.0f, 0.0f, 0.0f); Quaternion rot = Quaternion.FromAngleAxis(60, Vector3.UnitY); uint i; for (i = 0; i < 3; ++i) { OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 0, offPos, -vec.x, GRASS_HEIGHT, -vec.z); //position OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 0, offNorm, 0.0f, 1.0f, 0.0f); //normal OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 0, offUV, 0.0f, 0.0f); //uv OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 1, offPos, vec.x, GRASS_HEIGHT, vec.z); //position OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 1, offNorm, 0.0f, 1.0f, 0.0f); //normal OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 1, offUV, 1.0f, 0.0f); //uv OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 2, offPos, -vec.x, 0.0f, -vec.z); //position OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 2, offNorm, 0.0f, 1.0f, 0.0f); //normal OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 2, offUV, 0.0f, 1.0f); //uv OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 3, offPos, vec.x, 0.0f, vec.z); //position OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 3, offNorm, 0.0f, 1.0f, 0.0f); //normal OgreDotNet.MeshBuilderHelper.SetVertexFloat(pV, vertexsize, (i * 4) + 3, offUV, 1.0f, 1.0f); //uv vec = rot * vec; } vbuf.Get().Unlock(); sm.vertexData.vertexBufferBinding.setBinding(0, vbuf); sm.indexData.indexCount = 6 * 3; sm.indexData.indexBuffer = HardwareBufferManager.getSingleton().createIndexBuffer( HardwareIndexBuffer.IndexType.IT_16BIT, 6 * 3, HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY); IntPtr pI = sm.indexData.indexBuffer.Get().Lock(HardwareBuffer.LockOptions.HBL_DISCARD); for (i = 0; i < 3; ++i) { UInt16 off = (UInt16)(i * 4); OgreDotNet.MeshBuilderHelper.SetIndex16bit(pI, (i * 2) + 0, (UInt16)(0 + off), (UInt16)(3 + off), (UInt16)(1 + off)); OgreDotNet.MeshBuilderHelper.SetIndex16bit(pI, (i * 2) + 1, (UInt16)(0 + off), (UInt16)(2 + off), (UInt16)(3 + off)); } sm.indexData.indexBuffer.Get().Unlock(); sm.SetMaterialName(GRASS_MATERIAL); mp.Get().Load(); }
private static void SetVertex(IExportContainer container, Mesh instanceMesh, ref SubMesh origin, ref SubMesh instance) { if (SubMesh.HasVertex(container.Version)) { instance.FirstVertex = origin.FirstVertex; instance.VertexCount = origin.VertexCount; instance.LocalAABB = origin.LocalAABB; } else { CalculateSubMeshVertexRangeAndBounds(container.ExportVersion, instanceMesh, ref instance); } }
/// <summary> /// /// </summary> /// <param name="page"></param> /// <param name="layer"></param> /// <param name="grassPostions"></param> /// <param name="grassCount"></param> /// <returns></returns> private Mesh GenerateGrassCrossQuads(PageInfo page, GrassLayer layer, IntPtr grassPostions, int grassCount) { //Calculate the number of quads to be added int quadCount = grassCount * 2; //Create manual mesh to store grass quads Mesh mesh = (Mesh)MeshManager.Instance.CreateManual(GetUniqueID(), ResourceGroupManager.DefaultResourceGroupName, null); SubMesh subMesh = mesh.CreateSubMesh(); subMesh.useSharedVertices = false; //Setup vertex format information subMesh.vertexData = new VertexData(); subMesh.vertexData.vertexStart = 0; subMesh.vertexData.vertexCount = 4 * quadCount; VertexDeclaration dcl = subMesh.vertexData.vertexDeclaration; int offset = 0; dcl.AddElement(0, offset, VertexElementType.Float3, VertexElementSemantic.Position); offset += VertexElement.GetTypeSize(VertexElementType.Float3); dcl.AddElement(0, offset, VertexElementType.Color, VertexElementSemantic.Diffuse); offset += VertexElement.GetTypeSize(VertexElementType.Color); dcl.AddElement(0, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords); offset += VertexElement.GetTypeSize(VertexElementType.Float2); //Populate a new vertex buffer with grass HardwareVertexBuffer vbuf = HardwareBufferManager.Instance.CreateVertexBuffer( /*offset*/ dcl, subMesh.vertexData.vertexCount, BufferUsage.DynamicWriteOnly, false); unsafe { float *pReal = (float *)vbuf.Lock(BufferLocking.Discard); //Calculate size variance float rndWidth = layer.mMaxWidth - layer.mMinWidth; float rndHeight = layer.mMaxHeight - layer.mMinHeight; float minY = float.PositiveInfinity, maxY = float.NegativeInfinity; float *posPtr = (float *)grassPostions; //Position array "iterator" for (int i = 0; i < grassCount; i++) { //Get the x and z positions from the position array float x = *posPtr++; float z = *posPtr++; //Get the color at the grass position uint color = 0; if (layer.ColorMap != null) { color = layer.ColorMap.GetColorAt(x, z); } else { color = 0xFFFFFFFF; } //Calculate size float rnd = MogreLibMath.Utility.UnitRandom();//The same rnd value is used for width and height to maintain aspect ratio float halfXScale = (layer.mMinWidth + rndWidth * rnd) * 0.5f; float scaleY = (layer.mMinWidth + rndHeight * rnd); //Calculate rotation float angle = MogreLibMath.Utility.RangeRandom(0, MogreLibMath.Utility.TWO_PI); float xTrans = MogreLibMath.Utility.Cos(angle) * halfXScale; float zTrans = MogreLibMath.Utility.Sin(angle) * halfXScale; //Calculate heights and edge positions float x1 = x - xTrans, z1 = z - zTrans; float x2 = x + xTrans, z2 = z + zTrans; float y1, y2; if (mHeightFunction != null) { y1 = mHeightFunction.GetHeightAt(x1, z1, mHeightFunctionUserData); y2 = mHeightFunction.GetHeightAt(x2, z2, mHeightFunctionUserData); } else { y1 = 0; y2 = 0; } //Add vertices *pReal++ = (x1 - page.CenterPoint.x); *pReal++ = (y1 + scaleY); *pReal++ = (z1 - page.CenterPoint.z); //pos *((uint *)pReal++) = color; //color *pReal++ = 0; *pReal++ = 0; //uv *pReal++ = (x2 - page.CenterPoint.x); *pReal++ = (y2 + scaleY); *pReal++ = (z2 - page.CenterPoint.z); //pos *((uint *)pReal++) = color; //color *pReal++ = 1; *pReal++ = 0; //uv *pReal++ = (x1 - page.CenterPoint.x); *pReal++ = (y1); *pReal++ = (z1 - page.CenterPoint.z); //pos *((uint *)pReal++) = color; //color *pReal++ = 0; *pReal++ = 1; //uv *pReal++ = (x2 - page.CenterPoint.x); *pReal++ = (y2); *pReal++ = (z2 - page.CenterPoint.z); //pos *((uint *)pReal++) = color; //color *pReal++ = 1; *pReal++ = 1; //uv //Update bounds if (y1 < minY) { minY = y1; } if (y2 < minY) { minY = y2; } if (y1 + scaleY > maxY) { maxY = y1 + scaleY; } if (y2 + scaleY > maxY) { maxY = y2 + scaleY; } //Calculate heights and edge positions float x3 = x + zTrans, z3 = z - xTrans; float x4 = x - zTrans, z4 = z + xTrans; float y3, y4; if (mHeightFunction != null) { y3 = mHeightFunction.GetHeightAt(x3, z3, mHeightFunctionUserData); y4 = mHeightFunction.GetHeightAt(x4, z4, mHeightFunctionUserData); } else { y3 = 0; y4 = 0; } //Add vertices *pReal++ = (x3 - page.CenterPoint.x); *pReal++ = (y3 + scaleY); *pReal++ = (z3 - page.CenterPoint.z); //pos *((uint *)pReal++) = color; //color *pReal++ = 0; *pReal++ = 0; //uv *pReal++ = (x4 - page.CenterPoint.x); *pReal++ = (y4 + scaleY); *pReal++ = (z4 - page.CenterPoint.z); //pos *((uint *)pReal++) = color; //color *pReal++ = 1; *pReal++ = 0; //uv *pReal++ = (x3 - page.CenterPoint.x); *pReal++ = (y3); *pReal++ = (z3 - page.CenterPoint.z); //pos *((uint *)pReal++) = color; //color *pReal++ = 0; *pReal++ = 1; //uv *pReal++ = (x4 - page.CenterPoint.x); *pReal++ = (y4); *pReal++ = (z4 - page.CenterPoint.z); //pos *((uint *)pReal++) = color; //color *pReal++ = 1; *pReal++ = 1; //uv //Update bounds if (y3 < minY) { minY = y1; } if (y4 < minY) { minY = y2; } if (y3 + scaleY > maxY) { maxY = y3 + scaleY; } if (y4 + scaleY > maxY) { maxY = y4 + scaleY; } } vbuf.Unlock(); subMesh.vertexData.vertexBufferBinding.SetBinding(0, vbuf); //Populate index buffer subMesh.indexData.indexStart = 0; subMesh.indexData.indexCount = 6 * quadCount; subMesh.indexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, subMesh.indexData.indexCount, BufferUsage.DynamicWriteOnly); ushort *pI = (ushort *)subMesh.indexData.indexBuffer.Lock(BufferLocking.Discard); for (ushort i = 0; i < quadCount; i++) { ushort ofset = (ushort)(i * 4); * pI++ = (ushort)(0 + ofset); * pI++ = (ushort)(2 + ofset); * pI++ = (ushort)(1 + ofset); *pI++ = (ushort)(1 + ofset); *pI++ = (ushort)(2 + ofset); *pI++ = (ushort)(3 + ofset); } subMesh.indexData.indexBuffer.Unlock(); //Finish up mesh AxisAlignedBox bounds = new AxisAlignedBox( new Vector3(page.Bounds.Left - page.CenterPoint.x, minY, page.Bounds.Top - page.CenterPoint.z), new Vector3(page.Bounds.Right - page.CenterPoint.x, maxY, page.Bounds.Bottom - page.CenterPoint.z)); mesh.BoundingBox = bounds; Vector3 tmp = bounds.Maximum - bounds.Minimum; mesh.BoundingSphereRadius = tmp.Length * 0.5f; mesh.Load(); //Apply grass material to mesh subMesh.MaterialName = layer.Material.Name; //Return the mesh return(mesh); } }
unsafe void DeformationMeshParallel() { Vertex[] vertices = new Vertex[vertex_count]; ushort[] indices = new ushort[index_count]; mesh.SubMeshes[0].VertexData.GetSomeGeometry(ref changeable_vertex_pos, ref changeable_vertex_norm); if (first_init_mesh == false) { /*for (int i = 0; i < vertex_count; i++) * { * Vertex vertex = new Vertex(); * vertex.position = original_vertex_pos[i]; * vertex.normal = original_vertex_norm[i]; * vertex.texCoord = original_vertex_tc[i]; * vertices[i] = vertex; * } * for (int i = 0; i < index_count; i++) * { * indices[i] = (ushort)(original_vertex_ind[i]); * }*/ ParallelLoopResult parallel_result = Parallel.For(0, vertex_count, i => { Vertex vertex = new Vertex(); vertex.position = original_vertex_pos[i]; vertex.normal = original_vertex_norm[i]; vertex.texCoord = original_vertex_tc[i]; vertices[i] = vertex; }); if (parallel_result.IsCompleted) { for (int i = 0; i < index_count; i++) { indices[i] = (ushort)(original_vertex_ind[i]); } } SubMesh sub_mesh = mesh.SubMeshes[0]; { HardwareVertexBuffer vertex_buffer = sub_mesh.VertexData.VertexBufferBinding.GetBuffer(0); IntPtr buffer = vertex_buffer.Lock(HardwareBuffer.LockOptions.Discard); fixed(Vertex *pvertices = vertices) { NativeUtils.CopyMemory(buffer, (IntPtr)pvertices, vertices.Length * sizeof(Vertex)); } vertex_buffer.Unlock(); } { HardwareIndexBuffer index_buffer = sub_mesh.IndexData.IndexBuffer; IntPtr buffer = index_buffer.Lock(HardwareBuffer.LockOptions.Discard); fixed(ushort *pindices = indices) { NativeUtils.CopyMemory(buffer, (IntPtr)pindices, indices.Length * sizeof(ushort)); } index_buffer.Unlock(); } first_init_mesh = true; } else { if (hit_other != null) { ParallelLoopResult parallel_result = Parallel.For(0, vertex_count, i => { Vertex vertex = new Vertex(); Vec3 p = ((original_vertex_pos[i] * attached_mesh.ScaleOffset) * Rotation) + (Position + attached_mesh.PositionOffset); Vec3 pp = hit_pos; Sphere sp = new Sphere(pp, Type.CONF.DeformationRadius); Vec3 nvec = Vec3.Zero; Vec3 nnorm = Vec3.Zero; if (sp.IsContainsPoint(p)) { Ray ray = new Ray(p, changeable_vertex_norm[i] * .01f); if (!Single.IsNaN(ray.Direction.X) && !Single.IsNaN(ray.Origin.X)) { RayCastResult[] piercingResult = PhysicsWorld.Instance.RayCastPiercing( ray, (int)ContactGroup.CastOnlyDynamic);/*(int)ContactGroup.CastOnlyContact);*/ Vec3 collision_pos = Vec3.Zero; Vec3 collision_nor = Vec3.Zero; bool collision = false; foreach (RayCastResult result in piercingResult) { if (Array.IndexOf(PhysicsModel.Bodies, result.Shape.Body) != -1) { continue; } collision = true; collision_pos = result.Position; collision_nor = result.Normal; break; } if (collision) { float old_x = 0, old_y = 0, old_z = 0, new_x = 0, new_y = 0, new_z = 0; float deformation = 0, force = 0, max_deformation = Type.CONF.MaxStrengthDeformation, mass = 0, vel = 0; mass = hit_other.Body.Mass; vel = hit_other.Body.LastStepLinearVelocity.Length(); force = (((hit_this.Body.Mass * hit_this.Body.LastStepLinearVelocity.Length()) + (mass * vel)) / hit_this.Body.Mass) / 100.0f; if (force > max_deformation) { deformation = max_deformation; } else { deformation = force; } //Deform X if (changeable_vertex_pos[i].X > 0) { old_x = original_vertex_pos[i].X - deformation; if (old_x < changeable_vertex_pos[i].X) { new_x = old_x; } else { new_x = changeable_vertex_pos[i].X; } } else { old_x = original_vertex_pos[i].X + deformation; if (old_x > changeable_vertex_pos[i].X) { new_x = old_x; } else { new_x = changeable_vertex_pos[i].X; } } //Deform Y if (changeable_vertex_pos[i].Y > 0) { old_y = original_vertex_pos[i].Y - deformation; if (old_y < changeable_vertex_pos[i].Y) { new_y = old_y; } else { new_y = changeable_vertex_pos[i].Y; } } else { old_y = original_vertex_pos[i].Y + deformation; if (old_y > changeable_vertex_pos[i].Y) { new_y = old_y; } else { new_y = changeable_vertex_pos[i].Y; } } //Deform Z if (changeable_vertex_pos[i].Z > 0) { old_z = original_vertex_pos[i].Z - deformation; if (old_z < changeable_vertex_pos[i].Z) { new_z = old_z; } else { new_z = changeable_vertex_pos[i].Z; } } else { old_z = original_vertex_pos[i].Z + deformation; if (old_z > changeable_vertex_pos[i].Z) { new_z = old_z; } else { new_z = changeable_vertex_pos[i].Z; } } nvec = new Vec3(new_x, new_y, new_z); nnorm = -collision_nor; } else { nvec = changeable_vertex_pos[i]; nnorm = changeable_vertex_norm[i]; } } } else { nvec = changeable_vertex_pos[i]; nnorm = changeable_vertex_norm[i]; } vertex.position = nvec; vertex.normal = nnorm; vertex.texCoord = original_vertex_tc[i]; vertices[i] = vertex; }); if (parallel_result.IsCompleted) { for (int i = 0; i < index_count; i++) { indices[i] = (ushort)(original_vertex_ind[i]); } SubMesh sub_mesh = mesh.SubMeshes[0]; { HardwareVertexBuffer vertex_buffer = sub_mesh.VertexData.VertexBufferBinding.GetBuffer(0); IntPtr buffer = vertex_buffer.Lock(HardwareBuffer.LockOptions.Discard); fixed(Vertex *pvertices = vertices) { NativeUtils.CopyMemory(buffer, (IntPtr)pvertices, vertices.Length * sizeof(Vertex)); } vertex_buffer.Unlock(); } { HardwareIndexBuffer index_buffer = sub_mesh.IndexData.IndexBuffer; IntPtr buffer = index_buffer.Lock(HardwareBuffer.LockOptions.Discard); fixed(ushort *pindices = indices) { NativeUtils.CopyMemory(buffer, (IntPtr)pindices, indices.Length * sizeof(ushort)); } index_buffer.Unlock(); } } } hit_other = null; } }
/// <summary> /// /// </summary> /// <param name="page"></param> /// <param name="layer"></param> /// <param name="grassPostions"></param> /// <param name="grassCount"></param> /// <returns></returns> private Mesh GenerateGrassSprite(PageInfo page, GrassLayer layer, IntPtr grassPostions, int grassCount) { //Calculate the number of quads to be added int quadCount = grassCount; //Create manual mesh to store grass quads Mesh mesh = (Mesh)MeshManager.Instance.CreateManual(GetUniqueID(), ResourceGroupManager.DefaultResourceGroupName, null); SubMesh subMesh = mesh.CreateSubMesh(); subMesh.useSharedVertices = false; //Setup vertex format information subMesh.vertexData = new VertexData(); subMesh.vertexData.vertexStart = 0; subMesh.vertexData.vertexCount = 4 * quadCount; VertexDeclaration dcl = subMesh.vertexData.vertexDeclaration; int offset = 0; dcl.AddElement(0, offset, VertexElementType.Float3, VertexElementSemantic.Position); offset += VertexElement.GetTypeSize(VertexElementType.Float3); dcl.AddElement(0, offset, VertexElementType.Float4, VertexElementSemantic.Normal); offset += VertexElement.GetTypeSize(VertexElementType.Float4); dcl.AddElement(0, offset, VertexElementType.Color, VertexElementSemantic.Diffuse); offset += VertexElement.GetTypeSize(VertexElementType.Color); dcl.AddElement(0, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords); offset += VertexElement.GetTypeSize(VertexElementType.Float2); //Populate a new vertex buffer with grass HardwareVertexBuffer vbuf = HardwareBufferManager.Instance.CreateVertexBuffer( /*offset*/ dcl, subMesh.vertexData.vertexCount, BufferUsage.DynamicWriteOnly, false); unsafe { float *pReal = (float *)vbuf.Lock(BufferLocking.Discard); //Calculate size variance float rndWidth = layer.mMaxWidth - layer.mMinWidth; float rndHeight = layer.mMaxHeight - layer.mMinHeight; float minY = float.PositiveInfinity, maxY = float.NegativeInfinity; float *posPtr = (float *)grassPostions; //Position array "iterator" for (int i = 0; i < grassCount; i++) { //Get the x and z positions from the position array float x = *posPtr++; float z = *posPtr++; //Calculate height float y = 0; if (mHeightFunction != null) { y = mHeightFunction.GetHeightAt(x, z, mHeightFunctionUserData); } else { y = 0; } float x1 = (x - page.CenterPoint.x); float z1 = (z - page.CenterPoint.z); //Get the color at the grass position uint color = 0; if (layer.ColorMap != null) { color = layer.ColorMap.GetColorAt(x, z); } else { color = 0xFFFFFFFF; } //Calculate size float rnd = MogreLibMath.Utility.UnitRandom();//The same rnd value is used for width and height to maintain aspect ratio float halfXScale = (layer.mMinWidth + rndWidth * rnd) * 0.5f; float scaleY = (layer.mMinWidth + rndHeight * rnd); //Randomly mirror grass textures float uvLeft, uvRight; if (MogreLibMath.Utility.UnitRandom() > 0.5f) { uvLeft = 0; uvRight = 1; } else { uvLeft = 1; uvRight = 0; } //Add vertices *pReal++ = x1; *pReal++ = y; *pReal++ = z1; //center position *pReal++ = -halfXScale; *pReal++ = scaleY; *pReal++ = 0; *pReal++ = 0; //normal (used to store relative corner positions) *((uint *)pReal++) = color; //color *pReal++ = uvLeft; *pReal++ = 0; //uv *pReal++ = x1; *pReal++ = y; *pReal++ = z1; //center position *pReal++ = +halfXScale; *pReal++ = scaleY; *pReal++ = 0; *pReal++ = 0; //normal (used to store relative corner positions) *((uint *)pReal++) = color; //color *pReal++ = uvRight; *pReal++ = 0; //uv *pReal++ = x1; *pReal++ = y; *pReal++ = z1; //center position *pReal++ = -halfXScale; *pReal++ = 0.0f; *pReal++ = 0; *pReal++ = 0; //normal (used to store relative corner positions) *((uint *)pReal++) = color; //color *pReal++ = uvLeft; *pReal++ = 1; //uv *pReal++ = x1; *pReal++ = y; *pReal++ = z1; //center position *pReal++ = +halfXScale; *pReal++ = 0.0f; *pReal++ = 0; *pReal++ = 0; //normal (used to store relative corner positions) *((uint *)pReal++) = color; //color *pReal++ = uvRight; *pReal++ = 1; //uv //Update bounds if (y < minY) { minY = y; } if (y + scaleY > maxY) { maxY = y + scaleY; } } vbuf.Unlock(); subMesh.vertexData.vertexBufferBinding.SetBinding(0, vbuf); //Populate index buffer subMesh.indexData.indexStart = 0; subMesh.indexData.indexCount = 6 * quadCount; subMesh.indexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, subMesh.indexData.indexCount, BufferUsage.DynamicWriteOnly); ushort *pI = (ushort *)subMesh.indexData.indexBuffer.Lock(BufferLocking.Discard); for (ushort i = 0; i < quadCount; i++) { ushort ofset = (ushort)(i * 4); * pI++ = (ushort)(0 + ofset); * pI++ = (ushort)(2 + ofset); * pI++ = (ushort)(1 + ofset); *pI++ = (ushort)(1 + ofset); *pI++ = (ushort)(2 + ofset); *pI++ = (ushort)(3 + ofset); } subMesh.indexData.indexBuffer.Unlock(); //Finish up mesh AxisAlignedBox bounds = new AxisAlignedBox( new Vector3(page.Bounds.Left - page.CenterPoint.x, minY, page.Bounds.Top - page.CenterPoint.z), new Vector3(page.Bounds.Right - page.CenterPoint.x, maxY, page.Bounds.Bottom - page.CenterPoint.z)); mesh.BoundingBox = bounds; Vector3 tmp = bounds.Maximum - bounds.Minimum; mesh.BoundingSphereRadius = tmp.Length * 0.5f; mesh.Load(); //Apply grass material to mesh subMesh.MaterialName = layer.Material.Name; //Return the mesh return(mesh); } }
protected void EnsureObjectsCreated() { ClearCreatedObjects(); Texture prototypeTexture = null; if (useTextures) { prototypeMaterial = MaterialManager.Instance.Load("barrel.barrel"); if (uniqueTextures) { prototypeTexture = TextureManager.Instance.Load("blank.dds"); } } else { prototypeMaterial = MaterialManager.Instance.Load("unit_box.unit_box"); } prototypeMaterial.Compile(); if (objectCount == 0) { return; } int materialCount = (animatedObjects ? 0 : (numObjectsSharingMaterial == 0 ? objectCount : (numObjectsSharingMaterial >= objectCount ? 1 : (objectCount + numObjectsSharingMaterial - 1) / numObjectsSharingMaterial))); materialCountLabel.Text = "Material Count: " + materialCount; if (whichObjects == WhichObjectsEnum.woPlane || whichObjects == WhichObjectsEnum.woRandom) { Mesh plane = meshes[(int)WhichObjectsEnum.woPlane]; if (plane != null) { plane.Unload(); } // Create the plane float planeSide = 1000f; int planeUnits = Int32.Parse(planeUnitsTextBox.Text); plane = MeshManager.Instance.CreatePlane("testerPlane", new Plane(Vector3.UnitZ, Vector3.Zero), planeSide, planeSide, planeUnits, planeUnits, true, 1, planeSide / planeUnits, planeSide / planeUnits, Vector3.UnitY); meshes[(int)WhichObjectsEnum.woPlane] = plane; } // Create the new materials for (int i = 0; i < materialCount; i++) { Material mat = prototypeMaterial.Clone("mat" + i); Pass p = mat.GetTechnique(0).GetPass(0); if (!animatedObjects && uniqueTextures) { Texture t = prototypeTexture; Texture texture = TextureManager.Instance.CreateManual("texture" + i, t.TextureType, t.Width, t.Height, t.NumMipMaps, t.Format, t.Usage); textureList.Add(texture); p.CreateTextureUnitState(texture.Name); } // Make the materials lovely shades of blue p.Ambient = new ColorEx(1f, .2f, .2f, (1f / materialCount) * i); p.Diffuse = new ColorEx(p.Ambient); p.Specular = new ColorEx(1f, 0f, 0f, 0f); materialList.Add(mat); } // Create the entities and scene nodes for (int i = 0; i < objectCount; i++) { Mesh mesh = selectMesh(); Material mat = null; if (materialCount > 0) { mat = materialList[i % materialCount]; } Entity entity = scene.CreateEntity("entity" + i, mesh); if (animatedObjects) { string[] visibleSubs = visibleSubMeshes[(int)whichObjects - (int)WhichObjectsEnum.woZombie]; for (int j = 0; j < entity.SubEntityCount; ++j) { SubEntity sub = entity.GetSubEntity(j); bool visible = false; foreach (string s in visibleSubs) { if (s == sub.SubMesh.Name) { visible = true; break; } } sub.IsVisible = visible; if (visible) { totalVertexCount += sub.SubMesh.VertexData.vertexCount; } } } else { if (mesh.SharedVertexData != null) { totalVertexCount += mesh.SharedVertexData.vertexCount; } else { for (int j = 0; j < mesh.SubMeshCount; j++) { SubMesh subMesh = mesh.GetSubMesh(j); totalVertexCount += subMesh.VertexData.vertexCount; } } } if (animatedObjects && animateCheckBox.Checked) { AnimationState currentAnimation = entity.GetAnimationState(GetAnimationName()); currentAnimation.IsEnabled = true; if (!animationInitialized) { currentAnimationLength = entity.GetAnimationState(GetAnimationName()).Length; animationInitialized = true; } } if (mat != null) { entity.MaterialName = mat.Name; } entityList.Add(entity); SceneNode node = scene.RootSceneNode.CreateChildSceneNode(); sceneNodeList.Add(node); node.AttachObject(entity); node.Position = new Vector3(randomCoord(), randomCoord(), randomCoord()); if (randomSizes) { node.ScaleFactor = Vector3.UnitScale * randomScale(); } else if (randomScales) { node.ScaleFactor = new Vector3(randomScale(), randomScale(), randomScale()); } else { node.ScaleFactor = Vector3.UnitScale * 1f; } if (randomOrientations) { Vector3 axis = new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()); node.Orientation = Vector3.UnitY.GetRotationTo(axis.ToNormalized()); } else { node.Orientation = Quaternion.Identity; } } }
static void SaveLWO(bool exportUV) { // Error check if (Selection.activeTransform == null) { Debug.LogWarning("Please select the model you want to export"); return; } // Get stuff GameObject parent = Selection.activeTransform.gameObject; string modelName = parent.name; MeshRenderer[] meshRenderers = parent.GetComponentsInChildren <MeshRenderer>(); // Loop through stuff List <Material> surfaces = new List <Material>(); List <string> surfaceNames = new List <string>(); CustomMesh mesh = new CustomMesh(); int vertBoost = 0; for (int i = 0; i < meshRenderers.Length; i++) { // Get MeshFilter MeshFilter meshFilter = meshRenderers[i].gameObject.GetComponent <MeshFilter>(); if (meshFilter.sharedMesh.subMeshCount != meshRenderers[i].sharedMaterials.Length) { Debug.LogError("SubMesh count and material count don't match on " + meshRenderers[i].gameObject.name); return; } // Fill out surface lists foreach (Material material in meshRenderers[i].sharedMaterials) { // Moar error check if (material == null) { Debug.LogError("Material slot is null on " + meshRenderers[i].gameObject.name); return; } if (material.shader.name != "Rock Raiders" && material.shader.name != "Rock Raiders Transparent") { Debug.LogError(material.name + " doesn't use a Rock Raiders shader"); return; } // Surface stuff if (!surfaceNames.Contains(material.name)) { surfaces.Add(material); surfaceNames.Add(material.name); } } // Fill out our CustomMesh // verts foreach (Vector3 vertex in meshFilter.sharedMesh.vertices) { mesh.vertices.Add(meshFilter.gameObject.transform.TransformPoint(vertex)); } // normals - these won't be exported, but used later for determining which verts to merge in the LWO, so the smoothing the game calculates is correct if (meshFilter.sharedMesh.normals.Length == 0) { // default normals - zero is fine for this, the actual value doesn't really matter, we're only gonna be checking if verts have equal normals to each other for (int j = 0; j < meshFilter.sharedMesh.vertices.Length; j++) { mesh.normals.Add(Vector3.zero); } } else { // use normals if present foreach (Vector3 normal in meshFilter.sharedMesh.normals) { mesh.normals.Add(normal); } } // UV if (meshFilter.sharedMesh.uv.Length == 0) { // default UVs for (int j = 0; j < meshFilter.sharedMesh.vertices.Length; j++) { // these will be 0, 0 in the final UV file once flipped mesh.uv.Add(new Vector2(0.0f, 1.0f)); } } else { // use UVs if present foreach (Vector2 uv in meshFilter.sharedMesh.uv) { mesh.uv.Add(uv); } } // tris/submeshes for (int j = 0; j < meshFilter.sharedMesh.subMeshCount; j++) { SubMesh subMesh = new SubMesh(); subMesh.triangles = meshFilter.sharedMesh.GetTriangles(j); // reverse winding order for negative scale if (meshFilter.gameObject.transform.localToWorldMatrix.determinant < 0.0f) { for (int k = 0; k < subMesh.triangles.Length; k += 3) { int temp = subMesh.triangles[k]; subMesh.triangles[k] = subMesh.triangles[k + 2]; subMesh.triangles[k + 2] = temp; } } // vert boost for (int k = 0; k < subMesh.triangles.Length; k++) { subMesh.triangles[k] += vertBoost; } subMesh.material = meshRenderers[i].sharedMaterials[j]; mesh.subMeshes.Add(subMesh); } vertBoost += meshFilter.sharedMesh.vertices.Length; } // make condensed list of verts with only those that have different positions and normals (no UV splits etc) - so only intentionally unwelded verts will be unwelded in the LWO List <Vertex> uniqueVerts = new List <Vertex>(); int[] redirectArray = new int[mesh.vertices.Count]; for (int i = 0; i < mesh.vertices.Count; i++) { Vertex vertex; vertex.position = mesh.vertices[i]; vertex.normal = mesh.normals[i]; if (!uniqueVerts.Contains(vertex)) { uniqueVerts.Add(vertex); } int newVertexIndex; int findResults = uniqueVerts.IndexOf(vertex); if (findResults == -1) { uniqueVerts.Add(vertex); newVertexIndex = uniqueVerts.Count - 1; } else { newVertexIndex = findResults; } redirectArray[i] = newVertexIndex; } // Get path string path = EditorUtility.SaveFilePanel("Save LWO", "", modelName + ".lwo", "lwo"); if (string.IsNullOrEmpty(path)) { return; } // Start writing stuff FileStream fileStream = new FileStream(path, FileMode.Create); BinaryWriter binaryWriter = new BinaryWriter2(fileStream); long rememberMe; binaryWriter.Write("FORMtempLWOB".ToCharArray()); // PNTS binaryWriter.Write("PNTS".ToCharArray()); // Temp length binaryWriter.Write("temp".ToCharArray()); rememberMe = fileStream.Position; foreach (Vertex vertex in uniqueVerts) { binaryWriter.Write(-vertex.position.x); binaryWriter.Write(vertex.position.y); binaryWriter.Write(-vertex.position.z); } FinishWritingChunk(fileStream, binaryWriter, rememberMe); // SRFS binaryWriter.Write("SRFS".ToCharArray()); // Temp length binaryWriter.Write("temp".ToCharArray()); rememberMe = fileStream.Position; foreach (string surfaceName in surfaceNames) { binaryWriter.Write(surfaceName.ToCharArray()); binaryWriter.Write('\0'); // padding if (surfaceName.Length % 2 == 0) { binaryWriter.Write('\0'); } } FinishWritingChunk(fileStream, binaryWriter, rememberMe); // POLS binaryWriter.Write("POLS".ToCharArray()); // Temp length binaryWriter.Write("temp".ToCharArray()); rememberMe = fileStream.Position; for (int i = 0; i < mesh.subMeshes.Count; i++) { int surfaceIndex = surfaceNames.IndexOf(mesh.subMeshes[i].material.name) + 1; int[] tris = mesh.subMeshes[i].triangles; for (int j = 0; j < tris.Length; j += 3) { binaryWriter.Write((UInt16)3); // How many verts binaryWriter.Write((UInt16)redirectArray[tris[j]]); binaryWriter.Write((UInt16)redirectArray[tris[j + 1]]); binaryWriter.Write((UInt16)redirectArray[tris[j + 2]]); binaryWriter.Write((UInt16)surfaceIndex); } } FinishWritingChunk(fileStream, binaryWriter, rememberMe); // SURFs foreach (Material surface in surfaces) { binaryWriter.Write("SURF".ToCharArray()); // Temp length binaryWriter.Write("temp".ToCharArray()); rememberMe = fileStream.Position; binaryWriter.Write(surface.name.ToCharArray()); binaryWriter.Write('\0'); // padding if (surface.name.Length % 2 == 0) { binaryWriter.Write('\0'); } // COLR binaryWriter.Write("COLR".ToCharArray()); binaryWriter.Write((UInt16)4); Color32 color = (Color32)surface.GetColor("_Color"); binaryWriter.Write(color.r); binaryWriter.Write(color.g); binaryWriter.Write(color.b); binaryWriter.Write((byte)0); // FLAG binaryWriter.Write("FLAG".ToCharArray()); binaryWriter.Write((UInt16)2); int flag = 0; if (surface.GetFloat("_Luminosity") != 0.0f) { flag++; } flag += 4; // smoothing if (surface.GetFloat("_Additive") != 0.0f) { flag += 512; } binaryWriter.Write((UInt16)flag); // DIFF if (surface.GetFloat("_Diffuse") != 0.0f) { binaryWriter.Write("DIFF".ToCharArray()); binaryWriter.Write((UInt16)2); binaryWriter.Write((UInt16)(surface.GetFloat("_Diffuse") * 256.0f)); } // TRAN if (surface.GetFloat("_Transparency") != 0.0f) { binaryWriter.Write("TRAN".ToCharArray()); binaryWriter.Write((UInt16)2); binaryWriter.Write((UInt16)(surface.GetFloat("_Transparency") * 256.0f)); } // LUMI if (surface.GetFloat("_Luminosity") != 0.0f) { binaryWriter.Write("LUMI".ToCharArray()); binaryWriter.Write((UInt16)2); binaryWriter.Write((UInt16)(surface.GetFloat("_Luminosity") * 256.0f)); } if (!exportUV && surface.GetTexture("_MainTex") != null) { // CTEX binaryWriter.Write("CTEX".ToCharArray()); binaryWriter.Write((UInt16)18); binaryWriter.Write("Planar Image Map".ToCharArray()); binaryWriter.Write('\0'); binaryWriter.Write('\0'); // TIMG binaryWriter.Write("TIMG".ToCharArray()); // Temp length binaryWriter.Write("te".ToCharArray()); long rememberMe2 = fileStream.Position; string texturePath = null; string sequence; if (surface.GetFloat("_Sequence") != 0.0f) { sequence = " (sequence)"; } else { sequence = ""; } if (surface.GetFloat("_SharedTexture") != 0.0f) { texturePath = @"\\dummy\" + surface.GetTexture("_MainTex").name + ".bmp" + sequence; } else { texturePath = @"D:\dummy\" + surface.GetTexture("_MainTex").name + ".bmp" + sequence; } binaryWriter.Write(texturePath.ToCharArray()); binaryWriter.Write('\0'); // padding if (texturePath.Length % 2 == 0) { binaryWriter.Write('\0'); } FinishWritingSurfChunk(fileStream, binaryWriter, rememberMe2); // TFLG binaryWriter.Write("TFLG".ToCharArray()); binaryWriter.Write((UInt16)2); int textureFlag = 0; if (surface.GetFloat("_X") != 0.0f) { textureFlag++; } else if (surface.GetFloat("_Y") != 0.0f) { textureFlag += 2; } else if (surface.GetFloat("_Z") != 0.0f) { textureFlag += 4; } else { // default to z like the game seems to do if none are specified textureFlag += 4; } if (surface.GetFloat("_PixelBlending") != 0.0f) { textureFlag += 32; } binaryWriter.Write((UInt16)textureFlag); // TSIZ binaryWriter.Write("TSIZ".ToCharArray()); binaryWriter.Write((UInt16)12); binaryWriter.Write(surface.GetFloat("_TextureSizeX")); binaryWriter.Write(surface.GetFloat("_TextureSizeY")); binaryWriter.Write(surface.GetFloat("_TextureSizeZ")); // TCTR binaryWriter.Write("TCTR".ToCharArray()); binaryWriter.Write((UInt16)12); binaryWriter.Write(surface.GetFloat("_TextureCenterX")); binaryWriter.Write(surface.GetFloat("_TextureCenterY")); binaryWriter.Write(surface.GetFloat("_TextureCenterZ")); } FinishWritingChunk(fileStream, binaryWriter, rememberMe); } // Final length fileStream.Seek(4, SeekOrigin.Begin); binaryWriter.Write((UInt32)(fileStream.Length - 8)); binaryWriter.Close(); fileStream.Close(); Debug.Log("Saved file " + path); // UV TIME if (!exportUV) { return; } StringBuilder uvString = new StringBuilder(); uvString.Append("2\n"); uvString.Append(surfaces.Count).Append("\n"); foreach (string surfaceName in surfaceNames) { uvString.Append(surfaceName).Append("\n"); } foreach (Material surface in surfaces) { string texturePath; string sequence; if (surface.GetFloat("_Sequence") != 0.0f) { sequence = " (sequence)"; } else { sequence = ""; } if (surface.GetTexture("_MainTex") == null) { texturePath = "NULL"; } else if (surface.GetFloat("_SharedTexture") != 0.0f) { texturePath = @"\\dummy\" + surface.GetTexture("_MainTex").name + ".bmp" + sequence; } else { texturePath = @"D:\dummy\" + surface.GetTexture("_MainTex").name + ".bmp" + sequence; } uvString.Append(texturePath).Append("\n"); } int totalIndexCount = 0; foreach (SubMesh subMesh in mesh.subMeshes) { totalIndexCount += subMesh.triangles.Length; } uvString.Append(totalIndexCount / 3).Append("\n"); int whatever = 0; foreach (SubMesh subMesh in mesh.subMeshes) { for (int i = 0; i < subMesh.triangles.Length; i += 3) { uvString.Append(whatever).Append(" 3\n"); uvString.Append(mesh.uv[subMesh.triangles[i]].x).Append(" ").Append(-mesh.uv[subMesh.triangles[i]].y + 1.0f).Append(" 0\n"); uvString.Append(mesh.uv[subMesh.triangles[i + 1]].x).Append(" ").Append(-mesh.uv[subMesh.triangles[i + 1]].y + 1.0f).Append(" 0\n"); uvString.Append(mesh.uv[subMesh.triangles[i + 2]].x).Append(" ").Append(-mesh.uv[subMesh.triangles[i + 2]].y + 1.0f).Append(" 0\n"); whatever++; } } // dummy data for (int i = 0; i < surfaces.Count; i++) { uvString.Append("4\n0.000000 0.000000 0.000000\n0.000000 0.000000 0.000000\n0.000000 0.000000 0.000000\n1.000000 1.000000 1.000000\n"); } string uvPath = Path.ChangeExtension(path, ".uv"); File.WriteAllText(uvPath, uvString.ToString()); Debug.Log("Saved file " + uvPath); }
/// <summary> /// Apply all model combines and seal builder. /// </summary> public void Apply() { // Do nothing if sealed if (isSealed) { return; } // Count total vertices and indices int totalVertices = 0; int totalIndices = 0; foreach (var item in builderDictionary) { totalVertices += item.Value.Vertices.Count; totalIndices += item.Value.Indices.Count; } // Create combined data combinedModel = new CombinedModel(); combinedModel.Vertices = new Vector3[totalVertices]; combinedModel.Normals = new Vector3[totalVertices]; combinedModel.UVs = new Vector2[totalVertices]; combinedModel.Indices = new int[totalIndices]; combinedModel.SubMeshes = new SubMesh[builderDictionary.Count]; // Populate static arrays int currentVertex = 0; int currentIndex = 0; int subMeshIndex = 0; foreach (var item in builderDictionary) { // Save current highest vertex and index int highestVertex = currentVertex; int highestIndex = currentIndex; // Copy vertex data for (int i = 0; i < item.Value.Vertices.Count; i++) { combinedModel.Vertices[currentVertex] = item.Value.Vertices[i]; combinedModel.Normals[currentVertex] = item.Value.Normals[i]; combinedModel.UVs[currentVertex] = item.Value.UVs[i]; currentVertex++; } // Copy index data for (int i = 0; i < item.Value.Indices.Count; i++) { combinedModel.Indices[currentIndex++] = highestVertex + i; } // Add submesh int frame; SubMesh sm = new SubMesh(); sm.StartIndex = highestIndex; sm.PrimitiveCount = item.Value.Indices.Count / 3; MaterialReader.ReverseTextureKey(item.Key, out sm.TextureArchive, out sm.TextureRecord, out frame); combinedModel.SubMeshes[subMeshIndex++] = sm; } Seal(); }
public Mesh Import(string filename) { using (var importer = new AssimpContext()) { //importer.AttachLogStream(new LogStream((msg, userData) => //{ // Common.Log.WriteLine(msg); //})); var mesh = new Mesh(); importer.SetConfig(new Assimp.Configs.VertexBoneWeightLimitConfig(4)); //importer.ZAxisRotation = (float)(System.Math.PI / 2.0); var model = importer.ImportFile(filename, PostProcessSteps.CalculateTangentSpace | PostProcessSteps.Triangulate | PostProcessSteps.GenerateNormals | PostProcessSteps.LimitBoneWeights | PostProcessSteps.GenerateUVCoords); foreach (var meshToImport in model.Meshes) { // Validate sub mesh data if (meshToImport.PrimitiveType != PrimitiveType.Triangle) { Common.Log.WriteLine("{0}:{1} invalid primitive type {2} should be Triangle", filename, meshToImport.Name, meshToImport.PrimitiveType); continue; } if (!meshToImport.HasNormals) { Common.Log.WriteLine("{0}:{1} does not have any normals", filename, meshToImport.Name); continue; } if (!meshToImport.HasTangentBasis) { Common.Log.WriteLine("{0}:{1} does not have any tangents", filename, meshToImport.Name); continue; } if (meshToImport.TextureCoordinateChannelCount == 0) { Common.Log.WriteLine("{0}:{1} does not have any texture channels", filename, meshToImport.Name); continue; } var subMesh = new SubMesh(); subMesh.BoundingSphereRadius = 0; // Create vertex format if (meshToImport.HasBones) { subMesh.VertexFormat = new Renderer.VertexFormat(new Renderer.VertexFormatElement[] { new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.Position, Renderer.VertexPointerType.Float, 3, 0), new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.Normal, Renderer.VertexPointerType.Float, 3, sizeof(float) * 3), new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.Tangent, Renderer.VertexPointerType.Float, 3, sizeof(float) * 6), new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.TexCoord, Renderer.VertexPointerType.Float, 2, sizeof(float) * 9), new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.BoneIndex, Renderer.VertexPointerType.Float, 4, sizeof(float) * 11), new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.BoneWeight, Renderer.VertexPointerType.Float, 4, sizeof(float) * 15), }); } else { subMesh.VertexFormat = new Renderer.VertexFormat(new Renderer.VertexFormatElement[] { new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.Position, Renderer.VertexPointerType.Float, 3, 0), new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.Normal, Renderer.VertexPointerType.Float, 3, sizeof(float) * 3), new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.Tangent, Renderer.VertexPointerType.Float, 3, sizeof(float) * 6), new Renderer.VertexFormatElement(Renderer.VertexFormatSemantic.TexCoord, Renderer.VertexPointerType.Float, 2, sizeof(float) * 9), }); } subMesh.TriangleCount = meshToImport.FaceCount; Vertex[] vertices = new Vertex[meshToImport.VertexCount]; var positions = meshToImport.Vertices; var normals = meshToImport.Normals; var tangents = meshToImport.Tangents; var texCoords = meshToImport.TextureCoordinateChannels[0]; // Setup vertex data for (var i = 0; i < vertices.Length; i++) { vertices[i].Position = new Vector3(positions[i].X, positions[i].Y, positions[i].Z); vertices[i].Normal = new Vector3(normals[i].X, normals[i].Y, normals[i].Z); vertices[i].Tangent = new Vector3(tangents[i].X, tangents[i].Y, tangents[i].Z); vertices[i].TexCoord = new Vector2(texCoords[i].X, texCoords[i].Y); var length = vertices[i].Position.Length; if (subMesh.BoundingSphereRadius < length) subMesh.BoundingSphereRadius = length; } // Map bone weights if they are available if (meshToImport.HasBones) { var bones = meshToImport.Bones; for (var i = 0; i < bones.Count; i++) { var bone = bones[i]; if (!bone.HasVertexWeights) continue; foreach (var weight in bone.VertexWeights) { var index = weight.VertexID; var vertex = vertices[index]; if (vertex.BoneCount == 0) { vertex.BoneIndex.X = i; vertex.BoneWeight.X = weight.Weight; } else if (vertex.BoneCount == 1) { vertex.BoneIndex.Y = i; vertex.BoneWeight.Y = weight.Weight; } else if (vertex.BoneCount == 2) { vertex.BoneIndex.Z = i; vertex.BoneWeight.Z = weight.Weight; } else if (vertex.BoneCount == 3) { vertex.BoneIndex.W = i; vertex.BoneWeight.W = weight.Weight; } vertex.BoneCount++; vertices[index] = vertex; } } } using (var memStream = new MemoryStream(meshToImport.VertexCount * subMesh.VertexFormat.Size)) { using (var writer = new BinaryWriter(memStream)) { for (int i = 0; i < meshToImport.VertexCount; i++) { writer.Write(vertices[i].Position); writer.Write(vertices[i].Normal); writer.Write(vertices[i].Tangent); writer.Write(vertices[i].TexCoord); if (meshToImport.HasBones) { writer.Write(vertices[i].BoneIndex); writer.Write(vertices[i].BoneWeight); } } subMesh.Vertices = memStream.GetBuffer(); } } using (var memStream = new MemoryStream(meshToImport.VertexCount * subMesh.VertexFormat.Size)) { using (var writer = new BinaryWriter(memStream)) { var indices = meshToImport.GetIndices(); foreach (var index in indices) { writer.Write(index); } subMesh.Indices = memStream.GetBuffer(); } } if (model.HasMaterials) { var material = model.Materials[meshToImport.MaterialIndex].Name; if (!material.StartsWith("/materials/")) { material = "/materials/" + material; } subMesh.Material = material; } else { subMesh.Material = "no_material"; } mesh.SubMeshes.Add(subMesh); } return mesh; } }
void VertexUV(SubMesh data, CardShape shape, Vector3 pos, Vector2 uv) { data.AddVertex(pos, uv, Color.white); }
private unsafe void UpdateGeometry() { DestroyGeometry(); Curve positionCurve = GetPositionCurve(); Curve radiusCurve = null; { bool existsSpecialRadius = false; foreach (MapCurvePoint point in Points) { RenderableCurvePoint point2 = point as RenderableCurvePoint; if (point2 != null && point2.OverrideRadius >= 0) { existsSpecialRadius = true; break; } } if (existsSpecialRadius) { switch (radiusCurveType) { case RadiusCurveTypes.UniformCubicSpline: radiusCurve = new UniformCubicSpline(); break; case RadiusCurveTypes.Bezier: radiusCurve = new BezierCurve(); break; case RadiusCurveTypes.Line: radiusCurve = new LineCurve(); break; } for (int n = 0; n < Points.Count; n++) { MapCurvePoint point = Points[n]; if (!point.Editor_IsExcludedFromWorld()) { float rad = radius; RenderableCurvePoint renderableCurvePoint = point as RenderableCurvePoint; if (renderableCurvePoint != null && renderableCurvePoint.OverrideRadius >= 0) { rad = renderableCurvePoint.OverrideRadius; } radiusCurve.AddValue(point.Time, new Vec3(rad, 0, 0)); } } } } //create mesh Vertex[] vertices = null; int[] indices = null; if (positionCurve != null && positionCurve.Values.Count > 1 && Points.Count >= 2) { Vec3 positionOffset = -Position; int steps = (Points.Count - 1) * pathSteps + 1; int vertexCount = steps * (shapeSegments + 1); int indexCount = (steps - 1) * shapeSegments * 2 * 3; vertices = new Vertex[vertexCount]; indices = new int[indexCount]; //fill data { int currentVertex = 0; int currentIndex = 0; float currentDistance = 0; Vec3 lastPosition = Vec3.Zero; Quat lastRot = Quat.Identity; for (int nStep = 0; nStep < steps; nStep++) { int startStepVertexIndex = currentVertex; float coefficient = (float)nStep / (float)(steps - 1); Vec3 pos = CalculateCurvePointByCoefficient(coefficient) + positionOffset; Quat rot; { Vec3 v = CalculateCurvePointByCoefficient(coefficient + .3f / (float)(steps - 1)) - CalculateCurvePointByCoefficient(coefficient); if (v != Vec3.Zero) { rot = Quat.FromDirectionZAxisUp(v.GetNormalize()); } else { rot = lastRot; } } if (nStep != 0) { currentDistance += (pos - lastPosition).Length(); } float rad; if (radiusCurve != null) { Range range = new Range(radiusCurve.Times[0], radiusCurve.Times[radiusCurve.Times.Count - 1]); float t = range.Minimum + (range.Maximum - range.Minimum) * coefficient; rad = radiusCurve.CalculateValueByTime(t).X; } else { rad = radius; } for (int nSegment = 0; nSegment < shapeSegments + 1; nSegment++) { float rotateCoefficient = ((float)nSegment / (float)(shapeSegments)); float angle = rotateCoefficient * MathFunctions.PI * 2; Vec3 p = pos + rot * new Vec3(0, MathFunctions.Cos(angle) * rad, MathFunctions.Sin(angle) * rad); Vertex vertex = new Vertex(); vertex.position = p; Vec3 pp = p - pos; if (pp != Vec3.Zero) { vertex.normal = pp.GetNormalize(); } else { vertex.normal = Vec3.XAxis; } //vertex.normal = ( p - pos ).GetNormalize(); vertex.texCoord = new Vec2(currentDistance * textureCoordinatesTilesPerMeter, rotateCoefficient + .25f); vertex.tangent = new Vec4(rot.GetForward(), 1); vertices[currentVertex++] = vertex; } if (nStep < steps - 1) { for (int nSegment = 0; nSegment < shapeSegments; nSegment++) { indices[currentIndex++] = startStepVertexIndex + nSegment; indices[currentIndex++] = startStepVertexIndex + nSegment + 1; indices[currentIndex++] = startStepVertexIndex + nSegment + 1 + shapeSegments + 1; indices[currentIndex++] = startStepVertexIndex + nSegment + 1 + shapeSegments + 1; indices[currentIndex++] = startStepVertexIndex + nSegment + shapeSegments + 1; indices[currentIndex++] = startStepVertexIndex + nSegment; } } lastPosition = pos; lastRot = rot; } if (currentVertex != vertexCount) { Log.Fatal("RenderableCurve: UpdateRenderingGeometry: currentVertex != vertexCount."); } if (currentIndex != indexCount) { Log.Fatal("RenderableCurve: UpdateRenderingGeometry: currentIndex != indexCount."); } } if (vertices.Length != 0 && indices.Length != 0) { //create mesh string meshName = MeshManager.Instance.GetUniqueName( string.Format("__RenderableCurve_{0}_{1}", Name, uniqueMeshIdentifier)); uniqueMeshIdentifier++; //string meshName = MeshManager.Instance.GetUniqueName( string.Format( "__RenderableCurve_{0}", Name ) ); mesh = MeshManager.Instance.CreateManual(meshName); SubMesh subMesh = mesh.CreateSubMesh(); subMesh.UseSharedVertices = false; //init vertexData VertexDeclaration declaration = subMesh.VertexData.VertexDeclaration; declaration.AddElement(0, 0, VertexElementType.Float3, VertexElementSemantic.Position); declaration.AddElement(0, 12, VertexElementType.Float3, VertexElementSemantic.Normal); declaration.AddElement(0, 24, VertexElementType.Float2, VertexElementSemantic.TextureCoordinates, 0); declaration.AddElement(0, 32, VertexElementType.Float4, VertexElementSemantic.Tangent, 0); fixed(Vertex *pVertices = vertices) { subMesh.VertexData = VertexData.CreateFromArray(declaration, (IntPtr)pVertices, vertices.Length * Marshal.SizeOf(typeof(Vertex))); } subMesh.IndexData = IndexData.CreateFromArray(indices, 0, indices.Length, false); //set material subMesh.MaterialName = materialName; //set mesh gabarites Bounds bounds = Bounds.Cleared; foreach (Vertex vertex in vertices) { bounds.Add(vertex.position); } mesh.SetBoundsAndRadius(bounds, bounds.GetRadius()); } } //create MeshObject, SceneNode if (mesh != null) { meshObject = SceneManager.Instance.CreateMeshObject(mesh.Name); if (meshObject != null) { meshObject.SetMaterialNameForAllSubObjects(materialName); meshObject.CastShadows = true; sceneNode = new SceneNode(); sceneNode.Attach(meshObject); //apply offset sceneNode.Position = Position; MapObject.AssociateSceneNodeWithMapObject(sceneNode, this); } } //create collision body if (mesh != null && collision) { Vec3[] positions = new Vec3[vertices.Length]; for (int n = 0; n < vertices.Length; n++) { positions[n] = vertices[n].position; } string meshPhysicsMeshName = PhysicsWorld.Instance.AddCustomMeshGeometry(positions, indices, null, MeshShape.MeshTypes.TriangleMesh, 0, 0); collisionBody = PhysicsWorld.Instance.CreateBody(); collisionBody.Static = true; collisionBody._InternalUserData = this; collisionBody.Position = Position; MeshShape shape = collisionBody.CreateMeshShape(); shape.MeshName = meshPhysicsMeshName; shape.MaterialName = CollisionMaterialName; shape.ContactGroup = (int)ContactGroup.Collision; //shape.VehicleDrivableSurface = collisionVehicleDrivableSurface; collisionBody.PushedToWorld = true; } needUpdate = false; }
private static void ToAssimp(Module.Export.Assimp.Context context, Scene scene, Module.Export.Assimp.Mesh mesh_indexes, aiMesh assimp_mesh) { Mesh mesh = scene.meshes[mesh_indexes.mesh]; assimp_mesh.mMaterialIndex = (uint)mesh_indexes.material; using (aiString assimp_mesh_name = new aiString(mesh.name)) { assimp_mesh.mName = assimp_mesh_name.Unmanaged(); } if (mesh.vertices.Length > 0) { using (aiVector3DArray vertices = assimp_mesh.Vertices) { Assimp.Convert.UnityToAssimp.Array(Assimp.Convert.UnityToAssimp.Vector3, mesh.vertices, vertices); } } if (mesh.normals.Length > 0) { using (aiVector3DArray normals = assimp_mesh.Normals) { Assimp.Convert.UnityToAssimp.Array(Assimp.Convert.UnityToAssimp.Vector3, mesh.normals, normals); } } if (mesh.tangents.Length > 0) { using (aiVector3DArray tangents = assimp_mesh.Tangents) { Assimp.Convert.UnityToAssimp.Array(Assimp.Convert.UnityToAssimp.Tangent, mesh.tangents, tangents); } } if (mesh_indexes.submesh < mesh.submeshes.Length) { // Support for submeshes: this mesh represent only one submesh of the original mesh SubMesh sub_mesh = mesh.submeshes[mesh_indexes.submesh]; if (sub_mesh != null && sub_mesh.triangles != null && sub_mesh.triangles.Length > 0) { using (aiFaceArray faces = assimp_mesh.Faces) { Assimp.Convert.UnityToAssimp.Face(sub_mesh.triangles, sub_mesh.topology, faces); } } } if (mesh.uv1.Length > 0 || mesh.uv2.Length > 0) { using (aiVector3DMultiArray texture_coords = assimp_mesh.TextureCoords) { if (mesh.uv1.Length > 0) { using (aiVector3DArray texture_coords0 = texture_coords.Get(0)) { Assimp.Convert.UnityToAssimp.Array(Assimp.Convert.UnityToAssimp.UV, mesh.uv1, texture_coords0); } } if (mesh.uv2.Length > 0) { using (aiVector3DArray texture_coords1 = texture_coords.Get(1)) { Assimp.Convert.UnityToAssimp.Array(Assimp.Convert.UnityToAssimp.UV, mesh.uv2, texture_coords1); } } } } if (mesh.colors.Length > 0) { using (aiColor4DMultiArray colors = assimp_mesh.Colors) { using (aiColor4DArray colors0 = colors.Get(0)) { Assimp.Convert.UnityToAssimp.Array(Assimp.Convert.UnityToAssimp.Color, mesh.colors, colors0); } } } context.progress.Update(ASSIMP_PROGRESS_FACTOR); }
public static Shape SaveShape(FSHP fshp) { Shape Shape = new Shape(); Shape.VertexSkinCount = (byte)fshp.VertexSkinCount; Shape.Flags = ShapeFlags.HasVertexBuffer; Shape.BoneIndex = (ushort)fshp.BoneIndex; Shape.MaterialIndex = (ushort)fshp.MaterialIndex; Shape.VertexBufferIndex = (ushort)fshp.VertexBufferIndex; Shape.KeyShapes = new List <KeyShape>(); Shape.KeyShapeDict = new ResDict(); Shape.Name = fshp.Text; Shape.TargetAttribCount = (byte)fshp.TargetAttribCount; Shape.SkinBoneIndices = fshp.BoneIndices; Shape.SubMeshBoundings = new List <Bounding>(); Shape.RadiusArray = new List <float>(); Shape.RadiusArray = fshp.boundingRadius; Shape.Meshes = new List <Mesh>(); foreach (FSHP.BoundingBox box in fshp.boundingBoxes) { Bounding bnd = new Bounding(); bnd.Center = new Syroot.Maths.Vector3F(box.Center.X, box.Center.Y, box.Center.Z); bnd.Extent = new Syroot.Maths.Vector3F(box.Extend.X, box.Extend.Y, box.Extend.Z); Shape.SubMeshBoundings.Add(bnd); } foreach (FSHP.LOD_Mesh mesh in fshp.lodMeshes) { Mesh msh = new Mesh(); msh.MemoryPool = new MemoryPool(); msh.SubMeshes = new List <SubMesh>(); msh.PrimitiveType = (PrimitiveType)mesh.PrimitiveType; msh.FirstVertex = mesh.FirstVertex; foreach (FSHP.LOD_Mesh.SubMesh sub in mesh.subMeshes) { SubMesh subMesh = new SubMesh(); subMesh.Offset = sub.offset; subMesh.Count = (uint)mesh.faces.Count; msh.SubMeshes.Add(subMesh); } IList <uint> faceList = new List <uint>(); foreach (int f in mesh.faces) { faceList.Add((uint)f); } if (faceList.Count > 65000) { MessageBox.Show($"Warning! Your poly count for a single mesh {fshp.Text} is pretty high! ({faceList.Count})." + $" You may want to split this!"); msh.SetIndices(faceList, IndexFormat.UInt32); } else { msh.SetIndices(faceList, IndexFormat.UInt16); } Shape.Meshes.Add(msh); break; } return(Shape); }
/// <summary> /// /// </summary> /// <param name="parent"></param> /// <param name="ent"></param> public SubBatch(BatchedGeometry parent, SubEntity ent) { mMeshType = ent.SubMesh; mParent = parent; mBuild = false; mRequireVertexColors = false; // Material must always exist Material origMat = (Material)MaterialManager.Instance.GetByName(ent.MaterialName); if (origMat != null) { material = (Material)MaterialManager.Instance.GetByName(GetMaterialClone(origMat).Name); } else { Tuple<Resource, bool> result = MaterialManager.Instance.CreateOrRetrieve("PagedGeometry_Batched_Material", "General"); if (result.First == null) throw new Exception("BatchedGeometry failed to create a material for entity with invalid material."); material = (Material)result.First; } //Setup vertex/index data structure vertexData = mMeshType.vertexData.Clone(false); indexData = mMeshType.indexData.Clone(false); //Remove blend weights from vertex format VertexElement blendIndices = vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.BlendIndices); VertexElement blendWeights = vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.BlendWeights); if (blendIndices != null && blendWeights != null) { Debug.Assert(blendIndices.Source == blendWeights.Source, "Blend indices and weights should be in the same buffer"); Debug.Assert(blendIndices.Size + blendWeights.Size == vertexData.vertexBufferBinding.GetBuffer(blendIndices.Source).VertexSize, "Blend indices and blend buffers should have buffer to themselves!"); //Remove the blend weights vertexData.vertexBufferBinding.UnsetBinding(blendIndices.Source); vertexData.vertexDeclaration.RemoveElement(VertexElementSemantic.BlendIndices); vertexData.vertexDeclaration.RemoveElement(VertexElementSemantic.BlendWeights); } //Reset vertex/index count vertexData.vertexStart = 0; vertexData.vertexCount = 0; indexData.indexStart = 0; indexData.indexCount = 0; }
public void Rebuild() { if (!IsValid()) { Debug.LogError("The card definition is not valid."); return; } Stock.Validate(); Dictionary <Texture2D, SubMesh> table = new Dictionary <Texture2D, SubMesh>(); CardMesh card = new CardMesh(); CardShape paper = Definition.Atlas.FindById(Definition.Stock.Paper); if (paper == null) { Debug.LogError("Paper does not exist in atlas = " + Definition.Atlas.name + "::" + Definition.Stock.Paper); return; } SubMesh data = GetMesh(card, table, paper); float x = Stock.Size.x / 2; float y = Stock.Size.y / 2; float cx = x - Stock.Border.x; float cy = y - Stock.Border.y; Vector3 v0 = new Vector2(-cx, +cy); // middle Vector3 v1 = new Vector2(+cx, +cy); Vector3 v2 = new Vector2(+cx, -cy); Vector3 v3 = new Vector2(-cx, -cy); Vector3 v4 = new Vector2(-cx, +y); // top edge Vector3 v5 = new Vector2(+cx, +y); Vector3 v6 = new Vector2(+x, +cy); // right edge Vector3 v7 = new Vector2(+x, -cy); Vector3 v8 = new Vector2(+cx, -y); // bot edge Vector3 v9 = new Vector2(-cx, -y); Vector3 vA = new Vector2(-x, -cy); // left edge Vector3 vB = new Vector2(-x, +cy); // 4 5 // B 0 1 6 // C D // A 3 2 7 // 9 8 Vector3 vC = new Vector2(-cx, 0); // mid Vector3 vD = new Vector2(+cx, 0); if (Stock.Smooth > 0) { // middle Square4(data, paper, v0, v1, v2, v3, Color.white, false, false); // top Square4(data, paper, v4, v5, v1, v0, Color.white, false, false); // right Square4(data, paper, v1, v6, v7, v2, Color.white, false, false); // bottom Square4(data, paper, v3, v2, v8, v9, Color.white, false, false); // left Square4(data, paper, vB, v0, v3, vA, Color.white, false, false); BuildCorner3(data, paper, v0, vB, v4); BuildCorner3(data, paper, v1, v5, v6); BuildCorner3(data, paper, v2, v7, v8); BuildCorner3(data, paper, v3, v9, vA); } else // simple rectangle { Vector3 p1 = new Vector3(-x, +y, 0); Vector3 p2 = new Vector3(+x, +y, 0); Vector3 p3 = new Vector3(+x, -y, 0); Vector3 p4 = new Vector3(-x, -y, 0); Square4(data, paper, p1, p2, p3, p4, Color.white, false, false); } Vector2 textSize = new Vector2(0.175f, 0.175f); Vector2 symSize = new Vector2(0.25f, 0.25f); float symW = symSize.x * 0.5f; float symH = symSize.y * 0.5f; float rimX = Mathf.Max(textSize.x, symW); float rimY = Mathf.Max(textSize.y, symH); CardShape symbol = Atlas.FindById(Definition.Symbol); if (symbol == null && !string.IsNullOrEmpty(Definition.Symbol)) { Debug.LogError(string.Format("Symbol shape '{0}' is not defined in atlas.", Definition.Symbol)); } CardShape fullImage = Definition.FullImage ? Atlas.FindById(Definition.Image) : null; CardShape halfImage = !Definition.FullImage ? Atlas.FindById(Definition.Image) : null; if (fullImage != null) { SubMesh core = GetMesh(card, table, fullImage); Square4(core, fullImage, v0, v1, v2, v3, Color.white, false, false); } else if (halfImage != null) { SubMesh core = GetMesh(card, table, halfImage); Vector3 lift = new Vector3(0, 0, -0.01f); Square4(core, halfImage, v0 + lift, v1 + lift, vD + lift, vC + lift, Color.white, false, false); Square4(core, halfImage, vC + lift, vD + lift, v2 + lift, v3 + lift, Color.white, true, true); } else if (Definition.Pattern != 0 && symbol != null) { if (Definition.Pattern >= 1 && Definition.Pattern < patternBits.Length) { SubMesh core = GetMesh(card, table, symbol); Vector2 ssize = symSize; int bits = patternBits[Definition.Pattern]; float x0 = -x + Stock.Border.x; float x1 = +x - Stock.Border.x; float y0 = +y - Stock.Border.y; float y1 = -y + Stock.Border.y; for (int b = 0; b < 17; b++) { if ((bits & (1 << b)) != 0) { float px = Mathf.Lerp(x0, x1, patternPos[b].x); float py = Mathf.Lerp(y0, y1, patternPos[b].y); float scale = (Definition.Pattern == 1) ? 2.5f:1; Square(core, symbol, new Vector3(px, py, -0.01f), scale * ssize, Color.white); } } } else { Debug.LogError(string.Format("Pattern value '{0}' is not valid.", Definition.Pattern)); } } CardShape text = Atlas.FindById(Definition.Text); if (text == null && !string.IsNullOrEmpty(Definition.Text)) { Debug.LogError(string.Format("Text shape '{0}' is not defined in atlas.", Definition.Text)); } if (text != null) { SubMesh sub = GetMesh(card, table, text); float x0 = -x + (Stock.Border.x + rimX) * 0.5f; float x1 = +x - (Stock.Border.x + rimX) * 0.5f; float y0 = +y - Stock.Border.y; float y1 = -y + Stock.Border.y; Color color = GetSymbolColor(Definition.Symbol); Square(sub, text, new Vector3(x0, y0, -0.01f), textSize, color); Square(sub, text, new Vector3(x1, y1, -0.01f), textSize, color); } if (symbol != null) { SubMesh sub = GetMesh(card, table, symbol); Vector2 ssize = symSize * 0.5f; float gapY = ssize.y / 3; float x0 = -x + (Stock.Border.x + rimX) * 0.5f; float x1 = +x - (Stock.Border.x + rimX) * 0.5f; float y0 = +y - Stock.Border.y - textSize.y - gapY - ssize.y; float y1 = -y + Stock.Border.y + textSize.y + gapY + ssize.y; Color color = GetSymbolColor(Definition.Symbol); Square(sub, symbol, new Vector3(x0, y0, -0.01f), ssize, color); Square(sub, symbol, new Vector3(x1, y1, -0.01f), ssize, color); } if (Stock.TwoSided) { CardShape back = Atlas.FindById(Stock.Back); if (back != null) { SubMesh core = GetMesh(card, table, back); // middle Square4(core, back, v1, v0, vC, vD, Color.white, false, false); Square4(core, back, vD, vC, v3, v2, Color.white, true, true); // top Square4(core, paper, v5, v4, v0, v1, Color.white, false, false); // back-left Square5(core, paper, v2, v7, v6, v1, vD, Color.white, false); // bottom Square4(core, paper, v2, v3, v9, v8, Color.white, false, false); // back-right Square5(core, paper, v0, vB, vA, v3, vC, Color.white, false); BuildCorner3(core, paper, v1, v6, v5); BuildCorner3(core, paper, v2, v8, v7); BuildCorner3(core, paper, v3, vA, v9); BuildCorner3(core, paper, v0, v4, vB); } } Mesh mesh = SetupMesh(); mesh.vertices = card.GetCombinedVertices().ToArray(); mesh.triangles = data.IndexList.ToArray(); mesh.uv = card.GetCombinedTexCoords().ToArray(); mesh.colors = card.GetCombinedColors().ToArray(); if (card.MeshList.Count > 1) { mesh.subMeshCount = card.MeshList.Count; int vbase = 0; for (int i = 1; i < card.MeshList.Count; ++i) { SubMesh sub = card.MeshList[i]; int [] tris = sub.IndexList.ToArray(); vbase += card.MeshList[i - 1].VertexList.Count; for (int t = 0; t < tris.Length; ++t) { tris[t] += vbase; } mesh.SetTriangles(tris, i); } } mesh.RecalculateBounds(); mesh.Optimize(); mesh.RecalculateNormals(); this.GetComponent <Renderer>().sharedMaterials = card.Materials.ToArray(); }
/// <summary> /// Apply all model combines and seal builder. /// </summary> public void Apply() { // Do nothing if sealed if (isSealed) return; // Count total vertices and indices int totalVertices = 0; int totalIndices = 0; foreach (var item in builderDictionary) { totalVertices += item.Value.Vertices.Count; totalIndices += item.Value.Indices.Count; } // Create combined data combinedModel = new CombinedModel(); combinedModel.Vertices = new Vector3[totalVertices]; combinedModel.Normals = new Vector3[totalVertices]; combinedModel.UVs = new Vector2[totalVertices]; combinedModel.Indices = new int[totalIndices]; combinedModel.SubMeshes = new SubMesh[builderDictionary.Count]; // Populate static arrays int currentVertex = 0; int currentIndex = 0; int subMeshIndex = 0; foreach (var item in builderDictionary) { // Save current highest vertex and index int highestVertex = currentVertex; int highestIndex = currentIndex; // Copy vertex data for (int i = 0; i < item.Value.Vertices.Count; i++) { combinedModel.Vertices[currentVertex] = item.Value.Vertices[i]; combinedModel.Normals[currentVertex] = item.Value.Normals[i]; combinedModel.UVs[currentVertex] = item.Value.UVs[i]; currentVertex++; } // Copy index data for (int i = 0; i < item.Value.Indices.Count; i++) { combinedModel.Indices[currentIndex++] = highestVertex + i; } // Add submesh int frame; SubMesh sm = new SubMesh(); sm.StartIndex = highestIndex; sm.PrimitiveCount = item.Value.Indices.Count / 3; MaterialReader.ReverseTextureKey(item.Key, out sm.TextureArchive, out sm.TextureRecord, out frame); combinedModel.SubMeshes[subMeshIndex++] = sm; } Seal(); }
protected void CreateSubMeshList() { int idx = 0; for (int i = 0; i < _model.Meshes.Count; i++) { ModelMesh modelMesh = _model.Meshes[i]; for (int index = 0; index < modelMesh.MeshParts.Count; index++) { ModelMeshPart modelMeshPart = modelMesh.MeshParts[index]; SubMesh subMesh = new SubMesh(this); subMesh._meshPart = modelMeshPart; subMesh._modelIndex = idx; subMesh.Effect = modelMeshPart.Effect; subMesh._metadata = _metadata.SubMeshesMetadata[idx]; _subMeshes.Add(subMesh); } idx++; } UpdateSubMeshes(); }
/// <summary> /// /// </summary> public void Build() { if (mRenderMethod == BillboardMethod.Accelerated) { Clear(); //If there are no billboards to create, exit if (mBillboardBuffer.Count == 0) return; //Create manual mesh to store billboard quads mMesh = MeshManager.Instance.CreateManual(GetUniqueID("SBSMesh"), ResourceGroupManager.DefaultResourceGroupName, null); mSubMesh = mMesh.CreateSubMesh(); mSubMesh.useSharedVertices = false; //Setup vertex format information mSubMesh.vertexData = new VertexData(); mSubMesh.vertexData.vertexStart = 0; mSubMesh.vertexData.vertexCount = 4 * mBillboardBuffer.Count; VertexDeclaration dcl = mSubMesh.vertexData.vertexDeclaration; int offset = 0; dcl.AddElement(0, offset, VertexElementType.Float3, VertexElementSemantic.Position); offset += VertexElement.GetTypeSize(VertexElementType.Float3); dcl.AddElement(0, offset, VertexElementType.Float3, VertexElementSemantic.Normal); offset += VertexElement.GetTypeSize(VertexElementType.Float3); dcl.AddElement(0, offset, VertexElementType.Float3, VertexElementSemantic.Diffuse); offset += VertexElement.GetTypeSize(VertexElementType.Color); dcl.AddElement(0, offset, VertexElementType.Float3, VertexElementSemantic.TexCoords); offset += VertexElement.GetTypeSize(VertexElementType.Float2); //Populate a new vertex buffer HardwareVertexBuffer vbuf = HardwareBufferManager.Instance.CreateVertexBuffer( /*offset*/dcl, mSubMesh.vertexData.vertexCount, BufferUsage.StaticWriteOnly, false); unsafe { float* pReal = (float*)vbuf.Lock(BufferLocking.Discard); float minX = float.PositiveInfinity; float maxX = float.NegativeInfinity; float minY = float.PositiveInfinity; float maxY = float.NegativeInfinity; float minZ = float.PositiveInfinity; float maxZ = float.NegativeInfinity; foreach (StaticBillboard it in mBillboardBuffer) { StaticBillboard bb = it; float halfXScale = bb.XScale * 0.5f; float halfYScale = bb.YScale * 0.5f; // position *pReal++ = bb.Position.x; *pReal++ = bb.Position.y; *pReal++ = bb.Position.z; // normals (actually used as scale / translate info for vertex shader) *pReal++ = halfXScale; *pReal++ = halfYScale; *pReal++ = 0.0f; // color *((uint*)pReal++) = bb.Color; // uv *pReal++ = (float)(bb.TextCoordIndexU * mUFactor); *pReal++ = (float)(bb.TextCoordIndexV * mVFactor); // position *pReal++ = bb.Position.x; *pReal++ = bb.Position.y; *pReal++ = bb.Position.z; // normals (actually used as scale / translate info for vertex shader) *pReal++ = halfXScale; *pReal++ = halfYScale; *pReal++ = 1.0f; // color *((uint*)pReal++) = bb.Color; // uv *pReal++ = (float)((bb.TextCoordIndexU + 1)* mUFactor); *pReal++ = (float)(bb.TextCoordIndexV * mVFactor); // position *pReal++ = bb.Position.x; *pReal++ = bb.Position.y; *pReal++ = bb.Position.z; // normals (actually used as scale / translate info for vertex shader) *pReal++ = halfXScale; *pReal++ = halfYScale; *pReal++ = 2.0f; // color *((uint*)pReal++) = bb.Color; // uv *pReal++ = (float)(bb.TextCoordIndexU * mUFactor); *pReal++ = (float)((bb.TextCoordIndexV + 1) * mVFactor); // position *pReal++ = bb.Position.x; *pReal++ = bb.Position.y; *pReal++ = bb.Position.z; // normals (actually used as scale / translate info for vertex shader) *pReal++ = halfXScale; *pReal++ = halfYScale; *pReal++ = 3.0f; // color *((uint*)pReal++) = bb.Color; // uv *pReal++ = (float)((bb.TextCoordIndexU + 1) * mUFactor); *pReal++ = (float)((bb.TextCoordIndexV + 1) * mVFactor); //Update bounding box if (bb.Position.x - halfXScale < minX) minX = bb.Position.x - halfXScale; if (bb.Position.x + halfXScale > maxX) maxX = bb.Position.x + halfXScale; if (bb.Position.y - halfYScale < minY) minY = bb.Position.y - halfYScale; if (bb.Position.y + halfYScale > maxY) maxY = bb.Position.y + halfYScale; if (bb.Position.z - halfXScale < minZ) minZ = bb.Position.z - halfXScale; if (bb.Position.z + halfXScale > maxZ) maxZ = bb.Position.z + halfXScale; } AxisAlignedBox bounds = new AxisAlignedBox( new Vector3(minX, minY, minZ), new Vector3(maxX, maxY, maxZ)); vbuf.Unlock(); mSubMesh.vertexData.vertexBufferBinding.SetBinding(0, vbuf); //Populate index buffer mSubMesh.indexData.indexStart = 0; mSubMesh.indexData.indexCount = 6 * mBillboardBuffer.Count; mSubMesh.indexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, mSubMesh.indexData.indexCount, BufferUsage.StaticWriteOnly); ushort* pI = (ushort*)mSubMesh.indexData.indexBuffer.Lock(BufferLocking.Discard); for (ushort i = 0; i < mBillboardBuffer.Count; i++) { ushort ofset = (ushort)(i * 4); *pI++ = (ushort)(0 + ofset); *pI++ = (ushort)(2 + ofset); *pI++ = (ushort)(1 + ofset); *pI++ = (ushort)(1 + ofset); *pI++ = (ushort)(2 + ofset); *pI++ = (ushort)(3 + ofset); } mSubMesh.indexData.indexBuffer.Unlock(); //Finish up mesh mMesh.BoundingBox = bounds; Vector3 tmp = bounds.Maximum - bounds.Minimum; mMesh.BoundingSphereRadius = tmp.Length * 0.5f; LoggingLevel lvl = LogManager.Instance.LogDetail; LogManager.Instance.LogDetail = LoggingLevel.Low; mMesh.Load(); LogManager.Instance.LogDetail = lvl; //Empty the billboardBuffer now, because all billboards have been built mBillboardBuffer.Clear(); //Create an entity for the mesh mEntity = mSceneMgr.CreateEntity(mEntityName, mMesh.Name); mEntity.CastShadows = false; //Apply texture if (mFadeEnabled) { Debug.Assert(mFadeMaterial != null); mEntity.MaterialName = mFadeMaterial.Name; } else { Debug.Assert(mMaterial != null); mEntity.MaterialName = mMaterial.Name; } //Add to scene mNode.AttachObject(mEntity); mEntity.IsVisible = mVisible; } } }
/**************** New Functions Begin ***************/ /// <summary> /// Generate navmesh by entity /// </summary> /// <param name="ent">Ogre Entity</param> /// <returns>Navmesh</returns> public static Navmesh LoadNavmesh(Entity ent) { bool addedSharedVertex = false; vertices.Clear(); faces.Clear(); MeshPtr mesh = ent.GetMesh(); Mesh.SubMeshIterator subIterator = mesh.GetSubMeshIterator(); uint vertexNum = 0; uint vertexOffset = mesh.sharedVertexData.vertexStart; MyVector3 <float>[] verticeArray = new MyVector3 <float> [vertexNum]; VertexElement posElem = mesh.sharedVertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.VES_POSITION); HardwareVertexBufferSharedPtr vertexBuffer = mesh.sharedVertexData.vertexBufferBinding.GetBuffer(posElem.Source); while (subIterator.MoveNext()) { SubMesh subMesh = subIterator.Current; VertexData vertexData = subMesh.useSharedVertices ? mesh.sharedVertexData : subMesh.vertexData; HardwareIndexBufferSharedPtr indexBuffer = subMesh.indexData.indexBuffer; HardwareIndexBuffer.IndexType indexType = indexBuffer.Type; uint indexCount = subMesh.indexData.indexCount; uint trisNum = indexCount / 3; uint[] indcies = new uint[indexCount]; uint indexOffset = subMesh.indexData.indexStart; if (subMesh.useSharedVertices) { if (!addedSharedVertex) { vertexNum += mesh.sharedVertexData.vertexCount; addedSharedVertex = true; } } else { vertexNum += subMesh.vertexData.vertexCount; } unsafe { uint * pLong = (uint *)(indexBuffer.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY)); ushort *pShort = (ushort *)pLong; for (int i = 0; i < indexCount; i++) { if (indexType == HardwareIndexBuffer.IndexType.IT_32BIT) { indcies[indexOffset] = pLong[i] + vertexNum; } else { indcies[indexOffset] = pShort[i] + vertexNum; } indexOffset++; } } int indexLength = indcies.Length / 3; for (int i = 0; i < indexLength; i++) { faces.Add(new MyVector3 <ushort>( (ushort)indcies[i * 3 + 0], (ushort)indcies[i * 3 + 1], (ushort)indcies[i * 3 + 2] )); } indexBuffer.Unlock(); if (subMesh.vertexData != null) { vertexNum = subMesh.vertexData.vertexCount; vertexOffset = subMesh.vertexData.vertexStart; verticeArray = new MyVector3 <float> [vertexNum]; posElem = subMesh.vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.VES_POSITION); vertexBuffer = subMesh.vertexData.vertexBufferBinding.GetBuffer(posElem.Source); unsafe { byte * vertexMemory = (byte *)vertexBuffer.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); float *pVertexBuffer; for (int i = 0; i < vertexNum; i++) { posElem.BaseVertexPointerToElement(vertexMemory, &pVertexBuffer); verticeArray[vertexOffset] = (new MyVector3 <float>( pVertexBuffer[0], pVertexBuffer[1], pVertexBuffer[2] )); vertexMemory += vertexBuffer.VertexSize; vertexOffset++; } } for (int i = 0; i < verticeArray.Length; i++) { vertices.Add(verticeArray[i]); } vertexBuffer.Unlock(); } } vertexNum = mesh.sharedVertexData.vertexCount; vertexOffset = mesh.sharedVertexData.vertexStart; verticeArray = new MyVector3 <float> [vertexNum]; posElem = mesh.sharedVertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.VES_POSITION); vertexBuffer = mesh.sharedVertexData.vertexBufferBinding.GetBuffer(posElem.Source); unsafe { byte * vertexMemory = (byte *)vertexBuffer.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY); float *pVertexBuffer; for (int i = 0; i < vertexNum; i++) { posElem.BaseVertexPointerToElement(vertexMemory, &pVertexBuffer); verticeArray[vertexOffset] = (new MyVector3 <float>( pVertexBuffer[0], pVertexBuffer[1], pVertexBuffer[2] )); vertexMemory += vertexBuffer.VertexSize; vertexOffset++; } } for (int i = 0; i < verticeArray.Length; i++) { vertices.Add(verticeArray[i]); } vertexBuffer.Unlock(); return(GenerateNavmesh()); }
private void VertexDataToOutline(List <Vector2f[]> outlines, Vector3f[] vertices, ref SubMesh submesh) { Vector3i[] triangles = new Vector3i[submesh.IndexCount / 3]; for (int o = submesh.FirstByte, ti = 0; ti < triangles.Length; o += 6, ti++) { int x = BitConverter.ToInt16(IndexBuffer, o + 0); int y = BitConverter.ToInt16(IndexBuffer, o + 2); int z = BitConverter.ToInt16(IndexBuffer, o + 4); triangles[ti] = new Vector3i(x, y, z); } MeshOutlineGenerator outlineGenerator = new MeshOutlineGenerator(vertices, triangles); List <Vector2f[]> meshOutlines = outlineGenerator.GenerateOutlines(); outlines.AddRange(meshOutlines); }
public string GetSubmeshName(SubMesh _mesh) { Mesh.Const_SubMeshNameMap map = mainStick.GetMesh().GetSubMeshNameMap(); for (uint i = 0; i < map.Count; i++) { if(_mesh == mainStick.GetMesh().GetSubMesh((ushort)i)) { for (Mesh.Const_SubMeshNameMap.ConstIterator start = map.Begin(); start != map.End(); start++) { if (start.Value == i) return start.Key; } } } return ""; }