private void GenerateSegments(QuadDesc curQuad, ref ShapeDesc shape) { // use x, y of object instead of boundingbox center to determine segment int num1 = (int)((double)shape.x / ((double)this.quadOffset / 4.0)); int num2 = (int)((double)shape.y / ((double)this.quadOffset / 4.0)); if (num1 > 3) num1 = 3; if (num1 < 0) num1 = 0; if (num2 > 3) num2 = 3; if (num2 < 0) num2 = 0; SegmentDesc segmentDesc = new SegmentDesc(); segmentDesc.id = 4 * num1 + num2; segmentDesc.startTriangle = 0U; segmentDesc.numTriangles = shape.data.GetNumTriangles(); shape.segments = new List<SegmentDesc>(); shape.segments.Add(segmentDesc); }
private void MergeNodes(List<ShapeDesc> shapes) { int count = shapes.Count; Dictionary<string, List<ShapeDesc>> dictionary = new Dictionary<string, List<ShapeDesc>>(); for (int index = 0; index < shapes.Count; ++index) { ShapeDesc shape = new ShapeDesc(); shape = shapes[index]; string key = shape.textures[0].ToLower(); // use vertex color flag to seperate? // less draw calls more important than reducing a few bytes? // overall it is not even reducing bytes... so no /*if (useOptimizer && shape.data.HasVertexColors()) { key = key + "_VC"; }*/ // use material name from list file, Snow/Ash if (!this.ignoreMaterial && shape.material != "") { key = key + "_" + shape.material; } // only level 4 should have HD if (shape.isHighDetail && (this.quadLevel == 4 || useHDFlag)) { key = key + "_HD"; } // double-sided if (shape.isDoubleSided) { key = key + "_DS"; } // clamp mode key = key + "_" + shape.TextureClampMode; if (dictionary.ContainsKey(key)) { dictionary[key].Add(shape); } else { dictionary.Add(key, new List<ShapeDesc>()); dictionary[key].Add(shape); } } shapes.Clear(); foreach (KeyValuePair<string, List<ShapeDesc>> keyValuePair in dictionary) { if (keyValuePair.Value.Count == 1) { shapes.Add(keyValuePair.Value[0]); } else { SegmentDesc segmentDesc = (SegmentDesc)null; uint num1 = 0U; uint num2 = 0U; int num3 = -1; NiTriShape niTriShape = new NiTriShape(); NiTriShapeData data = new NiTriShapeData(); List<ShapeDesc> list = keyValuePair.Value; string str1 = list[0].textures[0]; string str2 = list[0].textures[1]; string str3 = list[0].material; //bool isVC = list[0].hasVertexColor; bool isHD = list[0].isHighDetail; // double-sided bool isDS = list[0].isDoubleSided; // clamp mode uint clampmode = list[0].TextureClampMode; bool allwhite = true; list.Sort((Comparison<ShapeDesc>)((a, b) => { if (a.segments[0].id > b.segments[0].id) return 1; return a.segments[0].id < b.segments[0].id ? -1 : 0; })); ShapeDesc shapeDesc = new ShapeDesc(); shapeDesc.boundingBox.Set(float.MaxValue, float.MinValue, float.MaxValue, float.MinValue, float.MaxValue, float.MinValue); for (int index1 = 0; index1 < list.Count; ++index1) { NiTriShapeData niTriShapeData = list[index1].data; List<Vector3> vertices = niTriShapeData.GetVertices(); List<Triangle> triangles = new List<Triangle>(niTriShapeData.GetTriangles()); if ((uint)data.GetNumVertices() + (uint)vertices.Count > (uint)ushort.MaxValue || (uint)data.GetNumTriangles() + (uint)triangles.Count > (uint)ushort.MaxValue) { data.SetCenter(shapeDesc.boundingBox.GetCenter() / (float)this.quadLevel); data.SetRadius(this.CalcRadius(data)); shapeDesc.segments.Add(segmentDesc); shapeDesc.shape = niTriShape; shapeDesc.data = data; shapeDesc.textures = new string[2]; shapeDesc.textures[0] = str1; shapeDesc.textures[1] = str2; shapeDesc.material = str3; shapeDesc.isHighDetail = isHD; //shapeDesc.hasVertexColor = isVC; // double-sided shapeDesc.isDoubleSided = isDS; //clamp mode shapeDesc.TextureClampMode = clampmode; shapes.Add(shapeDesc); shapeDesc = new ShapeDesc(); shapeDesc.boundingBox.Set(float.MaxValue, float.MinValue, float.MaxValue, float.MinValue, float.MaxValue, float.MinValue); niTriShape = new NiTriShape(); data = new NiTriShapeData(); num1 = 0U; num2 = 0U; num3 = -1; } for (int index2 = 0; index2 < (int)niTriShapeData.GetNumVertices(); ++index2) { Vector3 vector3 = vertices[index2] * (float)this.quadLevel; shapeDesc.boundingBox.GrowByVertex(vector3); } data.AppendVertices(niTriShapeData.GetVertices()); data.AppendNormals(niTriShapeData.GetNormals()); data.AppendUVCoords(niTriShapeData.GetUVCoords()); if (this.generateTangents) { //str3.Length != 0 if (!useOptimizer || (useOptimizer && (this.quadLevel == 4 || isHD))) { data.AppendTangents(niTriShapeData.GetTangents()); data.AppendBitangents(niTriShapeData.GetBitangents()); } } // only level 4 should have vertex colors if (this.generateVertexColors && (this.quadLevel == 4 || isHD)) { List<Color4> colors = new List<Color4>(); if (niTriShapeData.HasVertexColors()) { colors = niTriShapeData.GetVertexColors(); data.AppendVertexColors(colors); for (int index2 = 0; index2 < colors.Count; index2++) { if (colors[index2][0] != 1f || colors[index2][2] != 1f || colors[index2][2] != 1f) { allwhite = false; break; } } } else { for (int index2 = 0; index2 < vertices.Count; ++index2) { colors.Add(new Color4(1f, 1f, 1f, 1f)); } data.AppendVertexColors(colors); } } List<Triangle> trianglesNew = new List<Triangle>(); for (int index2 = 0; index2 < (int)niTriShapeData.GetNumTriangles(); ++index2) { trianglesNew.Add(new Triangle((ushort)(triangles[index2][0] + num1), (ushort)(triangles[index2][1] + num1), (ushort)(triangles[index2][2] + num1))); } data.AppendTriangles(trianglesNew); num1 += (uint)niTriShapeData.GetNumVertices(); if (list[index1].segments[0].id != num3) { if (num3 != -1) { num2 += (uint)segmentDesc.numTriangles * 3U; shapeDesc.segments.Add(segmentDesc); } segmentDesc = new SegmentDesc(); segmentDesc.id = list[index1].segments[0].id; segmentDesc.startTriangle = num2; segmentDesc.numTriangles = list[index1].segments[0].numTriangles; num3 = list[index1].segments[0].id; } else segmentDesc.numTriangles += list[index1].data.GetNumTriangles(); } data.SetCenter(shapeDesc.boundingBox.GetCenter() / (float)this.quadLevel); data.SetRadius(this.CalcRadius(data)); shapeDesc.segments.Add(segmentDesc); shapeDesc.shape = niTriShape; shapeDesc.data = data; shapeDesc.textures = new string[2]; shapeDesc.textures[0] = str1; shapeDesc.textures[1] = str2; shapeDesc.material = str3; //shapeDesc.hasVertexColor = isVC; shapeDesc.isHighDetail = isHD; // double-sided shapeDesc.isDoubleSided = isDS; // clamp mode shapeDesc.TextureClampMode = clampmode; if (allwhite) { shapeDesc.data.SetHasVertexColors(false); shapeDesc.hasVertexColor = false; } else { shapeDesc.data.SetHasVertexColors(true); shapeDesc.hasVertexColor = true; } shapes.Add(shapeDesc); } } }