private List<ShapeDesc> IterateNodes(QuadDesc quad, StaticDesc stat, int level, NiFile file, NiNode parentNode, Matrix44 parentTransform, float parentScale) { List<ShapeDesc> list = new List<ShapeDesc>(); if (parentNode == null || parentNode.IsHidden()) return list; int nameIndex = parentNode.GetNameIndex(); string str = nameIndex != -1 ? file.GetStringAtIndex(nameIndex) : parentNode.GetName(); if (str != null && str.ToLower().Contains("editormarker")) return list; Matrix44 parentTransform1 = parentNode.GetTransform() * parentTransform; if (ignoreTransRot.Any(stat.staticModels[level].Contains)) { parentTransform1 = parentTransform; } float parentScale1 = parentNode.GetScale() * parentScale; uint numChildren = parentNode.GetNumChildren(); for (int index = 0; (long)index < (long)numChildren; ++index) { NiObject blockAtIndex = file.GetBlockAtIndex(parentNode.GetChildAtIndex(index)); if (blockAtIndex != null) { if (blockAtIndex.IsDerivedType("NiNode")) { list.AddRange((IEnumerable<ShapeDesc>)this.IterateNodes(quad, stat, level, file, (NiNode)blockAtIndex, parentTransform1, parentScale1)); } else if (blockAtIndex.IsDerivedType("NiTriBasedGeom")) { NiTriBasedGeom geomOld = (NiTriBasedGeom)blockAtIndex; if (index + 1 < numChildren) { NiObject blockAtIndexNext = file.GetBlockAtIndex(parentNode.GetChildAtIndex(index + 1)); if (blockAtIndexNext.IsDerivedType("NiTriBasedGeom")) { NiTriBasedGeom geomOld2 = (NiTriBasedGeom)blockAtIndexNext; if (geomOld.GetData() == geomOld2.GetData()) { //Console.WriteLine(geomOld.GetData() + " = " + geomOld2.GetData()); NiTriBasedGeom geomNew = new NiTriBasedGeom(); geomNew.SetFlags(14); geomNew.SetTranslation(geomOld.GetTranslation()); geomNew.SetRotation(geomOld.GetRotation()); geomNew.SetScale(geomOld.GetScale()); geomNew.SetNumProperties(geomOld.GetNumProperties()); for (int index2 = 0; (long)index2 < (long)geomOld.GetNumProperties(); ++index2) { geomNew.SetProperties(geomOld.GetProperty(index2)); } NiTriShapeData dataOld = (NiTriShapeData)file.GetBlockAtIndex(geomOld.GetData()); NiTriShapeData dataNew = new NiTriShapeData(); dataNew.SetNumVertices(dataOld.GetNumVertices()); dataNew.SetHasVertices(dataOld.HasVertices()); dataNew.SetVertices(new List<Vector3>(dataOld.GetVertices())); dataNew.SetNumUVSets(dataOld.GetBSNumUVSets()); dataNew.SetHasNormals(dataOld.HasNormals()); dataNew.SetNormals(new List<Vector3>(dataOld.GetNormals())); dataNew.SetTangents(new List<Vector3>(dataOld.GetTangents())); dataNew.SetBitangents(new List<Vector3>(dataOld.GetBitangents())); dataNew.SetCenter(dataOld.GetCenter()); dataNew.SetRadius(dataOld.GetRadius()); dataNew.SetHasVertexColors(dataOld.HasVertexColors()); dataNew.SetVertexColors(dataOld.GetVertexColors()); dataNew.SetUVCoords(dataOld.GetUVCoords()); dataNew.SetConsistencyFlags(dataOld.GetConsistencyFlags()); dataNew.SetNumTriangles(dataOld.GetNumTriangles()); dataNew.SetNumTrianglePoints(dataOld.GetNumTrianglePoints()); dataNew.SetHasTriangles(dataOld.HasTriangles()); dataNew.SetTriangles(new List<Triangle>(dataOld.GetTriangles())); int newdata = file.AddBlock(dataNew); geomNew.SetData(newdata); int newblock = file.AddBlock(geomNew); blockAtIndex = file.GetBlockAtIndex(newblock); //Console.WriteLine("New block " + newdata + " = " + newblock); } } } ShapeDesc shapeDesc = this.TransformShape(quad, stat, file, (NiTriBasedGeom)blockAtIndex, parentTransform1, parentScale1); if (shapeDesc != null && shapeDesc.shape != null) { list.Add(shapeDesc); } } } } /* if (useOptimizer) { List<ShapeDesc> list2 = new List<ShapeDesc>(); for (int shapeIndex = 0; shapeIndex < list.Count; shapeIndex++) { ShapeDesc shapeDesc = list[shapeIndex]; NiTriShapeData data = shapeDesc.data; List<Triangle> triangles = data.GetTriangles(); if (data.HasVertexColors() && triangles.Count != 0) { NiTriShapeData data1 = new NiTriShapeData(); NiTriShapeData data2 = new NiTriShapeData(); List<Color4> vertexcolors = data.GetVertexColors(); bool vertexcolors_white = true; bool vertexcolors_colors = true; if (vertexcolors_white && vertexcolors_colors) { Dictionary<ushort, ushort>[] dictionary = new Dictionary<ushort, ushort>[] { new Dictionary<ushort, ushort>(), new Dictionary<ushort, ushort>() }; List<Vector3> vertices = data.GetVertices(); List<UVCoord> uvcoords = data.GetUVCoords(); List<Vector3> normals = data.GetNormals(); List<Vector3> tangents = data.GetTangents(); List<Vector3> bitangents = data.GetBitangents(); List<Triangle>[] triangles1 = new List<Triangle>[] { new List<Triangle>(), new List<Triangle>() }; List<Vector3>[] vertices1 = new List<Vector3>[] { new List<Vector3>(), new List<Vector3>() }; List<UVCoord>[] uvcoords1 = new List<UVCoord>[] { new List<UVCoord>(), new List<UVCoord>() }; List<Color4>[] vertexcolors1 = new List<Color4>[] { new List<Color4>(), new List<Color4>() }; List<Vector3>[] normals1 = new List<Vector3>[] { new List<Vector3>(), new List<Vector3>() }; List<Vector3>[] tangents1 = new List<Vector3>[] { new List<Vector3>(), new List<Vector3>() }; List<Vector3>[] bitangents1 = new List<Vector3>[] { new List<Vector3>(), new List<Vector3>() }; UInt16[] index2 = new UInt16[] { 0, 0 }; for (int index = 0; index < triangles.Count; ++index) { ushort indexA = triangles[index][0]; ushort indexB = triangles[index][1]; ushort indexC = triangles[index][2]; float colorA = vertexcolors[indexA][0] + vertexcolors[indexA][1] + vertexcolors[indexA][2]; float colorB = vertexcolors[indexB][0] + vertexcolors[indexB][1] + vertexcolors[indexB][2]; float colorC = vertexcolors[indexC][0] + vertexcolors[indexC][1] + vertexcolors[indexC][2]; int shapeSplit = new int(); if (colorA > 2.6f && colorB > 2.6f && colorC > 2.6f) { shapeSplit = 0; } else { shapeSplit = 1; } if (!dictionary[shapeSplit].ContainsKey(indexA)) { dictionary[shapeSplit].Add(indexA, index2[shapeSplit]); vertices1[shapeSplit].Add(vertices[indexA]); if (uvcoords.Count != 0) { uvcoords1[shapeSplit].Add(uvcoords[indexA]); } if (shapeSplit == 1 && vertexcolors.Count != 0) { vertexcolors1[shapeSplit].Add(vertexcolors[indexA]); } if (normals.Count != 0) { normals1[shapeSplit].Add(normals[indexA]); } if (tangents.Count != 0) { tangents1[shapeSplit].Add(tangents[indexA]); } if (bitangents.Count != 0) { bitangents1[shapeSplit].Add(bitangents[indexA]); } indexA = index2[shapeSplit]; ++index2[shapeSplit]; } else { indexA = dictionary[shapeSplit][indexA]; } if (!dictionary[shapeSplit].ContainsKey(indexB)) { dictionary[shapeSplit].Add(indexB, index2[shapeSplit]); vertices1[shapeSplit].Add(vertices[indexB]); if (uvcoords.Count != 0) { uvcoords1[shapeSplit].Add(uvcoords[indexB]); } if (shapeSplit == 1 && vertexcolors.Count != 0) { vertexcolors1[shapeSplit].Add(vertexcolors[indexB]); } if (normals.Count != 0) { normals1[shapeSplit].Add(normals[indexB]); } if (tangents.Count != 0) { tangents1[shapeSplit].Add(tangents[indexB]); } if (bitangents.Count != 0) { bitangents1[shapeSplit].Add(bitangents[indexB]); } indexB = index2[shapeSplit]; ++index2[shapeSplit]; } else { indexB = dictionary[shapeSplit][indexB]; } if (!dictionary[shapeSplit].ContainsKey(indexC)) { dictionary[shapeSplit].Add(indexC, index2[shapeSplit]); vertices1[shapeSplit].Add(vertices[indexC]); if (uvcoords.Count != 0) { uvcoords1[shapeSplit].Add(uvcoords[indexC]); } if (shapeSplit == 1 && vertexcolors.Count != 0) { vertexcolors1[shapeSplit].Add(vertexcolors[indexC]); } if (normals.Count != 0) { normals1[shapeSplit].Add(normals[indexC]); } if (tangents.Count != 0) { tangents1[shapeSplit].Add(tangents[indexC]); } if (bitangents.Count != 0) { bitangents1[shapeSplit].Add(bitangents[indexC]); } indexC = index2[shapeSplit]; ++index2[shapeSplit]; } else { indexC = dictionary[shapeSplit][indexC]; } triangles1[shapeSplit].Add(new Triangle(indexA, indexB, indexC)); } if (triangles1[0].Count != 0) { ShapeDesc shapeDesc1 = new ShapeDesc(); shapeDesc1.shape = shapeDesc.shape; shapeDesc1.material = shapeDesc.material; shapeDesc1.textures = shapeDesc.textures; shapeDesc1.isHighDetail = shapeDesc.isHighDetail; shapeDesc1.hasVertexColor = false; shapeDesc1.isDoubleSided = shapeDesc.isDoubleSided; shapeDesc1.TextureClampMode = shapeDesc.TextureClampMode; shapeDesc1.boundingBox = shapeDesc.boundingBox; shapeDesc1.x = shapeDesc.x; shapeDesc1.y = shapeDesc.y; shapeDesc1.segments = shapeDesc.segments; data1.SetNumVertices((ushort)vertices1[0].Count); data1.SetHasVertices(true); data1.SetNumUVSets(4097); data1.SetHasNormals(true); data1.SetCenter(data.GetCenter()); data1.SetRadius(data.GetRadius()); data1.SetConsistencyFlags(data.GetConsistencyFlags()); data1.SetNumTriangles((ushort)triangles1[0].Count); data1.SetNumTrianglePoints((uint)triangles1[0].Count * 3); data1.SetHasTriangles(true); data1.SetHasVertexColors(false); data1.SetVertices(vertices1[0]); data1.SetNormals(normals1[0]); data1.SetTangents(tangents1[0]); data1.SetBitangents(bitangents1[0]); data1.SetUVCoords(uvcoords1[0]); //data1.SetVertexColors(vertexcolors1[0]); data1.SetTriangles(triangles1[0]); shapeDesc1.data = data1; list2.Add(shapeDesc1); } if (triangles1[1].Count != 0) { ShapeDesc shapeDesc2 = new ShapeDesc(); shapeDesc2.shape = shapeDesc.shape; shapeDesc2.material = shapeDesc.material; shapeDesc2.textures = shapeDesc.textures; shapeDesc2.isHighDetail = shapeDesc.isHighDetail; shapeDesc2.hasVertexColor = true; shapeDesc2.isDoubleSided = shapeDesc.isDoubleSided; shapeDesc2.TextureClampMode = shapeDesc.TextureClampMode; shapeDesc2.boundingBox = shapeDesc.boundingBox; shapeDesc2.x = shapeDesc.x; shapeDesc2.y = shapeDesc.y; shapeDesc2.segments = shapeDesc.segments; data2.SetNumVertices((ushort)vertices1[0].Count); data2.SetHasVertices(true); data2.SetNumUVSets(4097); data2.SetHasNormals(true); data2.SetCenter(data.GetCenter()); data2.SetRadius(data.GetRadius()); data2.SetConsistencyFlags(data.GetConsistencyFlags()); data2.SetNumTriangles((ushort)triangles1[0].Count); data2.SetNumTrianglePoints((uint)triangles1[0].Count * 3); data2.SetHasTriangles(true); data2.SetHasVertexColors(true); data2.SetVertices(vertices1[1]); data2.SetNormals(normals1[1]); data2.SetTangents(tangents1[1]); data2.SetBitangents(bitangents1[1]); data2.SetUVCoords(uvcoords1[1]); data2.SetVertexColors(vertexcolors1[1]); data2.SetTriangles(triangles1[1]); shapeDesc2.data = data2; list2.Add(shapeDesc2); } } else { list2.Add(shapeDesc); } } else { list2.Add(shapeDesc); } } return list2; }*/ return list; }
private void RemoveUnseenFaces(QuadDesc quad, NiTriShapeData data, ShapeDesc shape) { List<Triangle> triangles = data.GetTriangles(); List<Vector3> vertices = data.GetVertices(); int count = triangles.Count; quad.outValues.totalTriCount += count; int loops = 0; if (this.removeUnderwaterFaces) { loops = 1; } for (int loop = 0; loop <= loops; loop++) { for (int index = 0; index < triangles.Count; ++index) { QuadDesc quadCurrent = new QuadDesc(); List<Triangle> trianglesCompare = new List<Triangle>(); List<Vector3> verticesCompare = new List<Vector3>(); bool[] vertexBelow = new bool[3]; for (int index1 = 0; index1 < 3; index1++) { Vector3 vertex = vertices[triangles[index][index1]]; float x = vertex[0]; float y = vertex[1]; int vertexQuadx = quad.x + cellquad(x * quadLevel, southWestX); int vertexQuady = quad.y + cellquad(y * quadLevel, southWestY); if (quad.x != vertexQuadx || quad.y != vertexQuady) { for (int index3 = 0; index3 < this.quadList.Count; ++index3) { if (vertexQuadx == this.quadList[index3].x && vertexQuady == this.quadList[index3].y) { quadCurrent = this.quadList[index3]; x -= (vertexQuadx - quad.x) / quadLevel * 4096; y -= (vertexQuady - quad.y) / quadLevel * 4096; break; } } } else { quadCurrent = quad; } if (!quadCurrent.hasTerrainVertices) { continue; } Vector3 vertex1 = new Vector3(x, y, vertex[2]); List<Triangle> trianglesTerrain = new List<Triangle>(); List<Vector3> verticesTerrain = new List<Vector3>(); if (this.removeUnderwaterFaces && loop == 0) { if (quadCurrent.waterQuadTree != null) { trianglesTerrain = quadCurrent.waterQuadTree.entirequad.triangles; verticesTerrain = quadCurrent.waterQuadTree.vertices; } } else { trianglesTerrain = quadCurrent.terrainQuadTree.GetSegment(vertex1, quadLevel); verticesTerrain = quadCurrent.terrainQuadTree.vertices; } if (trianglesTerrain == null) { vertexBelow[index1] = true; } else { if (trianglesTerrain.Count != 0) { float num1 = float.MaxValue; num1 = GetTriangleHeight(verticesTerrain, trianglesTerrain, vertex1); if (vertex1[2] < num1) { vertexBelow[index1] = true; } } } } if (vertexBelow[0] && vertexBelow[1] && vertexBelow[2]) { triangles.RemoveAt(index); --index; } } } // remove elements from other lists too if (triangles.Count != 0 && triangles.Count != count) { Dictionary<ushort, ushort> dictionary = new Dictionary<ushort, ushort>(); List<Vector3> vertices2 = new List<Vector3>(); List<UVCoord> uvcoords = data.GetUVCoords(); List<UVCoord> uvcoords2 = new List<UVCoord>(); List<Color4> vertexcolors = data.GetVertexColors(); List<Color4> vertexcolors2 = new List<Color4>(); List<Vector3> normals = data.GetNormals(); List<Vector3> normals2 = new List<Vector3>(); List<Vector3> tangents = data.GetTangents(); List<Vector3> tangents2 = new List<Vector3>(); List<Vector3> bitangents = data.GetBitangents(); List<Vector3> bitangents2 = new List<Vector3>(); ushort index2 = 0; bool vertexcolors_allwhite = true; for (int index = 0; index < triangles.Count; ++index) { for (int index3 = 0; index3 < 3; ++index3) { ushort v1 = triangles[index][index3]; if (!dictionary.ContainsKey(v1)) { dictionary.Add(v1, index2); ++index2; if (vertices.Count != 0) { vertices2.Add(vertices[v1]); } if (uvcoords.Count != 0) { uvcoords2.Add(uvcoords[v1]); } if (vertexcolors.Count != 0) { float r = vertexcolors[v1][0]; float g = vertexcolors[v1][1]; float b = vertexcolors[v1][2]; if (r != 1f || b != 1f || g != 1f) { vertexcolors_allwhite = false; } vertexcolors2.Add(vertexcolors[v1]); } if (normals.Count != 0) { normals2.Add(normals[v1]); } if (tangents.Count != 0) { tangents2.Add(tangents[v1]); } if (bitangents.Count != 0) { bitangents2.Add(bitangents[v1]); } } } } // update indexes of triangles for (int index = 0; index < triangles.Count; ++index) { for (int index3 = 0; index3 < 3; ++index3) { ushort key = triangles[index][index3]; if (!dictionary.ContainsKey(key)) { this.logFile.WriteLog("no index for " + key); } ushort v1 = dictionary[key]; Triangle triangle; (triangle = triangles[index])[index3] = (v1); } } if (vertices2.Count != 0) { data.SetVertices(vertices2); } if (uvcoords2.Count != 0) { data.SetUVCoords(uvcoords2); } if (vertexcolors2.Count != 0) { if (vertexcolors_allwhite) { data.SetHasVertexColors(false); shape.hasVertexColor = false; } else { data.SetHasVertexColors(true); shape.hasVertexColor = true; data.SetVertexColors(vertexcolors2); } } if (normals2.Count != 0) { data.SetNormals(normals2); } if (tangents2.Count != 0) { data.SetTangents(tangents2); } if (bitangents2.Count != 0) { data.SetBitangents(bitangents2); } } quad.outValues.reducedTriCount += triangles.Count; data.SetTriangles(triangles); }