private void WriteGroup(int groupIndex, ref int baseIndex, ModelEntity model) { _streamWriter.WriteLine("g group" + groupIndex); _streamWriter.WriteLine("usemtl mtl{0}", model.TexturePage); for (var k = 0; k < model.Triangles.Length; k++) { _streamWriter.WriteLine("f {2}/{2}/{2} {1}/{1}/{1} {0}/{0}/{0}", baseIndex++, baseIndex++, baseIndex++); } }
private void BindMesh(ModelEntity modelEntity, int index, Matrix4?matrix = null, TextureBinder textureBinder = null, bool updateMeshData = true) { var mesh = GetMesh(index); if (mesh == null) { return; } if (updateMeshData) { var numTriangles = modelEntity.Triangles.Length; var elementCount = numTriangles * 3 * 3; var baseIndex = 0; var positionList = new float[elementCount]; var normalList = new float[elementCount]; var colorList = new float[elementCount]; var uvList = new float[elementCount]; for (var t = 0; t < numTriangles; t++) { var triangle = modelEntity.Triangles[t]; for (var i = 0; i < 3; i++) { var index1 = baseIndex++; var index2 = baseIndex++; var index3 = baseIndex++; var vertex = triangle.Vertices[i]; positionList[index1] = vertex.X; positionList[index2] = vertex.Y; positionList[index3] = vertex.Z; var normal = triangle.Normals[i]; normalList[index1] = normal.X; normalList[index2] = normal.Y; normalList[index3] = normal.Z; var color = triangle.Colors[i]; colorList[index1] = color.R; colorList[index2] = color.G; colorList[index3] = color.B; var uv = triangle.Uv[i]; uvList[index1] = uv.X; uvList[index2] = uv.Y; uvList[index3] = uv.Z; } } mesh.SetData(numTriangles * 3, positionList, normalList, colorList, uvList); } mesh.WorldMatrix = matrix ?? modelEntity.WorldMatrix; if (textureBinder != null) { mesh.Texture = modelEntity.Texture != null?textureBinder.GetTexture(modelEntity.TexturePage) : 0; } }
private void WriteModel(ModelEntity model) { if (model.Texture != null) { if (_mtlExporter.AddMaterial(model.TexturePage)) { _pngExporter.Export(model.Texture, model.TexturePage, _selectedPath); } } var worldMatrix = model.WorldMatrix; foreach (var triangle in model.Triangles) { var vertexColor0 = string.Empty; var vertexColor1 = string.Empty; var vertexColor2 = string.Empty; var c0 = triangle.Colors[0]; var c1 = triangle.Colors[1]; var c2 = triangle.Colors[2]; if (_experimentalVertexColor) { vertexColor0 = string.Format(" {0} {1} {2}", (c0.R).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c0.G).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c0.B).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); vertexColor1 = string.Format(" {0} {1} {2}", (c1.R).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c1.G).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c1.B).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); vertexColor2 = string.Format(" {0} {1} {2}", (c2.R).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c2.G).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c2.B).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); } var v0 = Vector3.TransformPosition(triangle.Vertices[0], worldMatrix); var v1 = Vector3.TransformPosition(triangle.Vertices[1], worldMatrix); var v2 = Vector3.TransformPosition(triangle.Vertices[2], worldMatrix); _streamWriter.WriteLine("v {0} {1} {2} {3}", (v0.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v0.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v0.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), vertexColor0); _streamWriter.WriteLine("v {0} {1} {2} {3}", (v1.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v1.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v1.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), vertexColor1); _streamWriter.WriteLine("v {0} {1} {2} {3}", (v2.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v2.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v2.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), vertexColor2); } foreach (var triangle in model.Triangles) { var n0 = Vector3.TransformNormal(triangle.Normals[0], worldMatrix); var n1 = Vector3.TransformNormal(triangle.Normals[1], worldMatrix); var n2 = Vector3.TransformNormal(triangle.Normals[2], worldMatrix); _streamWriter.WriteLine("vn {0} {1} {2}", (n0.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n0.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n0.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); _streamWriter.WriteLine("vn {0} {1} {2}", (n1.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n1.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n1.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); _streamWriter.WriteLine("vn {0} {1} {2}", (n2.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n2.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n2.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); } foreach (var triangle in model.Triangles) { var uv0 = triangle.Uv[0]; var uv1 = triangle.Uv[1]; var uv2 = triangle.Uv[2]; _streamWriter.WriteLine("vt {0} {1}", uv0.X.ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (1f - uv0.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); _streamWriter.WriteLine("vt {0} {1}", uv1.X.ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (1f - uv1.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); _streamWriter.WriteLine("vt {0} {1}", uv2.X.ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (1f - uv2.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); } }
private void ProccessPrimitive(BinaryReader reader, List <ModelEntity> modelEntities, int modelIndex) { var triangles = new List <Triangle>(); var nextPrimitivePointer = reader.ReadUInt32() * 4; var primitiveHeaderPointer = reader.ReadUInt32() * 4; var typeCountMapped = reader.ReadUInt32(); var mapped = typeCountMapped >> 0x1F & 0x1; var typeCount = typeCountMapped & 0x1F; for (var j = 0; j < typeCount; j++) { var primitiveType = reader.ReadUInt16(); var dataType = reader.ReadUInt16(); var developerId = (dataType & 0xF000) >> 0xC; var category = (dataType & 0xF00) >> 0x8; //0: Polygon data 1: Shared polygon data 2: Image data 3: Animation data 4: MIMe data 5: Ground dat var driver = dataType & 0xFF; var dataCountAndSize = reader.ReadUInt32(); var flag = (dataCountAndSize & 0x80000000) >> 0x1F; var dataCount = (dataCountAndSize & 0x3FFF0000) >> 0x10; var dataSize = dataCountAndSize & 0xFFFF; var polygonIndex = reader.ReadUInt32() * 4; if (category == 0) { ProcessNonSharedPrimitiveData(triangles, reader, driver, primitiveType, primitiveHeaderPointer, nextPrimitivePointer, polygonIndex, dataCount); } } var modelEntity = new ModelEntity(); modelEntity.Triangles = triangles.ToArray(); modelEntity.HasColors = true; modelEntity.HasNormals = true; modelEntity.HasUvs = false; modelEntities.Add(modelEntity); if (nextPrimitivePointer < 1000) { reader.BaseStream.Seek(_offset + nextPrimitivePointer, SeekOrigin.Begin); ProccessPrimitive(reader, modelEntities, modelIndex); } }
private RootEntity ParsePMD(BinaryReader reader) { var primPoint = reader.ReadUInt32(); var vertPoint = reader.ReadUInt32(); var nObj = reader.ReadUInt32(); if (nObj < 1 || nObj > 4000) { return(null); } var models = new List <ModelEntity>(); for (var o = 0; o < nObj; o++) { var model = new ModelEntity(); var triangles = new List <Triangle>(); var nPointers = reader.ReadUInt32(); if (nPointers < 1 || nPointers > 4000) { return(null); } for (var p = 0; p < nPointers; p++) { var position = reader.BaseStream.Position; var pointer = reader.ReadUInt32(); reader.BaseStream.Seek(_offset + pointer, SeekOrigin.Begin); var nPacket = reader.ReadUInt16(); if (nPacket > 4000) { return(null); } var primType = reader.ReadUInt16(); if (primType > 15) { return(null); } for (var pk = 0; pk < nPacket; pk++) { switch (primType) { case 0x00: triangles.Add(ReadPolyFT3(reader)); break; case 0x01: triangles.AddRange(ReadPolyFT4(reader)); break; case 0x02: triangles.Add(ReadPolyGT3(reader)); break; case 0x03: triangles.AddRange(ReadPolyGT4(reader)); break; case 0x04: triangles.Add(ReadPolyF3(reader)); break; case 0x05: triangles.AddRange(ReadPolyF4(reader)); break; case 0x06: triangles.Add(ReadPolyG3(reader)); break; case 0x07: triangles.AddRange(ReadPolyG4(reader)); break; case 0x08: triangles.Add(ReadPolyFT3(reader, true, _offset + vertPoint)); break; case 0x09: triangles.AddRange(ReadPolyFT4(reader, true, _offset + vertPoint)); break; case 0x0a: triangles.Add(ReadPolyGT3(reader, true, _offset + vertPoint)); break; case 0x0b: triangles.AddRange(ReadPolyGT4(reader, true, _offset + vertPoint)); break; case 0x0c: triangles.Add(ReadPolyF3(reader, true, _offset + vertPoint)); break; case 0x0d: triangles.AddRange(ReadPolyF4(reader, true, _offset + vertPoint)); break; case 0x0e: triangles.Add(ReadPolyG3(reader, true, _offset + vertPoint)); break; case 0x0f: triangles.AddRange(ReadPolyG4(reader, true, _offset + vertPoint)); break; default: goto EndObject; } } reader.BaseStream.Seek(position + 4, SeekOrigin.Begin); } EndObject: model.Triangles = triangles.ToArray(); models.Add(model); } EndModel: if (models.Count > 0) { var entity = new RootEntity(); foreach (var model in models) { model.ParentEntity = entity; } entity.ChildEntities = models.ToArray(); entity.ComputeBounds(); return(entity); } return(null); }
public void SetupMultipleEntityBatch(RootEntity[] checkedEntities = null, ModelEntity selectedModelEntity = null, RootEntity selectedRootEntity = null, TextureBinder textureBinder = null, bool updateMeshData = true, bool focus = false, bool hasAnimation = false) { if (selectedModelEntity == null && selectedRootEntity == null) { return; } var bounds = focus ? new BoundingBox() : null; selectedRootEntity = selectedRootEntity ?? selectedModelEntity.GetRootEntity(); //count the selected entity var modelCount = 1; //count checked, excecpt, the selected if (checkedEntities != null) { foreach (var checkedEntity in checkedEntities) { if (checkedEntity == selectedRootEntity) { continue; } modelCount += checkedEntity.ChildEntities.Length; if (focus) { bounds.AddPoints(checkedEntity.Bounds3D.Corners); } } } //focus if (selectedRootEntity != null) { foreach (var subEntity in selectedRootEntity.ChildEntities) { modelCount++; if (focus) { bounds.AddPoints(subEntity.Bounds3D.Corners); } } } //reset ResetModelIndex(); if (updateMeshData) { Reset(modelCount); } //bindings //checked entities, except selected root if (checkedEntities != null) { foreach (var entity in checkedEntities) { if (entity == selectedRootEntity) { continue; } foreach (ModelEntity modelEntity in entity.ChildEntities) { BindMesh(modelEntity, modelEntity.TempMatrix * modelEntity.WorldMatrix, textureBinder, updateMeshData, modelEntity.InitialVertices, modelEntity.InitialNormals, modelEntity.FinalVertices, modelEntity.FinalNormals, modelEntity.Interpolator); } } } //if not animating //if (!hasAnimation) //{ //root entity if (selectedRootEntity != null) { foreach (ModelEntity modelEntity in selectedRootEntity.ChildEntities) { BindMesh(modelEntity, modelEntity.TempMatrix * modelEntity.WorldMatrix, textureBinder, updateMeshData, modelEntity.InitialVertices, modelEntity.InitialNormals, modelEntity.FinalVertices, modelEntity.FinalNormals, modelEntity.Interpolator); } } //} // do focus if (focus) { _scene.FocusOnBounds(bounds); } }
private void BindMesh(ModelEntity modelEntity, Matrix4?matrix = null, TextureBinder textureBinder = null, bool updateMeshData = true, Vector3[] initialVertices = null, Vector3[] initialNormals = null, Vector3[] finalVertices = null, Vector3[] finalNormals = null, float?interpolator = null) { if (!modelEntity.Visible) { return; } var mesh = GetMesh(_modelIndex++); if (mesh == null) { return; } //var rootEntity = modelEntity.ParentEntity as RootEntity; //todo mesh.WorldMatrix = matrix ?? modelEntity.WorldMatrix; if (updateMeshData) { var numTriangles = modelEntity.Triangles.Length; var elementCount = numTriangles * 3 * 3; var baseIndex = 0; var positionList = new float[elementCount]; var normalList = new float[elementCount]; var colorList = new float[elementCount]; var uvList = new float[elementCount]; for (var t = 0; t < numTriangles; t++) { var lastVertex = Vector3.Zero; var lastNormal = Vector3.Zero; var lastColor = Color.White; var lastUv = Vector3.Zero; var triangle = modelEntity.Triangles[t]; for (var i = 0; i < 3; i++) { var index1 = baseIndex++; var index2 = baseIndex++; var index3 = baseIndex++; var sourceVertex = triangle.Vertices[i]; if (triangle.AttachedIndices != null) { var attachedIndex = triangle.AttachedIndices[i]; if (attachedIndex != uint.MaxValue) { if (!_scene.AutoAttach) { sourceVertex = new Vector3(DiscardValue, DiscardValue, DiscardValue); } } } Vector3 vertex; if (_scene.VibRibbonWireframe && i == 2) { vertex = lastVertex; } else { if (initialVertices != null && finalVertices != null && triangle.OriginalVertexIndices[i] < finalVertices.Length) { var initialVertex = sourceVertex + initialVertices[triangle.OriginalVertexIndices[i]]; var finalVertex = sourceVertex + finalVertices[triangle.OriginalVertexIndices[i]]; vertex = Vector3.Lerp(initialVertex, finalVertex, interpolator.GetValueOrDefault()); } else { vertex = sourceVertex; } } positionList[index1] = vertex.X; positionList[index2] = vertex.Y; positionList[index3] = vertex.Z; Vector3 normal; if (_scene.VibRibbonWireframe && i == 2) { normal = lastNormal; } else { if (initialNormals != null && finalNormals != null && triangle.OriginalNormalIndices[i] < finalNormals.Length) { var initialNormal = triangle.Normals[i] + initialNormals[triangle.OriginalNormalIndices[i]] / 4096f; var finalNormal = triangle.Normals[i] + finalNormals[triangle.OriginalNormalIndices[i]] / 4096f; normal = Vector3.Lerp(initialNormal, finalNormal, interpolator.GetValueOrDefault()); } else { normal = triangle.Normals[i]; } } normalList[index1] = normal.X; normalList[index2] = normal.Y; normalList[index3] = normal.Z; Color color; if (_scene.VibRibbonWireframe && i == 2) { color = lastColor; } else { color = triangle.Colors[i]; } colorList[index1] = color.R; colorList[index2] = color.G; colorList[index3] = color.B; Vector3 uv; if (_scene.VibRibbonWireframe && i == 2) { uv = lastUv; } else { uv = triangle.Uv[i]; } uvList[index1] = uv.X; uvList[index2] = uv.Y; uvList[index3] = uv.Z; lastVertex = vertex; lastNormal = normal; lastColor = color; lastUv = uv; } } mesh.SetData(numTriangles * 3, positionList, normalList, colorList, uvList); } if (textureBinder != null) { mesh.Texture = modelEntity.Texture != null?textureBinder.GetTexture((int)modelEntity.TexturePage) : 0; } }
public void BindModelBatch(ModelEntity modelEntity, Matrix4 matrix, TextureBinder textureBinder = null, Vector3[] initialVertices = null, Vector3[] initialNormals = null, Vector3[] finalVertices = null, Vector3[] finalNormals = null, float?interpolator = null) { BindMesh(modelEntity, matrix, textureBinder, finalVertices != null || finalNormals != null, initialVertices, initialNormals, finalVertices, finalNormals, interpolator); }
public void BindModelBatch(ModelEntity modelEntity, int index, Matrix4 matrix, TextureBinder textureBinder = null) { BindMesh(modelEntity, index, matrix, textureBinder); }
public void SetupMultipleEntityBatch(RootEntity[] checkedEntities = null, ModelEntity selectedModel = null, RootEntity selectedEntity = null, TextureBinder textureBinder = null, bool updateMeshData = true, bool focus = false) { var bounds = focus ? new BoundingBox() : null; var modelCount = checkedEntities != null || selectedEntity != null || selectedModel != null ? 1 : 0; if (checkedEntities != null) { foreach (var entity in checkedEntities) { if (entity == selectedEntity) { continue; } modelCount += entity.ChildEntities.Length; } } if (selectedEntity != null) { foreach (var subEntity in selectedEntity.ChildEntities) { modelCount++; if (focus) { bounds.AddPoints(subEntity.Bounds3D.Corners); } } } if (updateMeshData) { Reset(modelCount); } var modelIndex = 0; if (checkedEntities != null) { foreach (var entity in checkedEntities) { if (entity == selectedEntity) { continue; } foreach (var subEntity in entity.ChildEntities) { if (subEntity == selectedModel) { continue; } BindMesh((ModelEntity)subEntity, modelIndex++, null, textureBinder, updateMeshData); } } } if (selectedEntity != null) { foreach (var subEntity in selectedEntity.ChildEntities) { if (subEntity == selectedModel) { continue; } BindMesh((ModelEntity)subEntity, modelIndex++, null, textureBinder, updateMeshData); } } if (selectedModel != null) { BindMesh(selectedModel, modelIndex, null, textureBinder, updateMeshData); } if (focus) { _scene.FocusOnBounds(bounds); } }