public void Export(string filePath) { PalletProperties palletProperties = _palletSolution.Analysis.PalletProperties; COLLADA model = new COLLADA(); // asset model.asset = new asset() { created = DateTime.Now, modified = DateTime.Now }; model.asset.keywords = "StackBuilder Pallet Case"; model.asset.title = _palletSolution.Title; model.asset.unit = new assetUnit() { name = "millimeters", meter = 0.001 }; model.asset.up_axis = UpAxisType.Z_UP; library_images images = new library_images(); library_materials materials = new library_materials(); library_effects effects = new library_effects(); library_geometries geometries = new library_geometries(); library_nodes nodes = new library_nodes(); library_cameras cameras = new library_cameras(); library_animations animations = new library_animations(); library_visual_scenes scenes = new library_visual_scenes(); COLLADAScene colladaScene = new COLLADAScene(); model.Items = new Object[] { images, materials, effects, geometries, nodes, cameras, animations, scenes }; model.scene = colladaScene; // colors and materials List<effect> listEffects = new List<effect>(); List<material> listMaterials = new List<material>(); List<image> listImages = new List<image>(); // effects effect effectPallet; material materialPallet; CreateMaterial(palletProperties.Color, null, null, "Pallet", out effectPallet, out materialPallet); listEffects.Add(effectPallet); listMaterials.Add(materialPallet); Box box = new Box(0, _palletSolution.Analysis.BProperties); // build list of effects / materials / images uint faceIndex = 0; foreach (Face face in box.Faces) { // build texture image if any string textureName = null; if (face.HasBitmap) { textureName = string.Format("textureFace_{0}", faceIndex); string texturePath = System.IO.Path.Combine( System.IO.Path.GetDirectoryName(filePath) , textureName + ".jpg"); double dimX = 0.0, dimY = 0.0; switch (faceIndex) { case 0: dimX = box.Width; dimY = box.Height; break; case 1: dimX = box.Width; dimY = box.Height; break; case 2: dimX = box.Length; dimY = box.Height; break; case 3: dimX = box.Length; dimY = box.Height; break; case 4: dimX = box.Length; dimY = box.Width; break; case 5: dimX = box.Length; dimY = box.Width; break; default: break; } face.ExtractFaceBitmap(dimX, dimY, _bmpWidth, texturePath); // create image listImages.Add( new image() { id = textureName + ".jpg", name = textureName + ".jpg", Item = @".\" + textureName + @".jpg" } ); } material materialCase; effect effectCase; CreateMaterial(face.ColorFill, textureName, "0", string.Format("Case{0}", faceIndex), out effectCase, out materialCase); listEffects.Add(effectCase); listMaterials.Add(materialCase); ++faceIndex; } // add to image list images.image = listImages.ToArray(); // case lines material effect effectCaseLines; material materialCaseLines; CreateMaterial(Color.Black, null, null, "CaseLines", out effectCaseLines, out materialCaseLines); listEffects.Add(effectCaseLines); listMaterials.Add(materialCaseLines); effects.effect = listEffects.ToArray(); materials.material = listMaterials.ToArray(); // geometries geometry geomPallet = new geometry() { id = "palletGeometry", name = "palletGeometry" }; geometry geomCase = new geometry() { id = "caseGeometry", name = "caseGeometry" }; geometries.geometry = new geometry[] { geomPallet, geomCase }; // pallet mesh meshPallet = CreatePalletMesh(palletProperties); geomPallet.Item = meshPallet; // case mesh meshCase = CreateCaseMesh(_palletSolution.Analysis.BProperties as BoxProperties); geomCase.Item = meshCase; // library_animations animation animationMain = new animation() { id = "animationMain_ID", name = "animationMain" }; animations.animation = new animation[] { animationMain }; List<object> listAnimationSource = new List<object>(); // library_visual_scenes visual_scene mainScene = new visual_scene() { id = "MainScene", name = "MainScene" }; scenes.visual_scene = new visual_scene[] { mainScene }; List<node> sceneNodes = new List<node>(); sceneNodes.Add(new node() { id = "PalletNode", name = "PalletNode", instance_geometry = new instance_geometry[] { new instance_geometry() { url = "#palletGeometry", bind_material = new bind_material() { technique_common = new instance_material[] { new instance_material() { symbol="materialPallet", target=string.Format("#{0}", materialPallet.id) } } } } } }); uint caseIndex = 0; foreach (ILayer layer in _palletSolution) { BoxLayer bLayer = layer as BoxLayer; if (null == bLayer) continue; foreach (BoxPosition bp in bLayer) { Vector3D translation = bp.Position; Vector3D rotations = bp.Transformation.Rotations; node caseNode = new node() { id = string.Format("CaseNode_{0}_ID", caseIndex), name = string.Format("CaseNode_{0}", caseIndex), ItemsElementName = new ItemsChoiceType2[] { ItemsChoiceType2.translate, ItemsChoiceType2.rotate, ItemsChoiceType2.rotate, ItemsChoiceType2.rotate }, Items = new object[] { new TargetableFloat3() { Values = new double[] { translation.X, translation.Y, translation.Z }, sid = "t", }, new rotate() { Values = new double[] { 1.0, 0.0, 0.0, rotations.X }, sid = "rx" }, new rotate() { Values = new double[] { 0.0, 1.0, 0.0, rotations.Y }, sid = "ry" }, new rotate() { Values = new double[] { 0.0, 0.0, 1.0, rotations.Z }, sid = "rz" } }, instance_geometry = new instance_geometry[] { new instance_geometry() { url="#caseGeometry", bind_material = new bind_material() { technique_common = new instance_material[] { new instance_material() { symbol="materialCase0", target="#material_Case0_ID" }, new instance_material() { symbol="materialCase1", target="#material_Case1_ID" }, new instance_material() { symbol="materialCase2", target="#material_Case2_ID" }, new instance_material() { symbol="materialCase3", target="#material_Case3_ID" }, new instance_material() { symbol="materialCase4", target="#material_Case4_ID" }, new instance_material() { symbol="materialCase5", target="#material_Case5_ID" }, new instance_material() { symbol="materialCaseLines", target="#material_CaseLines_ID"} } } } } }; sceneNodes.Add(caseNode); // animations CreateAnimation(caseIndex, (uint)_palletSolution.CaseCount, listAnimationSource, bp); // increment case index ++caseIndex; } } // add nodes mainScene.node = sceneNodes.ToArray(); animationMain.Items = listAnimationSource.ToArray(); // library_cameras camera cameraCamera = new camera() { id = "Camera-Camera", name = "Camera-Camera" }; cameraOpticsTechnique_commonPerspective cameraPerspective = new cameraOpticsTechnique_commonPerspective() { znear = new TargetableFloat() { sid = "znear", Value = 1.0 }, zfar = new TargetableFloat() { sid = "zfar", Value = 10000.0 } }; cameraCamera.optics = new cameraOptics() { technique_common = new cameraOpticsTechnique_common() { Item = cameraPerspective } }; cameras.camera = new camera[] { cameraCamera }; // colladaScene colladaScene.instance_visual_scene = new InstanceWithExtra() { url = "#MainScene" }; model.Save(filePath); model.Save(System.IO.Path.ChangeExtension(filePath, "xml")); }
static ColladaSpline GetSpline(CL.UpAxisType up, CL.geometry geo) { var spline = geo.Item as CL.spline; if (spline == null) { return(null); } var conv = new ColladaSpline(); Dictionary <string, float[]> arrays = new Dictionary <string, float[]>(); Dictionary <string, GeometrySource> sources = new Dictionary <string, GeometrySource>(); //Get arrays foreach (var acc in spline.source) { var arr = acc.Item as CL.float_array; arrays.Add(arr.id, FloatArray(arr.Text)); } //Accessors foreach (var acc in spline.source) { sources.Add(acc.id, new GeometrySource(acc, arrays)); } //Process spline /*foreach(var input in spline.control_vertices.input) { * switch(input.semantic) { * * } * } * spline.*/ return(conv); }
CL.instance_material[] GetMaterials(CL.geometry g) { var materials = new List <CL.instance_material>(); foreach (var item in ((CL.mesh)g.Item).Items) { string matref = ((CL.triangles)item).material; if (!materials.Any((m) => m.symbol == matref)) { materials.Add(new CL.instance_material() { symbol = matref, target = "#" + matref }); } } return(materials.ToArray()); }
static ColladaGeometry GetGeometry(CL.UpAxisType up, CL.geometry geo, CL.library_materials matlib, CL.library_effects fxlib) { var conv = new ColladaGeometry() { FVF = D3DFVF.XYZ }; conv.Name = string.IsNullOrEmpty(geo.name) ? geo.id : geo.name; var msh = geo.Item as CL.mesh; if (msh == null) { return(null); } List <VertexPositionNormalDiffuseTextureTwo> vertices = new List <VertexPositionNormalDiffuseTextureTwo>(); List <int> hashes = new List <int>(); List <ushort> indices = new List <ushort>(); List <ColladaDrawcall> drawcalls = new List <ColladaDrawcall>(); Dictionary <string, GeometrySource> sources = new Dictionary <string, GeometrySource>(); Dictionary <string, float[]> arrays = new Dictionary <string, float[]>(); Dictionary <string, GeometrySource> verticesRefs = new Dictionary <string, GeometrySource>(); int placeHolderIdx = 0; //Get arrays foreach (var acc in msh.source) { var arr = acc.Item as CL.float_array; arrays.Add(arr.id, FloatArray(arr.Text)); } //Accessors foreach (var acc in msh.source) { sources.Add(acc.id, new GeometrySource(acc, arrays)); } //Process geometry foreach (var item in msh.Items) { if (!(item is CL.triangles || item is CL.polylist || item is CL.polygons)) { FLLog.Warning("Collada", "Ignoring " + item.GetType().Name + " element."); } } int totalTriangles = 0; foreach (var item in msh.Items.Where(x => x is CL.triangles || x is CL.polylist || x is CL.polygons)) { if (item is CL.triangles) { totalTriangles += (int)((CL.triangles)item).count; } else if (item is CL.polylist plist) { totalTriangles += (int)plist.count; } else { totalTriangles += (int)((CL.polygons)item).count; } } if (totalTriangles > 21845) { throw new Exception(string.Format( "Overflow!\nCollada geometry {0} has {1} triangles\nVMeshData has limit of 21845", string.IsNullOrEmpty(geo.name) ? geo.id : geo.name, totalTriangles)); } foreach (var item in msh.Items.Where(x => x is CL.triangles || x is CL.polylist || x is CL.polygons)) { CL.InputLocalOffset[] inputs; int[] pRefs; int indexCount; string materialRef; ColladaMaterial material; if (item is CL.triangles) { var triangles = (CL.triangles)item; indexCount = (int)(triangles.count * 3); pRefs = IntArray(triangles.p); inputs = triangles.input; materialRef = triangles.material; } else if (item is CL.polygons polygons) { indexCount = (int)(polygons.count * 3); int j = 0; pRefs = new int[indexCount]; foreach (var arr in polygons.Items) { if (!(arr is string)) { throw new Exception("Polygons: ph element unsupported"); } var ints = IntArray((string)arr); if (ints.Length != 3) { throw new Exception("Polygons: non-triangle geometry not supported"); } pRefs[j] = ints[0]; pRefs[j + 1] = ints[1]; pRefs[j + 2] = ints[2]; j += 3; } inputs = polygons.input; materialRef = polygons.material; } else { var plist = (CL.polylist)item; pRefs = IntArray(plist.p); foreach (var c in IntArray(plist.vcount)) { if (c != 3) { throw new Exception("Polylist: non-triangle geometry"); } } materialRef = plist.material; inputs = plist.input; indexCount = (int)(plist.count * 3); } if (indexCount == 0) { continue; //Skip empty } material = ParseMaterial(materialRef, matlib, fxlib); int pStride = 0; foreach (var input in inputs) { pStride = Math.Max((int)input.offset, pStride); } pStride++; GeometrySource sourceXYZ = null; int offXYZ = int.MinValue; GeometrySource sourceNORMAL = null; int offNORMAL = int.MinValue; GeometrySource sourceCOLOR = null; int offCOLOR = int.MinValue; GeometrySource sourceUV1 = null; int offUV1 = int.MinValue; GeometrySource sourceUV2 = null; int offUV2 = int.MinValue; int texCount = 0; int startIdx = indices.Count; foreach (var input in inputs) { switch (input.semantic) { case SEM_VERTEX: if (CheckURI(input.source) != msh.vertices.id) { throw new Exception("VERTEX doesn't match mesh vertices"); } foreach (var ip2 in msh.vertices.input) { switch (ip2.semantic) { case SEM_POSITION: offXYZ = (int)input.offset; sourceXYZ = sources[CheckURI(ip2.source)]; break; case SEM_NORMAL: offNORMAL = (int)input.offset; sourceNORMAL = sources[CheckURI(ip2.source)]; conv.FVF |= D3DFVF.NORMAL; break; case SEM_COLOR: offCOLOR = (int)input.offset; sourceCOLOR = sources[CheckURI(ip2.source)]; conv.FVF |= D3DFVF.DIFFUSE; break; case SEM_TEXCOORD: if (texCount == 2) { throw new Exception("Too many texcoords!"); } if (texCount == 1) { offUV2 = (int)input.offset; sourceUV2 = sources[CheckURI(ip2.source)]; conv.FVF &= ~D3DFVF.TEX1; conv.FVF |= D3DFVF.TEX2; } else { offUV1 = (int)input.offset; sourceUV1 = sources[CheckURI(ip2.source)]; if ((conv.FVF & D3DFVF.TEX2) != D3DFVF.TEX2) { conv.FVF |= D3DFVF.TEX1; } } texCount++; break; } } break; case SEM_POSITION: offXYZ = (int)input.offset; sourceXYZ = sources[CheckURI(input.source)]; break; case SEM_NORMAL: offNORMAL = (int)input.offset; sourceNORMAL = sources[CheckURI(input.source)]; conv.FVF |= D3DFVF.NORMAL; break; case SEM_COLOR: offCOLOR = (int)input.offset; sourceCOLOR = sources[CheckURI(input.source)]; conv.FVF |= D3DFVF.DIFFUSE; break; case SEM_TEXCOORD: if (texCount == 2) { throw new Exception("Too many texcoords!"); } if (texCount == 1) { offUV2 = (int)input.offset; sourceUV2 = sources[CheckURI(input.source)]; conv.FVF &= ~D3DFVF.TEX1; conv.FVF |= D3DFVF.TEX2; } else { offUV1 = (int)input.offset; sourceUV1 = sources[CheckURI(input.source)]; if ((conv.FVF & D3DFVF.TEX2) != D3DFVF.TEX2) { conv.FVF |= D3DFVF.TEX1; } } texCount++; break; } } int vertexOffset = vertices.Count; for (int i = 0; i < indexCount; i++) { int idx = i * pStride; var vert = new VertexPositionNormalDiffuseTextureTwo( VecAxis(up, sourceXYZ.GetXYZ(pRefs[idx + offXYZ])), offNORMAL == int.MinValue ? Vector3.Zero : VecAxis(up, sourceNORMAL.GetXYZ(pRefs[idx + offNORMAL])), offCOLOR == int.MinValue ? (uint)Color4.White.ToRgba() : (uint)sourceCOLOR.GetColor(pRefs[idx + offCOLOR]).ToRgba(), offUV1 == int.MinValue ? Vector2.Zero : sourceUV1.GetUV(pRefs[idx + offUV1]), offUV2 == int.MinValue ? Vector2.Zero : sourceUV2.GetUV(pRefs[idx + offUV2]) ); var hash = HashVert(ref vert); var vertIdx = FindDuplicate(hashes, vertices, vertexOffset, ref vert, hash); if (indices.Count >= ushort.MaxValue) { throw new Exception("Too many indices"); } if (vertIdx == -1) { if (vertices.Count + 1 >= ushort.MaxValue) { throw new Exception("Too many vertices"); } indices.Add((ushort)(vertices.Count - vertexOffset)); vertices.Add(vert); hashes.Add(hash); } else { indices.Add((ushort)(vertIdx - vertexOffset)); } } drawcalls.Add(new ColladaDrawcall() { StartIndex = startIdx, StartVertex = vertexOffset, EndVertex = vertices.Count - 1, TriCount = (indices.Count - startIdx) / 3, Material = material }); } conv.Indices = indices.ToArray(); conv.Vertices = vertices.ToArray(); conv.Drawcalls = drawcalls.ToArray(); conv.CalculateDimensions(); return(conv); }
public static geometry MeshToGeometry(CPUMesh inputMesh, string id) { geometry outputGeometry = new geometry(); mesh outputMesh = new mesh(); outputGeometry.id = id + "-lib"; outputGeometry.name = inputMesh.name + "-mesh"; outputGeometry.Item = outputMesh; //vertex Positions List <source> sourceList = new List <source>(); var inputVertices = inputMesh.vertices; if (inputVertices.Length == 0) { return(null); } sourceList.Add(ArrayToSource(inputMesh.vertices, id + "-POSITION")); vertices vertexList = new vertices(); vertexList.id = id + "-VERTEX"; vertexList.input = new InputLocal[1]; vertexList.input[0] = new InputLocal(); vertexList.input[0].semantic = "POSITION"; vertexList.input[0].source = "#" + sourceList[0].id; outputMesh.vertices = vertexList; List <InputLocalOffset> offsetList = new List <InputLocalOffset>(); { InputLocalOffset offset = new InputLocalOffset(); offset.semantic = "VERTEX"; offset.offset = 0; offset.source = "#" + vertexList.id; offsetList.Add(offset); } var inputNormals = inputMesh.normals; if (inputNormals.Length > 0) { var array = ArrayToSource(inputNormals, id + "-Normal0"); InputLocalOffset offset = new InputLocalOffset(); offset.semantic = "NORMAL"; offset.offset = (ulong)sourceList.Count; offset.source = "#" + array.id; sourceList.Add(array); offsetList.Add(offset); } var inputUV1s = inputMesh.uv; if (inputUV1s.Length > 0) { var array = ArrayToSource(inputUV1s, id + "-UV0"); InputLocalOffset offset = new InputLocalOffset(); offset.semantic = "TEXCOORD"; offset.offset = (ulong)sourceList.Count; offset.source = "#" + array.id; offset.set = 0; offset.setSpecified = true; sourceList.Add(array); offsetList.Add(offset); } var inputUV2s = inputMesh.uv2; if (inputUV2s.Length > 0) { var array = ArrayToSource(inputUV2s, id + "-UV1"); InputLocalOffset offset = new InputLocalOffset(); offset.semantic = "TEXCOORD"; offset.offset = (ulong)sourceList.Count; offset.source = "#" + array.id; offset.set = 1; offset.setSpecified = true; sourceList.Add(array); offsetList.Add(offset); } var inputColors = inputMesh.colors; if (inputColors.Length > 0) { var array = ArrayToSource(inputColors, id + "-VERTEX_COLOR0"); InputLocalOffset offset = new InputLocalOffset(); offset.semantic = "COLOR"; offset.offset = (ulong)sourceList.Count; offset.source = "#" + array.id; offset.set = 0; offset.setSpecified = true; sourceList.Add(array); offsetList.Add(offset); } outputMesh.source = sourceList.ToArray(); triangles triangleList = new triangles(); triangleList.input = offsetList.ToArray(); var inputTriangles = inputMesh.triangles; triangleList.count = (ulong)inputTriangles.Length / 3; if (triangleList.count == 0) { return(null); } StringBuilder pString = new StringBuilder(); for (int i = 0; i < inputTriangles.Length; i++) { for (int j = 0; j < triangleList.input.Length; j++) { pString.Append(inputTriangles[i]).Append(" "); } if (i % 3 == 2) { pString.AppendLine(); } else { pString.Append(" "); } } triangleList.p = pString.ToString(); outputMesh.Items = new object[1]; outputMesh.Items[0] = triangleList; return(outputGeometry); }
public static geometry MeshToGeometry(Mesh inputMesh) { string meshName = "Mesh-" + inputMesh.GetInstanceID(); geometry outputGeometry = new geometry(); mesh outputMesh = new mesh(); outputGeometry.id = meshName + "-lib"; outputGeometry.name = inputMesh.name + "-mesh"; outputGeometry.Item = outputMesh; //vertex Positions List<source> sourceList = new List<source>(); var inputVertices = inputMesh.vertices; if (inputVertices.Length == 0) return null; sourceList.Add(ArrayToSource(inputMesh.vertices, meshName + "-POSITION")); vertices vertexList = new vertices(); vertexList.id = meshName + "-VERTEX"; vertexList.input = new InputLocal[1]; vertexList.input[0] = new InputLocal(); vertexList.input[0].semantic = "POSITION"; vertexList.input[0].source = "#" + sourceList[0].id; outputMesh.vertices = vertexList; List<InputLocalOffset> offsetList = new List<InputLocalOffset>(); { InputLocalOffset offset = new InputLocalOffset(); offset.semantic = "VERTEX"; offset.offset = 0; offset.source = "#" + vertexList.id; offsetList.Add(offset); } var inputNormals = inputMesh.normals; if(inputNormals.Length > 0) { var array = ArrayToSource(inputNormals, meshName + "-Normal0"); InputLocalOffset offset = new InputLocalOffset(); offset.semantic = "NORMAL"; offset.offset = (ulong)sourceList.Count; offset.source = "#" + array.id; sourceList.Add(array); offsetList.Add(offset); } var inputUV1s = inputMesh.uv; if (inputUV1s.Length > 0) { var array = ArrayToSource(inputUV1s, meshName + "-UV0"); InputLocalOffset offset = new InputLocalOffset(); offset.semantic = "TEXCOORD"; offset.offset = (ulong)sourceList.Count; offset.source = "#" + array.id; offset.set = 0; offset.setSpecified = true; sourceList.Add(array); offsetList.Add(offset); } var inputUV2s = inputMesh.uv2; if (inputUV2s.Length > 0) { var array = ArrayToSource(inputUV2s, meshName + "-UV1"); InputLocalOffset offset = new InputLocalOffset(); offset.semantic = "TEXCOORD"; offset.offset = (ulong)sourceList.Count; offset.source = "#" + array.id; offset.set = 1; offset.setSpecified = true; sourceList.Add(array); offsetList.Add(offset); } var inputColors = inputMesh.colors; if (inputColors.Length > 0) { var array = ArrayToSource(inputColors, meshName + "-VERTEX_COLOR0"); InputLocalOffset offset = new InputLocalOffset(); offset.semantic = "COLOR"; offset.offset = (ulong)sourceList.Count; offset.source = "#" + array.id; offset.set = 0; offset.setSpecified = true; sourceList.Add(array); offsetList.Add(offset); } outputMesh.source = sourceList.ToArray(); triangles triangleList = new triangles(); triangleList.input = offsetList.ToArray(); var inputTriangles = inputMesh.triangles; triangleList.count = (ulong)inputTriangles.Length / 3; if (triangleList.count == 0) return null; StringBuilder pString = new StringBuilder(); for(int i = 0; i < inputTriangles.Length; i++) { for(int j = 0; j < triangleList.input.Length; j++) { pString.Append(inputTriangles[i]).Append(" "); } if (i % 3 == 2) pString.AppendLine(); else pString.Append(" "); } triangleList.p = pString.ToString(); outputMesh.Items = new object[1]; outputMesh.Items[0] = triangleList; return outputGeometry; }
static ColladaGeometry GetGeometry(CL.UpAxisType up, CL.geometry geo) { var conv = new ColladaGeometry() { FVF = D3DFVF.XYZ }; var msh = geo.Item as CL.mesh; if (msh == null) { return(null); } List <VertexPositionNormalDiffuseTextureTwo> vertices = new List <VertexPositionNormalDiffuseTextureTwo>(); List <ushort> indices = new List <ushort>(); List <ColladaDrawcall> drawcalls = new List <ColladaDrawcall>(); Dictionary <string, GeometrySource> sources = new Dictionary <string, GeometrySource>(); Dictionary <string, float[]> arrays = new Dictionary <string, float[]>(); Dictionary <string, GeometrySource> verticesRefs = new Dictionary <string, GeometrySource>(); //Get arrays foreach (var acc in msh.source) { var arr = acc.Item as CL.float_array; arrays.Add(arr.id, FloatArray(arr.Text)); } //Accessors foreach (var acc in msh.source) { sources.Add(acc.id, new GeometrySource(acc, arrays)); } //Process geometry if (msh.Items.Where(x => x is CL.triangles || x is CL.polylist).Count() != msh.Items.Length) { throw new Exception("Non-triangle geometry"); } foreach (var item in msh.Items.Where(x => x is CL.triangles || x is CL.polylist)) { CL.InputLocalOffset[] inputs; int[] pRefs; int triangleCount; string material; if (item is CL.triangles) { var triangles = (CL.triangles)item; pRefs = IntArray(triangles.p); inputs = triangles.input; triangleCount = (int)(triangles.count * 3); material = triangles.material; } else { var plist = (CL.polylist)item; pRefs = IntArray(plist.p); foreach (var c in IntArray(plist.vcount)) { if (c != 3) { throw new Exception("Polylist: non-triangle geometry"); } } material = plist.material; inputs = plist.input; triangleCount = (int)(plist.count * 3); } int pStride = 0; foreach (var input in inputs) { pStride = Math.Max((int)input.offset, pStride); } pStride++; GeometrySource sourceXYZ = null; int offXYZ = int.MinValue; GeometrySource sourceNORMAL = null; int offNORMAL = int.MinValue; GeometrySource sourceCOLOR = null; int offCOLOR = int.MinValue; GeometrySource sourceUV1 = null; int offUV1 = int.MinValue; GeometrySource sourceUV2 = null; int offUV2 = int.MinValue; int texCount = 0; int startIdx = indices.Count; foreach (var input in inputs) { switch (input.semantic) { case SEM_VERTEX: if (CheckURI(input.source) != msh.vertices.id) { throw new Exception("VERTEX doesn't match mesh vertices"); } foreach (var ip2 in msh.vertices.input) { switch (ip2.semantic) { case SEM_POSITION: offXYZ = (int)input.offset; sourceXYZ = sources[CheckURI(ip2.source)]; break; case SEM_NORMAL: offNORMAL = (int)input.offset; sourceNORMAL = sources[CheckURI(ip2.source)]; conv.FVF |= D3DFVF.NORMAL; break; case SEM_COLOR: offCOLOR = (int)input.offset; sourceCOLOR = sources[CheckURI(ip2.source)]; conv.FVF |= D3DFVF.DIFFUSE; break; case SEM_TEXCOORD: if (texCount == 2) { throw new Exception("Too many texcoords!"); } if (texCount == 1) { offUV2 = (int)input.offset; sourceUV2 = sources[CheckURI(ip2.source)]; conv.FVF &= ~D3DFVF.TEX1; conv.FVF |= D3DFVF.TEX2; } else { offUV1 = (int)input.offset; sourceUV1 = sources[CheckURI(ip2.source)]; if ((conv.FVF & D3DFVF.TEX2) != D3DFVF.TEX2) { conv.FVF |= D3DFVF.TEX1; } } texCount++; break; } } break; case SEM_POSITION: offXYZ = (int)input.offset; sourceXYZ = sources[CheckURI(input.source)]; break; case SEM_NORMAL: offNORMAL = (int)input.offset; sourceNORMAL = sources[CheckURI(input.source)]; conv.FVF |= D3DFVF.NORMAL; break; case SEM_COLOR: offCOLOR = (int)input.offset; sourceCOLOR = sources[CheckURI(input.source)]; conv.FVF |= D3DFVF.DIFFUSE; break; case SEM_TEXCOORD: if (texCount == 2) { throw new Exception("Too many texcoords!"); } if (texCount == 1) { offUV2 = (int)input.offset; sourceUV2 = sources[CheckURI(input.source)]; conv.FVF &= ~D3DFVF.TEX1; conv.FVF |= D3DFVF.TEX2; } else { offUV1 = (int)input.offset; sourceUV1 = sources[CheckURI(input.source)]; if ((conv.FVF & D3DFVF.TEX2) != D3DFVF.TEX2) { conv.FVF |= D3DFVF.TEX1; } } texCount++; break; } } for (int i = 0; i < triangleCount; i++) { int idx = i * pStride; var vert = new VertexPositionNormalDiffuseTextureTwo( VecAxis(up, sourceXYZ.GetXYZ(pRefs[idx + offXYZ])), offNORMAL == int.MinValue ? Vector3.Zero : VecAxis(up, sourceNORMAL.GetXYZ(pRefs[idx + offNORMAL])), offCOLOR == int.MinValue ? Color4.White : sourceCOLOR.GetColor(pRefs[idx + offCOLOR]), offUV1 == int.MinValue ? Vector2.Zero : sourceUV1.GetUV(pRefs[idx + offUV1]), offUV2 == int.MinValue ? Vector2.Zero : sourceUV2.GetUV(pRefs[idx + offUV2]) ); var vertIdx = vertices.IndexOf(vert); if (indices.Count >= ushort.MaxValue) { throw new Exception("Too many indices"); } if (vertIdx == -1) { if (vertices.Count + 1 >= ushort.MaxValue) { throw new Exception("Overflow"); } indices.Add((ushort)vertices.Count); vertices.Add(vert); } else { indices.Add((ushort)vertIdx); } } drawcalls.Add(new ColladaDrawcall() { Start = startIdx, TriCount = (indices.Count - startIdx) / 3, Material = string.IsNullOrEmpty(material) ? "NullMaterial" : material }); } conv.Indices = indices.ToArray(); conv.Vertices = vertices.ToArray(); conv.Drawcalls = drawcalls.ToArray(); conv.CalculateDimensions(); return(conv); }
static ExportModel ProcessModel(ModelFile mdl, ResourceManager resources) { mdl.Path = mdl.Path.Replace(' ', '_'); var ex = new ExportModel(); for (int midx = 0; midx < mdl.Levels.Length; midx++) { var lvl = mdl.Levels[midx]; var processed = ProcessRef(lvl, resources); var geo = new CL.geometry(); geo.name = geo.id = mdl.Path + "-level" + midx; var mesh = new CL.mesh(); geo.Item = mesh; CL.source positions; CL.source normals = null; CL.source colors = null; CL.source tex1 = null; CL.source tex2 = null; int idxC = 1; positions = CreateSource( geo.name + "-positions", (k) => new Vector4(processed.Vertices[k].Position, 0), 3, processed.Vertices.Length); mesh.vertices = new CL.vertices() { id = geo.name + "-vertices", input = new CL.InputLocal[] { new CL.InputLocal() { semantic = "POSITION", source = "#" + positions.id } } }; var sources = new List <CL.source>() { positions }; if ((processed.FVF & D3DFVF.NORMAL) == D3DFVF.NORMAL) { normals = CreateSource( geo.name + "-normals", (k) => new Vector4(processed.Vertices[k].Normal, 0), 3, processed.Vertices.Length); sources.Add(normals); idxC++; } if ((processed.FVF & D3DFVF.DIFFUSE) == D3DFVF.DIFFUSE) { colors = CreateSource( geo.name + "-color", (k) => { var c = Color4.FromRgba(processed.Vertices[k].Diffuse); return(new Vector4(c.R, c.G, c.B, c.A)); }, 4, processed.Vertices.Length); sources.Add(colors); idxC++; } bool doTex1, doTex2 = false; if ((processed.FVF & D3DFVF.TEX2) == D3DFVF.TEX2) { doTex1 = doTex2 = true; } else if ((processed.FVF & D3DFVF.TEX1) == D3DFVF.TEX1) { doTex1 = true; } else { doTex1 = doTex2 = false; } if (doTex1) { tex1 = CreateSource( geo.name + "-tex1", (k) => new Vector4(processed.Vertices[k].TextureCoordinate, 0, 0), 2, processed.Vertices.Length); sources.Add(tex1); idxC++; } if (doTex2) { tex2 = CreateSource( geo.name + "-tex2", (k) => new Vector4(processed.Vertices[k].TextureCoordinateTwo, 0, 0), 2, processed.Vertices.Length); sources.Add(tex2); idxC++; } mesh.source = sources.ToArray(); var items = new List <object>(); foreach (var dc in processed.Drawcalls) { if (!ex.Materials.Any((x) => x.Name == dc.Material.Name)) { ex.Materials.Add(dc.Material); } var trs = new CL.triangles(); trs.count = (ulong)(dc.Indices.Length / 3); trs.material = dc.Material.Name + "-material"; List <int> pRefs = new List <int>(dc.Indices.Length * idxC); List <CL.InputLocalOffset> inputs = new List <CL.InputLocalOffset>() { new CL.InputLocalOffset() { semantic = "VERTEX", source = "#" + geo.id + "-vertices", offset = 0 } }; ulong off = 1; if (normals != null) { inputs.Add(new CL.InputLocalOffset() { semantic = "NORMAL", source = "#" + normals.id, offset = off++ }); } if (colors != null) { inputs.Add(new CL.InputLocalOffset() { semantic = "COLOR", source = "#" + colors.id, offset = off++ }); } if (tex1 != null) { inputs.Add(new CL.InputLocalOffset() { semantic = "TEXCOORD", source = "#" + tex1.id, offset = off++ }); } if (tex2 != null) { inputs.Add(new CL.InputLocalOffset() { semantic = "TEXCOORD", source = "#" + tex2.id, offset = off++ }); } trs.input = inputs.ToArray(); for (int i = 0; i < dc.Indices.Length; i++) { for (int j = 0; j < idxC; j++) { pRefs.Add(dc.Indices[i]); } } trs.p = string.Join(" ", pRefs.ToArray()); items.Add(trs); } mesh.Items = items.ToArray(); ex.Geometries.Add(geo); } return(ex); }