public triangles MakeColladaTriangles(InputLocalOffset[] inputs, Dictionary <int, int> positionMaps, Dictionary <int, int> normalMaps, List <Dictionary <int, int> > uvMaps, List <Dictionary <int, int> > colorMaps) { int numTris = (from grp in Groups select grp.TriCount).Sum(); var tris = new triangles(); tris.count = (ulong)numTris; tris.input = inputs; List <Dictionary <int, int> > inputMaps = new List <Dictionary <int, int> >(); int uvIndex = 0, colorIndex = 0; for (int i = 0; i < inputs.Length; i++) { var input = inputs[i]; switch (input.semantic) { case "VERTEX": inputMaps.Add(positionMaps); break; case "NORMAL": case "TANGENT": case "BINORMAL": inputMaps.Add(normalMaps); break; case "TEXCOORD": inputMaps.Add(uvMaps[uvIndex]); uvIndex++; break; case "COLOR": inputMaps.Add(colorMaps[colorIndex]); colorIndex++; break; default: throw new InvalidOperationException("No input maps available for semantic " + input.semantic); } } var indicesBuilder = new StringBuilder(); foreach (var group in Groups) { var indices = Indices; for (int index = group.TriFirst; index < group.TriFirst + group.TriCount; index++) { int firstIdx = index * 3; for (int vertIndex = 0; vertIndex < 3; vertIndex++) { for (int i = 0; i < inputs.Length; i++) { indicesBuilder.Append(inputMaps[i][indices[firstIdx + vertIndex]]); indicesBuilder.Append(" "); } } } } tris.p = indicesBuilder.ToString(); return(tris); }
private void LoadGeometryFromCollada(CollisionGroupNode parent, geometry geo) { mesh m = geo.Item as mesh; // For safety, read the model's definition of where the position data is // and grab it from there. We could just do a search for "position" in the // source list names, but this makes sure there are no errors. InputLocal pos_input = Array.Find(m.vertices.input, x => x.semantic == "POSITION"); source pos_src = Array.Find(m.source, x => x.id == pos_input.source.Trim('#')); float_array pos_arr = pos_src.Item as float_array; // For some reason Maya puts a leading space in the face index data, // so we need to trim that out before trying to parse the index string. triangles tris = m.Items[0] as triangles; string[] indices = tris.p.Trim(' ').Split(' '); int stride = tris.input.Length; // Make sure this tool can support meshes with multiple vertex attributes. for (int i = 0; i < indices.Length; i += stride * 3) { int vec1_index = Convert.ToInt32(indices[i]); int vec2_index = Convert.ToInt32(indices[i + stride]); int vec3_index = Convert.ToInt32(indices[i + (stride * 2)]); Vector3 vec1 = new Vector3((float)pos_arr.Values[vec1_index * 3], (float)pos_arr.Values[(vec1_index * 3) + 1], (float)pos_arr.Values[(vec1_index * 3) + 2]); Vector3 vec2 = new Vector3((float)pos_arr.Values[vec2_index * 3], (float)pos_arr.Values[(vec2_index * 3) + 1], (float)pos_arr.Values[(vec2_index * 3) + 2]); Vector3 vec3 = new Vector3((float)pos_arr.Values[vec3_index * 3], (float)pos_arr.Values[(vec3_index * 3) + 1], (float)pos_arr.Values[(vec3_index * 3) + 2]); // The benefit of using this library is that we easily got the up-axis // info from the file. If the up-axis was defined as Z-up, we need to // swap the Y and Z components of our vectors so the mesh isn't sideways. // (The Wind Waker is Y-up.) if (m_UpAxis == UpAxisType.Z_UP) { vec1 = SwapYZ(vec1); vec2 = SwapYZ(vec2); vec3 = SwapYZ(vec3); } CollisionTriangle new_tri = new CollisionTriangle(vec1, vec2, vec3, parent); parent.Triangles.Add(new_tri); Triangles.Add(new_tri); } }
polylist Triangles2Polylist(triangles triangles) { polylist poly = new polylist(); poly.count = triangles.count; poly.input = triangles.input; poly.material = triangles.material; poly.name = triangles.name; poly.p = triangles.p; string str = "3 "; System.Text.StringBuilder builder = new System.Text.StringBuilder(str.Length * (int)poly.count); for (int i = 0; i < (int)poly.count; i++) { builder.Append(str); } poly.vcount = builder.ToString(); return(poly); }
public triangles MakeColladaTriangles(InputLocalOffset[] inputs, Dictionary <int, int> vertexMaps, List <Dictionary <int, int> > uvMaps) { int numTris = (from grp in Groups select grp.TriCount).Sum(); var tris = new triangles(); tris.count = (ulong)numTris; tris.input = inputs; var indicesBuilder = new StringBuilder(); foreach (var group in Groups) { var indices = Indices; for (int index = group.TriFirst; index < group.TriFirst + group.TriCount; index++) { int firstIdx = index * 3; for (int vertIndex = 0; vertIndex < 3; vertIndex++) { for (int i = 0; i < inputs.Length; i++) { // TODO: Hacky! if (i == 0) { indicesBuilder.Append(vertexMaps[indices[firstIdx + vertIndex]]); } else { indicesBuilder.Append(uvMaps[i - 1][indices[firstIdx + vertIndex]]); } indicesBuilder.Append(" "); } } } } tris.p = indicesBuilder.ToString(); return(tris); }
protected mesh CreatePalletMesh(PalletProperties palletProperties) { // build pallet object Pallet pallet = new Pallet(palletProperties); // build list of boxes List <Box> listBoxes = pallet.BuildListOfBoxes(); // build list of vertices / normals / UVs ulong vertexCount = 0, normalCount = 0, uvCount = 0, triangleCount = 0, boxCount = 0; string triangle_string = string.Empty; List <double> doubleArrayPosition = new List <double>(), doubleArrayNormal = new List <double>(), doubleArrayUV = new List <double>(); foreach (Box box in listBoxes) { foreach (Vector3D p in box.Points) { doubleArrayPosition.Add(p.X); doubleArrayPosition.Add(p.Y); doubleArrayPosition.Add(p.Z); ++vertexCount; } foreach (Vector3D n in box.Normals) { doubleArrayNormal.Add(n.X); doubleArrayNormal.Add(n.Y); doubleArrayNormal.Add(n.Z); ++normalCount; } foreach (Vector2D uv in box.UVs) { doubleArrayUV.Add(uv.X); doubleArrayUV.Add(uv.Y); ++uvCount; } foreach (TriangleIndices tr in box.Triangles) { triangle_string += tr.ConvertToString(boxCount); ++triangleCount; } ++boxCount; } mesh palletMesh = new mesh(); // position source source palletPositionSource = new source() { id = "pallet_position", name = "pallet_position" }; float_array farrayPosition = new float_array { id = "pallet_position_float_array", count = (ulong)doubleArrayPosition.Count, Values = doubleArrayPosition.ToArray() }; palletPositionSource.technique_common = new sourceTechnique_common() { accessor = new accessor() { stride = 3, count = vertexCount, source = "#pallet_position_float_array", param = new param[] { new param() { name = "X", type = "float" }, new param() { name = "Y", type = "float" }, new param() { name = "Z", type = "float" } } } }; palletPositionSource.Item = farrayPosition; // normal source source palletPositionNormal = new source() { id = "pallet_normal", name = "pallet_normal" }; float_array farrayNormal = new float_array { id = "pallet_normal_float_array", count = (ulong)doubleArrayNormal.Count, Values = doubleArrayNormal.ToArray() }; palletPositionNormal.technique_common = new sourceTechnique_common() { accessor = new accessor() { stride = 3, count = normalCount, source = "#pallet_normal_float_array", param = new param[] { new param() { name = "X", type = "float" }, new param() { name = "Y", type = "float" }, new param() { name = "Z", type = "float" } } } }; palletPositionNormal.Item = farrayNormal; // uv source source palletPositionUV = new source() { id = "pallet_UV", name = "pallet_UV" }; float_array farrayUV = new float_array { id = "pallet_UV_float_array", count = (ulong)doubleArrayUV.Count, Values = doubleArrayUV.ToArray() }; palletPositionUV.technique_common = new sourceTechnique_common() { accessor = new accessor() { stride = 2, count = vertexCount, source = "#pallet_UV_float_array", param = new param[] { new param() { name = "S", type = "float" }, new param() { name = "T", type = "float" } } } }; palletPositionUV.Item = farrayUV; // insert sources palletMesh.source = new source[] { palletPositionSource, palletPositionNormal, palletPositionUV }; // vertices InputLocal verticesInput = new InputLocal() { semantic = "POSITION", source = "#pallet_position" }; palletMesh.vertices = new vertices() { id = "pallet_vertex", input = new InputLocal[] { verticesInput } }; triangles trianglesPallet = new triangles() { material = "materialPallet", count = triangleCount }; trianglesPallet.input = new InputLocalOffset[] { new InputLocalOffset() { semantic = "VERTEX", source = "#pallet_vertex", offset = 0 } , new InputLocalOffset() { semantic = "NORMAL", source = "#pallet_normal", offset = 1 } , new InputLocalOffset() { semantic = "TEXCOORD", source = "#pallet_UV", offset = 2, set = 0, setSpecified = true } }; trianglesPallet.p = triangle_string; palletMesh.Items = new object[] { trianglesPallet }; return(palletMesh); }
protected mesh CreateCaseMesh(BoxProperties caseProperties) { // build box Box box = new Box(0, caseProperties); // build list of vertices / normals / UVs ulong vertexCount = 0, normalCount = 0, uvCount = 0; List <double> doubleArrayPosition = new List <double>(), doubleArrayNormal = new List <double>(), doubleArrayUV = new List <double>(); foreach (Vector3D p in box.PointsSmallOffset) { doubleArrayPosition.Add(p.X); doubleArrayPosition.Add(p.Y); doubleArrayPosition.Add(p.Z); ++vertexCount; } foreach (Vector3D n in box.Normals) { doubleArrayNormal.Add(n.X); doubleArrayNormal.Add(n.Y); doubleArrayNormal.Add(n.Z); ++normalCount; } foreach (Vector2D uv in box.UVs) { doubleArrayUV.Add(uv.X); doubleArrayUV.Add(uv.Y); ++uvCount; } mesh caseMesh = new mesh(); // position source source casePositionSource = new source() { id = "case_position", name = "case_position" }; float_array farrayPosition = new float_array { id = "case_position_float_array", count = (ulong)doubleArrayPosition.Count, Values = doubleArrayPosition.ToArray() }; casePositionSource.technique_common = new sourceTechnique_common() { accessor = new accessor() { stride = 3, count = vertexCount, source = "#case_position_float_array", param = new param[] { new param() { name = "X", type = "float" }, new param() { name = "Y", type = "float" }, new param() { name = "Z", type = "float" } } } }; casePositionSource.Item = farrayPosition; // normal source source casePositionNormal = new source() { id = "case_normal", name = "case_normal" }; float_array farrayNormal = new float_array { id = "case_normal_float_array", count = (ulong)doubleArrayNormal.Count, Values = doubleArrayNormal.ToArray() }; casePositionNormal.technique_common = new sourceTechnique_common() { accessor = new accessor() { stride = 3, count = normalCount, source = "#case_normal_float_array", param = new param[] { new param() { name = "X", type = "float" }, new param() { name = "Y", type = "float" }, new param() { name = "Z", type = "float" } } } }; casePositionNormal.Item = farrayNormal; // uv source source casePositionUV = new source() { id = "case_UV", name = "pallet_UV" }; float_array farrayUV = new float_array { id = "case_UV_float_array", count = (ulong)doubleArrayUV.Count, Values = doubleArrayUV.ToArray() }; casePositionUV.technique_common = new sourceTechnique_common() { accessor = new accessor() { stride = 2, count = vertexCount, source = "#case_UV_float_array", param = new param[] { new param() { name = "S", type = "float" }, new param() { name = "T", type = "float" } } } }; casePositionUV.Item = farrayUV; // insert sources caseMesh.source = new source[] { casePositionSource, casePositionNormal, casePositionUV }; // vertices InputLocal verticesInput = new InputLocal() { semantic = "POSITION", source = "#case_position" }; caseMesh.vertices = new vertices() { id = "case_vertex", input = new InputLocal[] { verticesInput } }; List <object> trianglesList = new List <object>(); // build list of triangles foreach (HalfAxis.HAxis axis in HalfAxis.All) { triangles trianglesCase = new triangles() { material = string.Format("materialCase{0}", (uint)axis), count = 2 }; trianglesCase.input = new InputLocalOffset[] { new InputLocalOffset() { semantic = "VERTEX", source = "#case_vertex", offset = 0 } , new InputLocalOffset() { semantic = "NORMAL", source = "#case_normal", offset = 1 } , new InputLocalOffset() { semantic = "TEXCOORD", source = "#case_UV", offset = 2, set = 0, setSpecified = true } }; string triangle_string = string.Empty; foreach (TriangleIndices tr in box.TrianglesByFace(axis)) { triangle_string += tr.ConvertToString(0); } trianglesCase.p = triangle_string; trianglesList.Add(trianglesCase); } // build list of lines lines linesCase = new lines() { material = "materialCaseLines", count = 12, input = new InputLocalOffset[] { new InputLocalOffset() { semantic = "VERTEX", source = "#case_vertex", offset = 0 } }, p = "0 1 1 2 2 3 3 0 4 5 5 6 6 7 7 4 0 4 1 5 2 6 3 7" }; trianglesList.Add(linesCase); caseMesh.Items = trianglesList.ToArray(); return(caseMesh); }
static List <CELLMARK> cellmark_List = new List <CELLMARK>(); // для текущей сцены static void Main() { var filesName = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.cellgrup", SearchOption.AllDirectories); System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); List <Model> Models = new List <Model>(); // список мешей на сцене foreach (var file in filesName) { byte[] array1d = File.ReadAllBytes(file); int ci = 0; // счётчик вхождений //88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 using (var br = new BinaryReader(File.Open(file, FileMode.Open))) { for (int i = 0; i < array1d.Length; i++) // проходим по всем байтам файла *.cellgrup { if (array1d[i + 0] == 0x69 && array1d[i + 1] == 0x00 && array1d[i + 2] == 0x00 && array1d[i + 3] == 0x00 && // i*** array1d[i + 4] == 0x64 && array1d[i + 5] == 0x65 && array1d[i + 6] == 0x66 && array1d[i + 7] == 0x61 && // defa array1d[i + 8] == 0x75 && array1d[i + 9] == 0x6C && array1d[i + 10] == 0x74 && array1d[i + 11] == 0x00) // ult* { br.BaseStream.Position = i + 12; // отступаем от "вхождения" на i***default* байт int BlockSize = br.ReadInt32(); // размер блока br.ReadInt32(); // пропускаем пустые байты [00 00 00 00] int type = br.ReadInt32(); // "тип" модели if (type == 1819045731) { ci++; // coll[modc] } if (type == 1634493549) { ci++; // mdla[ttr*] } if (type == 6581618) // только для rmd*[****] { br.BaseStream.Position = i + 4; // "возвращаемся", чтобы скопировать модель Model mesh = new Model(); // создаём модель mesh.BaseStreamPosition = br.BaseStream.Position; mesh.type = type; mesh.index = ci++; // присваиваем и увеличиваем индекс mesh.content = br.ReadBytes(BlockSize).ToList(); Models.Add(mesh); // добавляем её в список моделей на "сцене" } i = i + BlockSize; // ускоряем поиск? } // 63 65 6C 6C 69 6E 73 74 (места моделей) if (array1d[i + 0] == 0x63 && array1d[i + 1] == 0x65 && array1d[i + 2] == 0x6C && array1d[i + 3] == 0x6C && // cell array1d[i + 4] == 0x69 && array1d[i + 5] == 0x6E && array1d[i + 6] == 0x73 && array1d[i + 7] == 0x74) // inst { br.BaseStream.Position = i + 16; int count = br.ReadInt32(); // кол-во координат для расстановки моделей for (int j = 0; j < count; j++) { CELLINST cellinst = new CELLINST(br); cellinst_List.Add(cellinst); } } // 63 65 6C 6C 6D 61 72 6B cellmark if (array1d[i + 0] == 0x63 && array1d[i + 1] == 0x65 && array1d[i + 2] == 0x6C && array1d[i + 3] == 0x6C && // cell array1d[i + 4] == 0x6D && array1d[i + 5] == 0x61 && array1d[i + 6] == 0x72 && array1d[i + 7] == 0x6B) // mark { br.BaseStream.Position = i + 16; int count = br.ReadInt32(); // кол-во координат для расстановки моделей for (int j = 0; j < count; j++) { CELLMARK cellmark = new CELLMARK(br); cellmark_List.Add(cellmark); } } } //88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 foreach (var mesh in Models) { for (int ji = 0; ji < mesh.content.Count; ji++) { // ИЩЕМ ВЕРШИНЫ // v // если нашли строку "position" = 00 00 00 00 70 6F 73 69 74 69 6F 6E if (mesh.content[ji + 0] == 0x70 && mesh.content[ji + 1] == 0x6F && mesh.content[ji + 2] == 0x73 && mesh.content[ji + 3] == 0x69 && // 70 6F 73 69 mesh.content[ji + 4] == 0x74 && mesh.content[ji + 5] == 0x69 && mesh.content[ji + 6] == 0x6F && mesh.content[ji + 7] == 0x6E) // 74 69 6F 6E { br.BaseStream.Position = mesh.BaseStreamPosition + ji + 16; // +20, если отступаем OOOO_position int count = br.ReadInt32(); for (int j = 0; j < count; j++) { mesh.positionList.Add(new Vector3(br)); } } ///////////// ИЩЕМ Vn (нормали) if (mesh.content[ji + 0] == 0x6E && mesh.content[ji + 1] == 0x6F && mesh.content[ji + 2] == 0x72 && mesh.content[ji + 3] == 0x6D && // 6E 6F 72 6D mesh.content[ji + 4] == 0x61 && mesh.content[ji + 5] == 0x6C && mesh.content[ji + 6] == 0x73 && mesh.content[ji + 7] == 0x00) // 61 6C 73 00 { br.BaseStream.Position = mesh.BaseStreamPosition + ji + 16; int count = br.ReadInt32(); for (int j = 0; j < count; j++) { mesh.normalsList.Add(new Vector3(br)); } } ///////////// ИЩЕМ ГРАНИ FACES // 70 72 69 6D // 73 ( 00 00 00 ) if (mesh.content[ji + 0] == 0x70 && mesh.content[ji + 1] == 0x72 && mesh.content[ji + 2] == 0x69 && mesh.content[ji + 3] == 0x6D) // 70 72 69 6D 73 { br.BaseStream.Position = mesh.BaseStreamPosition + ji + 16; int primsCount = br.ReadInt32(); for (int j = 0; j < primsCount; j++) { int faceNumber = br.ReadInt32(); int faceCount = br.ReadInt32(); int faceSize = br.ReadInt32(); List <TRI> face = new List <TRI>(); for (int f = 0; f < faceCount; f++) { face.Add(new TRI(br, faceNumber)); } mesh.subMeshFaces.Add(face); for (int jj = 0; jj < 10; jj++) { br.ReadInt32(); // непонятные данные, мб для наложения текстур } if ((faceCount % 2) != 0) { br.ReadUInt16(); // для "выравнивания" читается FF FF } } } ///////////// ИЩЕМ uvs index , индексы текстурных координат // строку "textures" = // (00 00 FF FF) 74 65 78 74 75 72 65 73 // if ( mesh.content[ji+0] == 0x00 && mesh.content[ji+1] == 0x00 && mesh.content[ji+2] == 0x00 && mesh.content[ji+3] == 0x00 && // это необходимо ? if (mesh.content[ji + 0] == 0x74 && mesh.content[ji + 1] == 0x65 && mesh.content[ji + 2] == 0x78 && mesh.content[ji + 3] == 0x74 && // если да mesh.content[ji + 4] == 0x75 && mesh.content[ji + 5] == 0x72 && mesh.content[ji + 6] == 0x65 && mesh.content[ji + 7] == 0x73) // то изменить индексы { br.BaseStream.Position = mesh.BaseStreamPosition + ji + 16; // или +20 в big файле int count = br.ReadInt32(); for (int j = 0; j < count; j++) { mesh.texturesList.Add(br.ReadUInt16()); } } ///////////// ТЕКСТУРНЫЕ КООРДИНАТЫ // vt // uvs. // 75 76 73 00 00 00 00 00 // может попастся два набора, поэтому пока что сохраняем смещение, а затем читаем что надо if (mesh.content[ji + 0] == 0x75 && mesh.content[ji + 1] == 0x76 && mesh.content[ji + 2] == 0x73 && mesh.content[ji + 3] == 0x00) // 75 76 73 00 { uvs_offset_int_list.Add(ji); } /////////////// /* * // mdlattr* * * if ( mesh.content[ji+0] == 0x6D && mesh.content[ji+1] == 0x64 && mesh.content[ji+2] == 0x6C && mesh.content[ji+3] == 0x61 && * mesh.content[ji+4] == 0x74 && mesh.content[ji+5] == 0x74 && mesh.content[ji+6] == 0x72 && mesh.content[ji+7] == 0x00) * { * br.BaseStream.Position = mesh.BaseStreamPosition + ji + 8; * int BlockSize = br.ReadInt32(); br.ReadInt32(); // 00 00 00 00 * * br.ReadInt32(); // 00 00 00 00 * br.ReadInt32(); // 00 00 00 00 * * int defaultBlockSize = br.ReadInt32(); * * br.ReadInt32(); * br.ReadInt32(); * } */ ///////////// mtlctrl* // 6D 74 6C 63 74 72 6C 00 if (mesh.content[ji + 0] == 0x6D && mesh.content[ji + 1] == 0x74 && mesh.content[ji + 2] == 0x6C && mesh.content[ji + 3] == 0x63 && // 6D 74 6C 63 mesh.content[ji + 4] == 0x74 && mesh.content[ji + 5] == 0x72 && mesh.content[ji + 6] == 0x6C && mesh.content[ji + 7] == 0x00) // 74 72 6C 00 { br.BaseStream.Position = mesh.BaseStreamPosition + ji + 16; int count = br.ReadInt32(); for (int j = 0; j < count; j++) { Mtlctrl mtlctrl = new Mtlctrl(br); mesh.mtlctrlList.Add(mtlctrl); } } ///////////// mlyrcolr ??? привильно ли я добавляю в список? по "сомнению" надо выделить три "строки" в один объект if (mesh.content[ji + 0] == 0x6D && mesh.content[ji + 1] == 0x6C && mesh.content[ji + 2] == 0x79 && mesh.content[ji + 3] == 0x72 && // 6D 6C 79 72 mesh.content[ji + 4] == 0x63 && mesh.content[ji + 5] == 0x6F && mesh.content[ji + 6] == 0x6C && mesh.content[ji + 7] == 0x72) // 63 6F 6C 72 { br.BaseStream.Position = mesh.BaseStreamPosition + ji + 20; int count = br.ReadInt32(); for (int j = 0; j < count; j++) { for (int jj = 0; jj < 3; jj++) { Mlyrcolr mlyrcolr = new Mlyrcolr(br); mesh.mlyrcolrList.Add(mlyrcolr); } } } ///////////// mlyrctrl +++ if (mesh.content[ji + 0] == 0x6D && mesh.content[ji + 1] == 0x6C && mesh.content[ji + 2] == 0x79 && mesh.content[ji + 3] == 0x72 && // 6D 6C 79 72 mesh.content[ji + 4] == 0x63 && mesh.content[ji + 5] == 0x74 && mesh.content[ji + 6] == 0x72 && mesh.content[ji + 7] == 0x6C) // 63 74 72 6C { br.BaseStream.Position = mesh.BaseStreamPosition + ji + 16; int flag = br.ReadInt32(); // 0 или 1 int count = br.ReadInt32(); for (int j = 0; j < count; j++) { Mlyrctrl m = new Mlyrctrl(br); mesh.mlyrctrlList.Add(m); } } ///////////// texture* +++ if (mesh.content[ji + 0] == 0x74 && mesh.content[ji + 1] == 0x65 && mesh.content[ji + 2] == 0x78 && mesh.content[ji + 3] == 0x74 && // 74 65 78 74 mesh.content[ji + 4] == 0x75 && mesh.content[ji + 5] == 0x72 && mesh.content[ji + 6] == 0x65 && mesh.content[ji + 7] == 0x00) // 75 72 65 00 { br.BaseStream.Position = mesh.BaseStreamPosition + ji + 20; // br.BaseStream.Position = mesh.BaseStreamPosition + ji + 20; int count = br.ReadInt32(); for (int j = 0; j < count; j++) { Texture thz = new Texture(br); mesh.texture_List.Add(thz); } } ///////////// vtxweigh +++ if (mesh.content[ji + 0] == 0x76 && mesh.content[ji + 1] == 0x74 && mesh.content[ji + 2] == 0x78 && mesh.content[ji + 3] == 0x77 && // 76 74 78 77 mesh.content[ji + 4] == 0x65 && mesh.content[ji + 5] == 0x69 && mesh.content[ji + 6] == 0x67 && mesh.content[ji + 7] == 0x68) // 65 69 67 68 { br.BaseStream.Position = mesh.BaseStreamPosition + ji + 16; int count = br.ReadInt32(); for (int ii = 0; ii < count; ii++) { mesh.vtxweighList.Add(br.ReadSingle()); } } ///////////// jointidx +++ if (mesh.content[ji + 0] == 0x6A && mesh.content[ji + 1] == 0x6F && mesh.content[ji + 2] == 0x69 && mesh.content[ji + 3] == 0x6E && // 6A 6F 69 6E // join mesh.content[ji + 4] == 0x74 && mesh.content[ji + 5] == 0x69 && mesh.content[ji + 6] == 0x64 && mesh.content[ji + 7] == 0x78) // 74 69 64 78 // tidx { br.BaseStream.Position = mesh.BaseStreamPosition + ji + 16; int count = br.ReadInt32(); for (int j = 0; j < count; j++) { mesh.jointidxList.Add(br.ReadUInt16()); } int ffff = 0; if (count % 2 != 0) { ffff = br.ReadUInt16(); } } ///////////// collmodc } // для массива внутри модели //88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 //88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 //88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 if (uvs_offset_int_list.Count > 0) { br.BaseStream.Position = mesh.BaseStreamPosition + uvs_offset_int_list[0] + 8; int BlockSizeU0 = br.ReadInt32(); br.ReadInt32(); int number0 = br.ReadInt32(); // 00 00 00 00 int uvsCount = br.ReadInt32(); for (int uvc = 0; uvc < uvsCount; uvc++) { mesh.uvs0.Add(new Vector2(br)); } mesh.uvsList.Add(mesh.uvs0); } if (uvs_offset_int_list.Count > 1) { br.BaseStream.Position = mesh.BaseStreamPosition + uvs_offset_int_list[1] + 8; int BlockSizeU1 = br.ReadInt32(); br.ReadInt32(); int number1 = br.ReadInt32(); // 01 00 00 00 int uvsCount = br.ReadInt32(); for (int uvc = 0; uvc < uvsCount; uvc++) { mesh.uvs1.Add(new Vector2(br)); } mesh.uvsList.Add(mesh.uvs1); } uvs_offset_int_list.Clear(); // обязательно очищаем для другой модели } // для каждой модели } // binary reader //88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 //88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 //88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 string name = file.Replace(".cellgrup", ""); library_geometries lgeom = new library_geometries() // создаём библиотеку мешей { geometry = new geometry[Models.Count] // в библиотеке геометрии Models.Count мешей }; ///////////////////////////////////////////////////////////////////////////////////////////////// int qqq = 0; // шагаем по списку геометрий в файле foreach (var mesh in Models) // для каждой модели { //----------------------------------------------------------------------------------------------- //{ создаём массив координат для вершин модели float_array xyz_N_array = new float_array() // массив для координат { count = (ulong)mesh.positionList.Count * 3, id = "mesh_" + mesh.index + "_positions_array" }; float_coords = new List <double>(); foreach (var fl in mesh.positionList) { float_coords.Add(fl.x); float_coords.Add(fl.y); float_coords.Add(fl.z); } xyz_N_array.Values = float_coords.ToArray(); //---------------------------------- source pos_source = new source() // источник для координат { Item = xyz_N_array, id = "mesh_" + mesh.index + "_positions", technique_common = new sourceTechnique_common() { accessor = new accessor() { count = (ulong)mesh.positionList.Count, offset = 0L, source = "#" + xyz_N_array.id, stride = 3L, param = new param[] { new param() { name = "X", type = "float" }, new param() { name = "Y", type = "float" }, new param() { name = "Z", type = "float" } } } } }; //} //----------------------------------------------------------------------------------------------- /* * //{ создаём массив координат для нормалей модели * * float_array xyz_Normals = new float_array() * { * count = (ulong)mesh.normalsList.Count * 3; * id = "mesh_" + mesh.index + "_normals_array"; * } * * float_coords = new List<double>(); * * foreach(var fl in mesh.positionList) * { * float_coords.Add(fl.x); * float_coords.Add(fl.y); * float_coords.Add(fl.z); * } * * xyz_Normals.Values = float_coords.ToArray(); * * //---------------------------------- * * source norm_source = new source() * { * Item = xyz_N_array, * id = "mesh_" + mesh.index + "_positions", * * technique_common = new sourceTechnique_common() * { * accessor = new accessor() * { * count = (ulong)mesh.positionList.Count, * offset = 0L, * source = "#" + xyz_N_array.id, * stride = 3L, * * param = new param[] * { * new param() { name = "X", type = "float" }, * new param() { name = "Y", type = "float" }, * new param() { name = "Z", type = "float" } * } * } * } * }; * //} */ //----------------------------------------------------------------------------------------------- vertices v = new vertices() // вершины = часть объекта mesh { id = "mesh_" + mesh.index + "_vertices", input = new InputLocal[] { new InputLocal() // пока что только коорднаты { semantic = "POSITION", source = "#" + pos_source.id } } }; //----------------------------------------------------------------------------------------------- int faceNumber = 0; foreach (var q in mesh.subMeshFaces) { foreach (var qq in q) { faceNumber++; } } triangles tres = new triangles() // треугольники = часть объекта mesh { count = (ulong)faceNumber, input = new InputLocalOffset[] { new InputLocalOffset() // пока что только для координат { semantic = "VERTEX", offset = 0L, source = "#" + v.id } } }; //---------------------------------- StringBuilder all_TRI = new StringBuilder(); foreach (var q in mesh.subMeshFaces) { foreach (var qq in q) { string str = qq.vi0 + " " + qq.vi1 + " " + qq.vi2 + " "; all_TRI.Append(str); } } tres.p = all_TRI.ToString(); //----------------------------------------------------------------------------------------------- mesh m = new mesh() // создаём объект меша { vertices = v, source = new source[1] // пока что только 1 источник для position { pos_source }, Items = new object[1] // для треугольников { tres } }; //----------------------------------------------------------------------------------------------- geometry geom = new geometry() // создаём оболочку для меши { id = "mesh_" + mesh.index, // задаём ей имя mesh_№ Item = m }; lgeom.geometry[qqq++] = geom; } // для каждой модели в файле cellgrup создаём блоки с геометрией //88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 library_visual_scenes lvs = new library_visual_scenes(); // создаём библиотеку сцен visual_scene vs = new visual_scene() // создаём сцену, вроде всегда одна { id = "MyScene", // обзываем её node = new node[Models.Count] // добавляем узлы для моделей на сцене }; //=============================================================================================== qqq = 0; // шагаем по списку мешей, создаём им ноды, задаём расположение foreach (var mesh in Models) { //---------------------------------- node n = new node() { id = "mesh" + mesh.index, instance_geometry = new instance_geometry[] { new instance_geometry() { url = "#" + lgeom.geometry[qqq].id } } }; //---------------------------------- n.ItemsElementName = new ItemsChoiceType2[5] { ItemsChoiceType2.translate, ItemsChoiceType2.rotate, ItemsChoiceType2.rotate, ItemsChoiceType2.rotate, ItemsChoiceType2.scale }; //---------------------------------- float xx = 0.0f; float yy = 0.0f; float zz = 0.0f; float rx = 0.0f; float ry = 0.0f; float rz = 0.0f; for (int ccc = 0; ccc < cellinst_List.Count; ccc++) { if (mesh.index == cellinst_List[ccc].number) { xx = cellinst_List[ccc].position.x; yy = cellinst_List[ccc].position.y; zz = cellinst_List[ccc].position.z; rx = cellinst_List[ccc].rotation.x; ry = cellinst_List[ccc].rotation.y; rz = cellinst_List[ccc].rotation.z; } } for (int ccc = 0; ccc < cellmark_List.Count; ccc++) { if (mesh.index == cellmark_List[ccc].number1) { xx = cellmark_List[ccc].position.x; yy = cellmark_List[ccc].position.y; zz = cellmark_List[ccc].position.z; rx = cellmark_List[ccc].rotation.x; ry = cellmark_List[ccc].rotation.y; rz = cellmark_List[ccc].rotation.z; } } //---------------------------------- n.Items = new object[5] { new TargetableFloat3() { sid = "location", // translate Values = new double[3] { xx, yy, zz } }, new rotate() { sid = "rotationX", Values = new double[4] { 0, 0, 1, rz *57.5 } }, // Z new rotate() { sid = "rotationY", Values = new double[4] { 0, 1, 0, ry *57.5 } }, // Y почему такой "угол" ? new rotate() { sid = "rotationZ", Values = new double[4] { 1, 0, 0, rx *57.5 } }, // X new TargetableFloat3() { sid = "scale", Values = new double[3] { 1, 1, 1 } } }; //---------------------------------- vs.node[qqq] = n; qqq++; } // для каждой модели в файле cellgrup //----------------------------------------------------------------------------------------------- lvs.visual_scene = new visual_scene[1] // создаём массив для сцен { vs // добавляем visual_scene в library_visual_scenes }; //----------------------------------------------------------------------------------------------- COLLADA collada = new COLLADA() { asset = new asset() { up_axis = UpAxisType.Z_UP }, Items = new object[] // для библиотеки мешей и сцен { lgeom, // присваиваем колладе библиотеку геометрию lvs // в массив Item добавляем библиотеку сцен }, scene = new COLLADAScene() { instance_visual_scene = new InstanceWithExtra() { url = "#" + vs.id } } }; //88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 collada.Save(name + ".dae"); Models.Clear(); cellinst_List.Clear(); cellmark_List.Clear(); //88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 } // для каждого cellgrup файла } // void Main()
internal DAEGeometry(DAELoaderNode loader, geometry geo) { if (geo.Item == null || !(geo.Item is mesh)) { // empty or not supported geometry return; } mesh m = geo.Item as mesh; // load sources Dictionary <string, MeshSource> sources = new Dictionary <string, MeshSource>(); foreach (source src in m.source) { if (src.Item is float_array) { float_array values = src.Item as float_array; int stride = (int)src.technique_common.accessor.stride; sources.Add(src.id, new MeshSource(values.Values, stride)); } } // load positions foreach (InputLocal input in m.vertices.input) { if (input.semantic.Equals("POSITION")) { sources.Add(m.vertices.id, sources[DAEUtils.GetUrl(input.source).Id]); break; } } // load primitives foreach (var item in m.Items) { // load triangles if (item is triangles) { triangles tris = item as triangles; DAEVertexDescription[] vertices = new DAEVertexDescription[tris.count * 3]; int[] p = DAEUtils.StringToIntArray(tris.p); int stepSize = p.Length / ((int)tris.count * 3); foreach (InputLocalOffset input in tris.input) { SetVertices(input, p, stepSize, sources, vertices); } if (!ContainsTangents(tris.input)) { GenerateMeshTangents(vertices); } _triangles.Add(new DAETriangles(loader, vertices, tris.material)); } else if (item is polylist) { polylist polys = item as polylist; int[] polyVertexCounts = DAEUtils.StringToIntArray(polys.vcount); int vertexCount = 0; int triCount = 0; for (int i = 0; i < polyVertexCounts.Length; i++) { vertexCount += polyVertexCounts[i]; triCount += polyVertexCounts[i] - 2; } DAEVertexDescription[] polyVertices = new DAEVertexDescription[vertexCount]; int[] p = DAEUtils.StringToIntArray(polys.p); int stepSize = p.Length / vertexCount; foreach (InputLocalOffset input in polys.input) { SetVertices(input, p, stepSize, sources, polyVertices); } // triangulation DAEVertexDescription[] triVertices = new DAEVertexDescription[triCount * 3]; int triVertexIdx = 0; int polyVertexIdx = 0; for (int i = 0; i < polyVertexCounts.Length; i++) { int triVertex = 0; for (int k = 0; k < polyVertexCounts[i]; k++) { if (triVertex == 3) { triVertex = 1; k--; // repeat first vertex triVertices[triVertexIdx++] = polyVertices[polyVertexIdx]; } triVertices[triVertexIdx++] = polyVertices[polyVertexIdx + k]; triVertex++; } // skip to next polygon polyVertexIdx += polyVertexCounts[i]; } if (!ContainsTangents(polys.input)) { GenerateMeshTangents(triVertices); } _triangles.Add(new DAETriangles(loader, triVertices, polys.material)); } } }
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { COLLADA model = new COLLADA(); // init new model.asset = new asset(); model.asset.contributor[1] = new assetContributor(); model.asset.contributor[0] = new assetContributor(); model.asset.unit = new assetUnit(); model.asset.up_axis = new UpAxisType(); model.Items = new object[1]; // asset model.asset.contributor[0].author = "caimagic"; model.asset.contributor[0].authoring_tool = "FBX COLLADA exporter"; model.asset.contributor[0].comments = "hello world"; model.asset.unit.meter = 0.01; model.asset.unit.name = "centimer"; model.asset.up_axis = UpAxisType.Y_UP; // library_geometries library_geometries library_geom = new library_geometries(); library_geom.geometry[1] = new geometry(); library_geom.geometry[0] = new geometry(); geometry geom = new geometry(); mesh geomMesh = new mesh(); geomMesh.source[3] = new source(); geomMesh.source[0] = new source(); geomMesh.source[1] = new source(); geomMesh.source[2] = new source(); float_array position_float_array = new float_array(); float_array normal_float_array = new float_array(); float_array uv_float_array = new float_array(); sourceTechnique_common position_technique_common = new sourceTechnique_common(); sourceTechnique_common normal_technique_common = new sourceTechnique_common(); sourceTechnique_common uv_technique_common = new sourceTechnique_common(); position_float_array.id = "Plane001-POSITION-array"; position_float_array.count = 9; //根据count创建一个数组 position_float_array.Values = new double[position_float_array.count]; position_float_array.Values[0] = -49.719101f; position_float_array.Values[1] = -41.011238f; position_float_array.Values[2] = 0.000000f; position_float_array.Values[3] = 49.719101f; position_float_array.Values[4] = -41.011238f; position_float_array.Values[5] = 0.000000f; position_float_array.Values[6] = -49.719101f; position_float_array.Values[7] = 41.011238f; position_float_array.Values[8] = 0.000000f; position_technique_common.accessor = new accessor(); /* * 创建数组的几种形式 * double[] array = new double[10]; * double[] array = { 0.0, 1.1, 2.2}; * double[] array = new double[5] { 99, 98, 92, 97, 95}; * double[] array = new double[ ] { 99, 98, 92, 97, 95}; * double[] another_array = array;*/ position_technique_common.accessor.param = new param[3]; position_technique_common.accessor.param[0] = new param(); position_technique_common.accessor.param[1] = new param(); position_technique_common.accessor.param[2] = new param(); position_technique_common.accessor.source = "#" + position_float_array.id; position_technique_common.accessor.count = 3; position_technique_common.accessor.stride = 3; position_technique_common.accessor.param[0].name = "X"; position_technique_common.accessor.param[0].type = "float"; position_technique_common.accessor.param[1].name = "Y"; position_technique_common.accessor.param[1].type = "float"; position_technique_common.accessor.param[2].name = "Z"; position_technique_common.accessor.param[2].type = "float"; normal_float_array.id = "Plane001-Normal0-array"; normal_float_array.count = 9; normal_float_array.Values = new double[normal_float_array.count]; normal_float_array.Values[0] = 0.0f; normal_float_array.Values[1] = 0.0f; normal_float_array.Values[2] = 1.0f; normal_float_array.Values[3] = 0.0f; normal_float_array.Values[4] = 0.0f; normal_float_array.Values[5] = 1.0f; normal_float_array.Values[6] = 0.0f; normal_float_array.Values[7] = 0.0f; normal_float_array.Values[8] = 1.0f; normal_technique_common.accessor = new accessor(); normal_technique_common.accessor.param = new param[3]; normal_technique_common.accessor.param[0] = new param(); normal_technique_common.accessor.param[1] = new param(); normal_technique_common.accessor.param[2] = new param(); normal_technique_common.accessor.source = "#" + normal_float_array.id; normal_technique_common.accessor.count = 3; normal_technique_common.accessor.stride = 3; normal_technique_common.accessor.param[0].name = "X"; normal_technique_common.accessor.param[0].type = "float"; normal_technique_common.accessor.param[1].name = "Y"; normal_technique_common.accessor.param[1].type = "float"; normal_technique_common.accessor.param[2].name = "Z"; normal_technique_common.accessor.param[2].type = "float"; uv_float_array.id = "Plane001-UV0-array"; uv_float_array.count = 6; uv_float_array.Values = new double[uv_float_array.count]; uv_float_array.Values[0] = 1.0000f; uv_float_array.Values[1] = 0.0000f; uv_float_array.Values[2] = 0.0000f; uv_float_array.Values[3] = 0.0000f; uv_float_array.Values[4] = 1.0000f; uv_float_array.Values[5] = 1.0000f; uv_technique_common.accessor = new accessor(); uv_technique_common.accessor.param = new param[2]; uv_technique_common.accessor.param[0] = new param(); uv_technique_common.accessor.param[1] = new param(); uv_technique_common.accessor.source = "#" + uv_float_array.id; uv_technique_common.accessor.count = 3; uv_technique_common.accessor.stride = 2; uv_technique_common.accessor.param[0].name = "S"; uv_technique_common.accessor.param[0].type = "float"; uv_technique_common.accessor.param[1].name = "T"; uv_technique_common.accessor.param[1].type = "float"; geomMesh.source[0].id = "Plane001-POSITION"; geomMesh.source[0].Item = position_float_array; geomMesh.source[0].technique_common = position_technique_common; geomMesh.source[1].id = "Plane001-Normal0"; geomMesh.source[1].Item = normal_float_array; geomMesh.source[1].technique_common = normal_technique_common; geomMesh.source[2].id = "Plane001-UV0"; geomMesh.source[2].Item = uv_float_array; geomMesh.source[2].technique_common = uv_technique_common; geomMesh.vertices = new vertices(); geomMesh.vertices.input[0] = new InputLocal(); geomMesh.vertices.input[0].semantic = "POSITION"; geomMesh.vertices.input[0].source = "#Plane001-POSITION"; geomMesh.vertices.id = "Plane001-VERTEX"; triangles meshTriangle = new triangles(); meshTriangle.count = 1; meshTriangle.input = new InputLocalOffset[3]; meshTriangle.input[0] = new InputLocalOffset(); meshTriangle.input[1] = new InputLocalOffset(); meshTriangle.input[2] = new InputLocalOffset(); meshTriangle.input[0].semantic = "VERTEX"; meshTriangle.input[0].offset = 0; meshTriangle.input[0].source = "#Plane001-VERTEX"; meshTriangle.input[1].semantic = "NORMAL"; meshTriangle.input[1].offset = 1; meshTriangle.input[1].source = "#Plane001-Normal0"; meshTriangle.input[2].semantic = "TEXCOORD"; meshTriangle.input[2].offset = 2; meshTriangle.input[2].set = 0; meshTriangle.input[2].source = "#Plane001-UV0"; string p = ""; int[] pArray = new int[9]; pArray[0] = 0; pArray[1] = 0; pArray[2] = 0; pArray[3] = 1; pArray[4] = 1; pArray[5] = 1; pArray[6] = 2; pArray[7] = 2; pArray[8] = 2; foreach (var data in pArray) { if (data is int) { p += " " + data.ToString(); } } meshTriangle.p = p; geomMesh.Items = new object[1]; geomMesh.Items[0] = new object(); geomMesh.Items[0] = meshTriangle; geom.Item = geomMesh; geom.id = "Plane001-lib"; geom.name = "Plane001Mesh"; library_geom.geometry[0] = geom; // library_visual_scenes library_visual_scenes lib_visual_scene = new library_visual_scenes(); lib_visual_scene.visual_scene = new visual_scene[1]; lib_visual_scene.visual_scene[0] = new visual_scene(); visual_scene visaul = new visual_scene(); visaul.node = new node[1]; visaul.node[0] = new node(); visaul.node[0].name = "Triangle001"; visaul.node[0].id = "Triangle001"; visaul.node[0].sid = "Triangle001"; visaul.node[0].instance_geometry = new instance_geometry[1]; visaul.node[0].instance_geometry[0] = new instance_geometry(); visaul.node[0].instance_geometry[0].url = "#Plane001-lib"; visaul.node[0].extra = new extra[1]; visaul.node[0].extra[0] = new extra(); visaul.node[0].extra[0].technique = new technique[1]; visaul.node[0].extra[0].technique[0] = new technique(); visaul.node[0].extra[0].technique[0].profile = "FCOLLADA"; visaul.name = "cube"; visaul.id = "cube"; lib_visual_scene.visual_scene[0] = visaul; model.Items = new object[2]; model.Items[0] = library_geom; model.Items[1] = lib_visual_scene; model.scene = new COLLADAScene(); model.scene.instance_visual_scene = new InstanceWithExtra(); model.scene.instance_visual_scene.url = "#" + visaul.id; model.Save("C:\\ProgramData\\Autodesk\\revit\\Addins\\2020\\dd.dae"); return(0); }
private static geometry SerializeModel(Geometry geometry_section, Topology topology_section, Model model_data, string id) { string VERT_ID = "vertices-" + id; string NORM_ID = "norms-" + id; string UV_ID = "uv-" + id; string RAW_VERT_ID = "vert_raw-" + id; int vertlen = geometry_section.verts.Count; int normlen = geometry_section.normals.Count; int uvlen = geometry_section.uvs.Count; triangles triangles = new triangles(); List <InputLocalOffset> inputs = new List <InputLocalOffset>(); inputs.Add(new InputLocalOffset { semantic = "VERTEX", source = "#" + VERT_ID, offset = 0, }); if (normlen > 0) { inputs.Add(new InputLocalOffset { semantic = "NORMAL", source = "#" + NORM_ID, offset = 0, }); } if (uvlen > 0) { inputs.Add(new InputLocalOffset { semantic = "TEXCOORD", source = "#" + UV_ID, offset = 0, set = 1, // IDK what this does or why we need it }); } triangles.input = inputs.ToArray(); mesh mesh = new mesh { vertices = new vertices { id = VERT_ID, input = new InputLocal[] { new InputLocal { semantic = "POSITION", source = "#" + RAW_VERT_ID } } }, Items = new object[] { triangles } }; StringBuilder facesData = new StringBuilder("\n"); // Start on a newline foreach (Face face in topology_section.facelist) { if (!face.BoundsCheck(vertlen)) { throw new Exception("Vert Out Of Bounds!"); } if (normlen > 0 && !face.BoundsCheck(normlen)) { throw new Exception("Norm Out Of Bounds!"); } if (uvlen > 0 && !face.BoundsCheck(uvlen)) { throw new Exception("UV Out Of Bounds!"); } // This set is used for the Vertices, Normals and UVs, as they all have the same indexes // A bit inefficent in terms of storage space, but easier to implement as that's how it's // handled inside the Diesel model files and making a index remapper thing would be a pain. facesData.AppendFormat("{0} {1} {2}\n", face.a, face.b, face.c); triangles.count++; } triangles.p = facesData.ToString(); List <source> sources = new List <source>(); sources.Add(GenerateSource(RAW_VERT_ID, geometry_section.verts)); if (normlen > 0) { sources.Add(GenerateSource(NORM_ID, geometry_section.normals)); } if (uvlen > 0) { sources.Add(GenerateSourceTex(UV_ID, geometry_section.uvs)); } mesh.source = sources.ToArray(); return(new geometry { name = "Diesel Converted Model " + id, id = "model-geom-" + id, Item = mesh }); }
public void Export(RootEntity[] entities, string selectedPath) { for (int i = 0; i < entities.Length; i++) { var entity = entities[i]; var modelCount = entity.ChildEntities.Length; var geometries = new library_geometries { geometry = new geometry[modelCount] }; var visualSceneNodes = new node[modelCount]; const string visualSceneName = "visual-scene"; var visualScenes = new library_visual_scenes { visual_scene = new[] { new visual_scene { id = visualSceneName, name = visualSceneName, node = visualSceneNodes } } }; for (int j = 0; j < modelCount; j++) { var model = (ModelEntity)entity.ChildEntities[j]; var modelName = string.Format("model-{0}-lib", j); var materialName = string.Format("{0}-material", modelName); var triangleCount = model.Triangles.Count(); var elementGroupCount = triangleCount * 3; var elementCount = elementGroupCount * 3; var acessorParams = new[] { new param { name = "X", type = "float" }, new param { name = "Y", type = "float" }, new param { name = "Z", type = "float" } }; #region Position var positionArrayName = string.Format("{0}-positions-array", modelName); var positionAccessor = new accessor { count = (ulong)elementGroupCount, offset = 0, source = string.Format("#{0}", positionArrayName), stride = 3, param = acessorParams }; var positionTechnique = new sourceTechnique_common { accessor = positionAccessor }; var positionArrayValues = new double[elementCount]; var positionArray = new float_array { id = positionArrayName, count = (ulong)elementCount, Values = positionArrayValues }; var positionName = string.Format("{0}-positions", modelName); var positionSource = new source { id = positionName, name = "position", Item = positionArray, technique_common = positionTechnique }; #endregion #region Normal var normalArrayName = string.Format("{0}-normals-array", modelName); var normalAccessor = new accessor { count = (ulong)elementGroupCount, offset = 0, source = string.Format("#{0}", normalArrayName), stride = 3, param = acessorParams }; var normalTechinique = new sourceTechnique_common { accessor = normalAccessor }; var normalArrayValues = new double[elementCount]; var normalArray = new float_array { id = normalArrayName, count = (ulong)elementCount, Values = normalArrayValues }; var normalName = string.Format("{0}-normals", modelName); var normalSource = new source { id = normalName, name = "normal", Item = normalArray, technique_common = normalTechinique }; #endregion #region Processing var triangleIndices = new StringBuilder(); for (int l = 0; l < model.Triangles.Length; l++) { var triangle = model.Triangles[l]; for (var k = 0; k < 3; k++) { var elementIndex = l * 3 + k; var vertex = triangle.Vertices[k]; var normal = triangle.Normals[k]; var color = triangle.Colors[k]; var uv = triangle.Uv[k]; positionArrayValues[elementIndex] = vertex.X; positionArrayValues[elementIndex + 1] = vertex.Y; positionArrayValues[elementIndex + 2] = vertex.Z; normalArrayValues[elementIndex] = normal.X; normalArrayValues[elementIndex + 1] = normal.Y; normalArrayValues[elementIndex + 2] = normal.Z; triangleIndices.Append(elementIndex); triangleIndices.Append(" "); } } #endregion #region Vertices var verticesName = string.Format("{0}-vertices", modelName); var triangles = new triangles { count = (ulong)triangleCount, material = materialName, input = new[] { new InputLocalOffset { offset = 0, semantic = "VERTEX", source = string.Format("#{0}", verticesName) }//, //new InputLocalOffset //{ // offset = 1, // semantic = "NORMAL", // source = string.Format("#{0}", normalName) //} }, p = triangleIndices.ToString() }; #endregion #region Mesh var mesh = new mesh { source = new[] { positionSource, normalSource }, vertices = new vertices { id = verticesName, input = new[] { new InputLocal { semantic = "POSITION", source = string.Format("#{0}", positionName) } } }, Items = new object[] { triangles } }; #endregion #region Geometry var geometryName = string.Format("{0}-geometry", modelName); var geometry = new geometry { id = geometryName, name = geometryName, Item = mesh }; geometries.geometry[j] = geometry; #endregion #region Visual Node var visualSceneNodeName = string.Format("{0}-node", modelName); visualSceneNodes[j] = new node { name = visualSceneNodeName, id = visualSceneNodeName, instance_geometry = new[] { new instance_geometry { url = string.Format("#{0}", geometryName) } } }; #endregion } var collada = new COLLADA { Items = new Object[] { geometries, visualScenes }, scene = new COLLADAScene { instance_visual_scene = new InstanceWithExtra { url = string.Format("#{0}", visualSceneName) } } }; var fileName = string.Format("{0}/dae{1}.dae", selectedPath, i); collada.Save(fileName); } }
public void SelectSubmesh(int submesh) { Triangles = _allTriangles[submesh]; }
public static void ExportIOModelAsDAE(string FileName, IOModel m) { COLLADA colladaFile = new COLLADA(); List <geometry> list_geometries = new List <geometry>(m.Meshes.Count); if (m.HasMeshes) { foreach (IOMesh iomesh in m.Meshes) { geometry g = new geometry(); g.name = iomesh.Name; g.id = iomesh.Name + $"_{m.Meshes.IndexOf(iomesh)}"; List <double> list_positions = new List <double>(); List <double> list_normals = new List <double>(); List <double> list_uvs = new List <double>(); List <double> list_colors = new List <double>(); foreach (IOVertex v in iomesh.Vertices) { list_positions.Add(v.Position.X); list_positions.Add(v.Position.Y); list_positions.Add(v.Position.Z); list_normals.Add(v.Normal.X); list_normals.Add(v.Normal.Y); list_normals.Add(v.Normal.Z); list_uvs.Add(v.UV0.X); list_uvs.Add(v.UV0.Y); } // Position source source_position = new source(); { float_array floats = new float_array(); floats.count = (ulong)list_positions.Count; floats.id = g.id + "_pos_arr"; floats.Values = list_positions.ToArray(); source_position = CreateSource(list_positions.Count, 3, floats.id, floats, new param[] { new param() { name = "X", type = "float" }, new param() { name = "Y", type = "float" }, new param() { name = "Z", type = "float" } }); } // Normal source source_normal = new source(); { float_array floats = new float_array(); floats.count = (ulong)list_normals.Count; floats.id = g.id + "_nrm_arr"; floats.Values = list_normals.ToArray(); source_normal = CreateSource(list_normals.Count, 3, floats.id, floats, new param[] { new param() { name = "X", type = "float" }, new param() { name = "Y", type = "float" }, new param() { name = "Z", type = "float" } }); } // UV0 source source_uv0 = new source(); { float_array floats = new float_array(); floats.count = (ulong)list_uvs.Count; floats.id = g.id + "_uv0_arr"; floats.Values = list_uvs.ToArray(); source_uv0 = CreateSource(list_uvs.Count, 2, floats.id, floats, new param[] { new param() { name = "S", type = "float" }, new param() { name = "T", type = "float" } }); } // vertices vertices vertices = new vertices(); vertices.id = g.id + "_verts"; vertices.input = new InputLocal[] { new InputLocal() { source = "#" + source_position.id, semantic = "POSITION" }, new InputLocal() { source = "#" + source_normal.id, semantic = "NORMAL" }, new InputLocal() { source = "#" + source_uv0.id, semantic = "TEXCOORD" } }; // triangles triangles triangles = new triangles(); triangles.count = (ulong)iomesh.Indices.Count; triangles.input = new InputLocalOffset[] { new InputLocalOffset() { offset = 0, semantic = "VERTEX", source = "#" + vertices.id } }; triangles.p = string.Join(" ", iomesh.Indices); // creating mesh mesh geomesh = new mesh(); geomesh.source = new source[] { source_position, source_normal, source_uv0 }; geomesh.Items = new object[] { triangles }; geomesh.vertices = vertices; g.Item = geomesh; list_geometries.Add(g); } } library_geometries lib_geometry = new library_geometries(); lib_geometry.geometry = list_geometries.ToArray(); // controllers List <controller> list_controller = new List <controller>(); if (m.HasMeshes && m.HasSkeleton) { // create lists List <source> skinSources = new List <source>(); List <string> boneNames = new List <string>(); List <double> InverseBinds = new List <double>(); foreach (RBone b in m.Skeleton.Bones) { boneNames.Add(b.Name); InverseBinds.AddRange(new double[] { b.InvWorldTransform.M11, b.InvWorldTransform.M21, b.InvWorldTransform.M31, b.InvWorldTransform.M41, b.InvWorldTransform.M12, b.InvWorldTransform.M22, b.InvWorldTransform.M32, b.InvWorldTransform.M42, b.InvWorldTransform.M13, b.InvWorldTransform.M23, b.InvWorldTransform.M33, b.InvWorldTransform.M43, b.InvWorldTransform.M14, b.InvWorldTransform.M24, b.InvWorldTransform.M34, b.InvWorldTransform.M44, }); } // setup controllers foreach (IOMesh iomesh in m.Meshes) { controller controller = new controller() { id = iomesh.Name + "_" + m.Meshes.IndexOf(iomesh) + "_controller" }; list_controller.Add(controller); // create source for weights List <double> weights = new List <double>(); List <int> bones = new List <int>(); List <int> boneCount = new List <int>(); StringBuilder build_v = new StringBuilder(); foreach (IOVertex v in iomesh.Vertices) { int bcount = 0; if (v.BoneWeights.X > 0) { if (!weights.Contains(v.BoneWeights.X)) { weights.Add(v.BoneWeights.X); } build_v.Append($"{(int)v.BoneIndices.X} {weights.IndexOf(v.BoneWeights.X)} "); bcount++; } if (v.BoneWeights.Y > 0) { if (!weights.Contains(v.BoneWeights.Y)) { weights.Add(v.BoneWeights.Y); } build_v.Append($"{(int)v.BoneIndices.Y} {weights.IndexOf(v.BoneWeights.Y)} "); bcount++; } if (v.BoneWeights.Z > 0) { if (!weights.Contains(v.BoneWeights.Z)) { weights.Add(v.BoneWeights.Z); } build_v.Append($"{(int)v.BoneIndices.Z} {weights.IndexOf(v.BoneWeights.Z)} "); bcount++; } if (v.BoneWeights.W > 0) { if (!weights.Contains(v.BoneWeights.W)) { weights.Add(v.BoneWeights.W); } build_v.Append($"{(int)v.BoneIndices.W} {weights.IndexOf(v.BoneWeights.W)} "); bcount++; } boneCount.Add(bcount); } // skin Name_array arr_name = new Name_array(); arr_name.count = (ulong)boneNames.Count; arr_name.id = controller.id + "joints"; arr_name.Values = boneNames.ToArray(); source source_skin = CreateSource(boneNames.Count, 1, arr_name.id, arr_name, new param[] { new param() { name = "JOINT", type = "name" } }); // bind float_array arr_bind = new float_array(); arr_bind.count = (ulong)InverseBinds.Count; arr_bind.id = controller.id + "binds"; arr_bind.Values = InverseBinds.ToArray(); source source_binds = CreateSource(InverseBinds.Count, 16, arr_bind.id, arr_bind, new param[] { new param() { name = "TRANSFORM", type = "float4x4" } }); // weight source source_weight = new source(); { float_array floats = new float_array(); floats.count = (ulong)weights.Count; floats.id = controller.id + "_weights"; floats.Values = weights.ToArray(); source_weight = CreateSource(weights.Count, 1, floats.id, floats, new param[] { new param() { name = "WEIGHT", type = "float" }, }); } skin skin = new skin(); skin.source1 = "#" + iomesh.Name + $"_{m.Meshes.IndexOf(iomesh)}"; skin.source = new source[] { source_skin, source_binds, source_weight }; skin.joints = new skinJoints() { input = new InputLocal[] { new InputLocal() { semantic = "JOINT", source = "#" + source_skin.id }, new InputLocal() { semantic = "INV_BIND_MATRIX", source = "#" + source_binds.id } } }; //skin weights skin.vertex_weights = new skinVertex_weights(); skin.vertex_weights.count = (ulong)iomesh.Vertices.Count; skin.vertex_weights.input = new InputLocalOffset[] { new InputLocalOffset() { semantic = "JOINT", source = "#" + source_skin.id, offset = 0 }, new InputLocalOffset() { semantic = "WEIGHT", source = "#" + source_weight.id, offset = 1 } }; skin.vertex_weights.vcount = string.Join(" ", boneCount); skin.vertex_weights.v = build_v.ToString(); controller.Item = skin; } } library_controllers lib_controllers = new library_controllers(); lib_controllers.controller = list_controller.ToArray(); // scene nodes List <node> scene_nodes = new List <node>(); int visual_index = 0; if (m.HasSkeleton) { Dictionary <RBone, node> boneToNode = new Dictionary <RBone, node>(); foreach (RBone b in m.Skeleton.Bones) { // create bone node node node = new node(); node.name = b.Name; node.id = "bone" + visual_index++; node.sid = b.Name; node.type = NodeType.JOINT; // add transform matrix mat = new matrix() { Values = new double[] { b.Transform.M11, b.Transform.M21, b.Transform.M31, b.Transform.M41, b.Transform.M12, b.Transform.M22, b.Transform.M32, b.Transform.M42, b.Transform.M13, b.Transform.M23, b.Transform.M33, b.Transform.M43, b.Transform.M14, b.Transform.M24, b.Transform.M34, b.Transform.M44, } }; node.ItemsElementName = new ItemsChoiceType2[] { ItemsChoiceType2.matrix }; node.Items = new object[] { mat }; // deal with parenting boneToNode.Add(b, node); if (b.ParentID == -1) { scene_nodes.Add(node); } else { if (boneToNode[m.Skeleton.Bones[b.ParentID]].node1 == null) { boneToNode[m.Skeleton.Bones[b.ParentID]].node1 = new node[0]; } node[] parentnode = boneToNode[m.Skeleton.Bones[b.ParentID]].node1; Array.Resize <node>(ref parentnode, parentnode.Length + 1); parentnode[parentnode.Length - 1] = node; boneToNode[m.Skeleton.Bones[b.ParentID]].node1 = parentnode; } } } if (m.HasMeshes) { foreach (IOMesh iomesh in m.Meshes) { node node = new node() { id = "mesh" + visual_index++, name = iomesh.Name, type = NodeType.NODE }; if (m.HasSkeleton) { instance_controller controller = new instance_controller() { url = iomesh.Name + "_" + m.Meshes.IndexOf(iomesh) + "_controller" }; controller.skeleton = new string[] { "#bone0" }; node.instance_controller = new instance_controller[] { controller }; } scene_nodes.Add(node); } } // visual scene root library_visual_scenes scenes = new library_visual_scenes(); scenes.visual_scene = new visual_scene[] { new visual_scene() { id = "visualscene0", name = "rdmscene" } }; scenes.visual_scene[0].node = scene_nodes.ToArray(); // scene COLLADAScene scene = new COLLADAScene(); scene.instance_visual_scene = new InstanceWithExtra() { url = "#visualscene0" }; // putting it all together colladaFile.Items = new object[] { lib_geometry, lib_controllers, scenes }; colladaFile.scene = scene; colladaFile.Save(FileName); }
// return mesh id private string CreateMeshWithSubmeshes(Mesh mesh, List <string> materialNames) { string id = ""; if (meshLookup.TryGetValue(mesh, out id)) { return(id); } var geometry = new geometry(); geometries.Add(geometry); id = CreateId(); geometry.id = id; var m = new mesh(); geometry.Item = m; m.source = new source[] { new source(), // position new source(), // normal new source(), // uvs }; m.source[0].id = CreateId(); var fa = new float_array(); fa.id = CreateId(); fa.Values = ToDoubleArray(mesh.vertices); fa.count = (ulong)fa.Values.Length; m.source[0].Item = fa; m.source[0].technique_common = new sourceTechnique_common(); m.source[0].technique_common.accessor = new accessor(); m.source[0].technique_common.accessor.count = fa.count / 3; m.source[0].technique_common.accessor.source = "#" + fa.id; m.source[0].technique_common.accessor.stride = 3; m.source[0].technique_common.accessor.param = new[] { new param(), new param(), new param() }; m.source[0].technique_common.accessor.param[0].name = "X"; m.source[0].technique_common.accessor.param[0].type = "float"; m.source[0].technique_common.accessor.param[1].name = "Y"; m.source[0].technique_common.accessor.param[1].type = "float"; m.source[0].technique_common.accessor.param[2].name = "Z"; m.source[0].technique_common.accessor.param[2].type = "float"; m.source[1].id = CreateId(); fa = new float_array(); fa.id = CreateId(); fa.Values = ToDoubleArray(mesh.normals); fa.count = (ulong)fa.Values.Length; m.source[1].Item = fa; m.source[1].technique_common = new sourceTechnique_common(); m.source[1].technique_common.accessor = new accessor(); m.source[1].technique_common.accessor.count = fa.count / 3; m.source[1].technique_common.accessor.source = "#" + fa.id; m.source[1].technique_common.accessor.stride = 3; m.source[1].technique_common.accessor.param = new[] { new param(), new param(), new param() }; m.source[1].technique_common.accessor.param[0].name = "X"; m.source[1].technique_common.accessor.param[0].type = "float"; m.source[1].technique_common.accessor.param[1].name = "Y"; m.source[1].technique_common.accessor.param[1].type = "float"; m.source[1].technique_common.accessor.param[2].name = "Z"; m.source[1].technique_common.accessor.param[2].type = "float"; m.source[2].id = CreateId(); fa = new float_array(); fa.id = CreateId(); fa.Values = ToDoubleArray(mesh.uv); fa.count = (ulong)fa.Values.Length; m.source[2].Item = fa; m.source[2].technique_common = new sourceTechnique_common(); m.source[2].technique_common.accessor = new accessor(); m.source[2].technique_common.accessor.count = fa.count / 2; m.source[2].technique_common.accessor.source = "#" + fa.id; m.source[2].technique_common.accessor.stride = 2; m.source[2].technique_common.accessor.param = new[] { new param(), new param() }; m.source[2].technique_common.accessor.param[0].name = "X"; m.source[2].technique_common.accessor.param[0].type = "float"; m.source[2].technique_common.accessor.param[1].name = "Y"; m.source[2].technique_common.accessor.param[1].type = "float"; m.vertices = new vertices(); m.vertices.id = CreateId(); m.vertices.input = new InputLocal[] { new InputLocal(), // position }; m.vertices.input[0].semantic = "POSITION"; m.vertices.input[0].source = "#" + m.source[0].id; var submeshes = new List <object>(); for (int i = 0; i < mesh.subMeshCount; i++) { var triangles = new List <int>(); var stringWriter = new StringWriter(); var t = mesh.GetTriangles(i); triangles.AddRange(t); for (int j = 0; j < t.Length; j = j + 3) { // index for position, normal and texcoord stringWriter.Write("{0} ", t[j]); stringWriter.Write("{0} ", t[j]); stringWriter.Write("{0} ", t[j]); stringWriter.Write("{0} ", t[j + 1]); stringWriter.Write("{0} ", t[j + 1]); stringWriter.Write("{0} ", t[j + 1]); stringWriter.Write("{0} ", t[j + 2]); stringWriter.Write("{0} ", t[j + 2]); stringWriter.Write("{0} ", t[j + 2]); } var tris = new triangles(); tris.count = (ulong)(triangles.Count / 3); tris.material = materialNames[i]; tris.input = new InputLocalOffset[] { new InputLocalOffset(), new InputLocalOffset(), new InputLocalOffset() }; tris.input[0].offset = 0; tris.input[0].semantic = "VERTEX"; tris.input[0].source = "#" + m.vertices.id; tris.p = stringWriter.ToString(); tris.input[1].offset = 1; tris.input[1].semantic = "NORMAL"; tris.input[1].source = "#" + m.source[1].id; tris.input[2].offset = 2; tris.input[2].semantic = "TEXCOORD"; tris.input[2].source = "#" + m.source[2].id; tris.input[2].set = 0; submeshes.Add(tris); } m.Items = submeshes.ToArray(); meshLookup[mesh] = id; return(id); }
// return mesh id private string CreateMesh(Mesh mesh) { string id = ""; if (meshLookup.TryGetValue(mesh, out id)) { return(id); } var geometry = new geometry(); geometries.Add(geometry); id = CreateId(); geometry.id = id; var m = new mesh(); geometry.Item = m; m.source = new source[] { new source(), // position new source(), // normal new source(), // uvs }; m.source[0].id = CreateId(); var fa = new float_array(); fa.id = CreateId(); fa.Values = ToDoubleArray(mesh.vertices); fa.count = (ulong)fa.Values.Length; m.source[0].Item = fa; m.source[0].technique_common = new sourceTechnique_common(); m.source[0].technique_common.accessor = new accessor(); m.source[0].technique_common.accessor.count = fa.count / 3; m.source[0].technique_common.accessor.source = "#" + fa.id; m.source[0].technique_common.accessor.stride = 3; m.source[0].technique_common.accessor.param = new[] { new param(), new param(), new param() }; m.source[0].technique_common.accessor.param[0].name = "X"; m.source[0].technique_common.accessor.param[0].type = "float"; m.source[0].technique_common.accessor.param[1].name = "Y"; m.source[0].technique_common.accessor.param[1].type = "float"; m.source[0].technique_common.accessor.param[2].name = "Z"; m.source[0].technique_common.accessor.param[2].type = "float"; m.source[1].id = CreateId(); fa = new float_array(); fa.id = CreateId(); fa.Values = ToDoubleArray(mesh.normals); fa.count = (ulong)fa.Values.Length; m.source[1].Item = fa; m.source[1].technique_common = new sourceTechnique_common(); m.source[1].technique_common.accessor = new accessor(); m.source[1].technique_common.accessor.count = fa.count / 3; m.source[1].technique_common.accessor.source = "#" + fa.id; m.source[1].technique_common.accessor.stride = 3; m.source[1].technique_common.accessor.param = new[] { new param(), new param(), new param() }; m.source[1].technique_common.accessor.param[0].name = "X"; m.source[1].technique_common.accessor.param[0].type = "float"; m.source[1].technique_common.accessor.param[1].name = "Y"; m.source[1].technique_common.accessor.param[1].type = "float"; m.source[1].technique_common.accessor.param[2].name = "Z"; m.source[1].technique_common.accessor.param[2].type = "float"; m.source[2].id = CreateId(); fa = new float_array(); fa.id = CreateId(); fa.Values = ToDoubleArray(mesh.uv); fa.count = (ulong)fa.Values.Length; m.source[2].Item = fa; m.source[2].technique_common = new sourceTechnique_common(); m.source[2].technique_common.accessor = new accessor(); m.source[2].technique_common.accessor.count = fa.count / 2; m.source[2].technique_common.accessor.source = "#" + fa.id; m.source[2].technique_common.accessor.stride = 2; m.source[2].technique_common.accessor.param = new[] { new param(), new param() }; m.source[2].technique_common.accessor.param[0].name = "X"; m.source[2].technique_common.accessor.param[0].type = "float"; m.source[2].technique_common.accessor.param[1].name = "Y"; m.source[2].technique_common.accessor.param[1].type = "float"; m.vertices = new vertices(); m.vertices.id = CreateId(); m.vertices.input = new InputLocal[] { new InputLocal(), // position new InputLocal(), // normal new InputLocal() // uvs }; m.vertices.input[0].semantic = "POSITION"; m.vertices.input[0].source = "#" + m.source[0].id; m.vertices.input[1].semantic = "NORMAL"; m.vertices.input[1].source = "#" + m.source[1].id; m.vertices.input[2].semantic = "TEXCOORD"; m.vertices.input[2].source = "#" + m.source[2].id; var triangles = new List <int>(); var stringWriter = new StringWriter(); for (int i = 0; i < mesh.subMeshCount; i++) { var t = mesh.GetTriangles(i); triangles.AddRange(t); for (int j = 0; j < t.Length; j = j + 3) { stringWriter.Write("{0} ", t[j]); stringWriter.Write("{0} ", t[j + 1]); stringWriter.Write("{0} ", t[j + 2]); } } var tris = new triangles(); tris.count = (ulong)(triangles.Count / 3); tris.material = defaultMaterialName; tris.input = new InputLocalOffset[] { new InputLocalOffset(), //new InputLocalOffset(), //new InputLocalOffset() }; tris.input[0].offset = 0; tris.input[0].semantic = "VERTEX"; tris.input[0].source = "#" + m.vertices.id; // <input semantic="TEXCOORD" source="#Cube-mesh-map-0" offset="2" set="0"/> /*tris.input[1].offset = 1; * tris.input[1].semantic = "NORMAL"; * tris.input[1].source= "#"+m.source[1].id; * * tris.input[2].offset = 2; * tris.input[2].semantic = "TEXCOORD"; * tris.input[2].source= "#"+m.source[2].id; * tris.input[2].set = 0; * tris.input[2].setSpecified = true;*/ tris.p = stringWriter.ToString(); m.Items = new object[] { tris }; meshLookup[mesh] = id; return(id); }