private static WriteModelToCN6Response WriteModelToCN6(IGrannyFile grannyFile, bool isBatch, IGrannyModel model, string filterMeshName) { List <string> textureMaps = new List <string>(); string fileExtension = ".cn6"; string outputFilename = ""; string numberFormat = "f8"; List <string> decalMeshNames = new List <string>(); IGrannySkeleton skeleton = model.Skeleton; string decalMeshName = ""; if (filterMeshName != null) { decalMeshName = "_DCL_" + GetSafeFilename(filterMeshName); } if (grannyFile.Models.Count > 1) { string modelFilename = "__" + model.Name + decalMeshName + fileExtension; outputFilename = grannyFile.Filename.Replace(".gr2", modelFilename); outputFilename = outputFilename.Replace(".GR2", modelFilename); } else { outputFilename = grannyFile.Filename.Replace(".gr2", fileExtension); outputFilename = outputFilename.Replace(".GR2", fileExtension); } if (isBatch) { outputFilename = outputFilename.Replace(fileExtension, "_batch" + fileExtension); } string directory = Path.GetDirectoryName(outputFilename); string filename = Path.GetFileName(outputFilename); outputFilename = directory + "\\" + GetSafeFilename(filename); StreamWriter outputWriter = new StreamWriter(new FileStream(outputFilename, FileMode.Create)); // Lookup so we can identify the meshes belonging the current model in the list of file meshes Dictionary <int, int> meshBindingToMesh = new Dictionary <int, int>(); HashSet <string> distinctMeshNames = new HashSet <string>(); for (int i = 0; i < model.MeshBindings.Count; i++) { for (int j = 0; j < grannyFile.Meshes.Count; j++) { GrannyMeshWrapper modelMesh = new GrannyMeshWrapper(model.MeshBindings[i]); IGrannyMesh fileMesh = grannyFile.Meshes[j]; if (modelMesh.meshEqual(fileMesh)) { meshBindingToMesh.Add(i, j); } } distinctMeshNames.Add(model.MeshBindings[i].Name); } // Used to give meshes distinct names where we have multiple meshes with the same name in our source gr2 Dictionary <string, int> meshNameCount = new Dictionary <string, int>(); foreach (string meshName in distinctMeshNames) { meshNameCount.Add(meshName, 0); } List <GrannyMeshInfo> grannyMeshInfos = new List <GrannyMeshInfo>(); for (int i = 0; i < model.MeshBindings.Count; i++) { GrannyMeshWrapper meshWrapper = new GrannyMeshWrapper(model.MeshBindings[i]); grannyMeshInfos.Add(meshWrapper.getMeshInfo()); } BiLookup <int, string> boneLookup = new BiLookup <int, string>(); for (int i = 0; i < skeleton.Bones.Count; i++) { boneLookup.Add(i, skeleton.Bones[i].Name); } Dictionary <string, double[]> boneNameToPositionMap = new Dictionary <string, double[]>(); foreach (IGrannyBone bone in skeleton.Bones) { if (!boneNameToPositionMap.ContainsKey(bone.Name)) { double[] bonePosition = NB2Exporter.getBoneWorldPosition(bone); boneNameToPositionMap.Add(bone.Name, bonePosition); } } string headerLine = "// CivNexus6 CN6 - Exported from Nexus Buddy " + NexusBuddyApplicationForm.getVersionString(); outputWriter.WriteLine(headerLine); outputWriter.WriteLine("skeleton"); // Write Bones for (int boneIndex = 0; boneIndex < skeleton.Bones.Count; boneIndex++) { IGrannyBone bone = skeleton.Bones[boneIndex]; string boneName = bone.Name; IGrannyTransform transform = bone.LocalTransform; float[] orientation = transform.Orientation; float[] position = transform.Position; float[] invWorldTransform = bone.InverseWorldTransform; StringBuilder boneStringBuilder = new StringBuilder(boneIndex + " \"" + boneName + "\" " + bone.ParentIndex + " " + position[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + position[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + position[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[3].ToString(numberFormat, CultureInfo.InvariantCulture)); foreach (float j in invWorldTransform) { boneStringBuilder.Append(" " + j.ToString(numberFormat, CultureInfo.InvariantCulture)); } outputWriter.WriteLine(boneStringBuilder); } List <IndieMaterial> modelMaterials = new List <IndieMaterial>(); foreach (IGrannyMesh mesh in model.MeshBindings) { IGrannyMaterial material = mesh.MaterialBindings[0]; foreach (ListViewItem materialListItem in NexusBuddyApplicationForm.form.materialList.Items) { IndieMaterial shader = (IndieMaterial)materialListItem.Tag; GrannyMaterialWrapper matWrap1 = new GrannyMaterialWrapper(shader.GetMaterial()); GrannyMaterialWrapper matWrap2 = new GrannyMaterialWrapper(material); if (matWrap1.getName().Equals(matWrap2.getName()) && !modelMaterials.Contains(shader)) { modelMaterials.Add(shader); } } } int meshCount = 0; for (int mi = 0; mi < grannyMeshInfos.Count; mi++) { IGrannyMesh mesh = model.MeshBindings[mi]; string meshName = model.MeshBindings[mi].Name; GrannyMeshWrapper meshWrapper = new GrannyMeshWrapper(mesh); GrannyMeshInfo meshInfo = meshWrapper.getMeshInfo(); bool isFlatMesh = true; foreach (GrannyVertexInfo vertexInfo in meshInfo.vertices) { float zPos = vertexInfo.position[2]; bool isZero = NumberUtils.almostEquals(zPos, 0.0f, 4); if (!isZero) { isFlatMesh = false; break; } } if (filterMeshName == null) { if (isFlatMesh) { decalMeshNames.Add(meshName); } else { meshCount++; } } else { meshCount = 1; } } if (meshCount == 0) { outputWriter.Close(); File.Delete(outputFilename); return(new WriteModelToCN6Response(decalMeshNames, textureMaps)); } // Write Meshes outputWriter.WriteLine("meshes:" + meshCount); for (int mi = 0; mi < grannyMeshInfos.Count; mi++) { GrannyMeshInfo grannyMeshInfo = grannyMeshInfos[mi]; string meshName = model.MeshBindings[mi].Name; if ((filterMeshName == null && !decalMeshNames.Contains(meshName)) || meshName.Equals(filterMeshName)) { meshNameCount[meshName]++; if (meshNameCount[meshName] > 1) { meshName += meshNameCount[meshName]; } outputWriter.WriteLine("mesh:\"" + meshName + "\""); // Write Materials outputWriter.WriteLine("materials"); foreach (IGrannyMaterial material in model.MeshBindings[mi].MaterialBindings) { IndieMaterial shader = NexusBuddyApplicationForm.GetIndieMaterialFromMaterial(material); string baseMap; if (shader.GetType() == typeof(IndieLeaderGlassShader)) { baseMap = "Leader_cornea"; } else if (shader.GetType() == typeof(IndieBuildingShader)) { baseMap = shader.Diffuse; } else if (shader.GetType().Name.StartsWith("IndieLeaderFur")) { baseMap = shader.Fur_BaseMap; } else if (shader.GetType().Name.StartsWith("IndieLeader")) { baseMap = shader.DiffuseMap; } else if (shader.GetType() == typeof(IndieLandmarkStencilShader)) { baseMap = shader.BaseTextureMap; } else { baseMap = shader.BaseTextureMap; } if (!String.IsNullOrEmpty(baseMap)) { outputWriter.WriteLine("\"" + baseMap + "\""); textureMaps.Add(baseMap); } else { outputWriter.WriteLine("\"" + material.Name + "\""); } } // Write Vertices outputWriter.WriteLine("vertices"); for (int vi = 0; vi < grannyMeshInfo.vertices.Count; vi++) { GrannyVertexInfo vertex = grannyMeshInfo.vertices[vi]; string[] boneNames = new string[8]; float[] boneWeights = new float[8]; int[] boneIds = new int[8]; for (int z = 0; z < 8; z++) { if (z > 3) { //boneNames[z] = grannyMeshInfo.boneBindings[vertex.boneIndices[z]]; boneWeights[z] = 0f; boneIds[z] = 0; } else { boneNames[z] = grannyMeshInfo.boneBindings[vertex.boneIndices[z]]; boneWeights[z] = (float)vertex.boneWeights[z] / 255; boneIds[z] = NB2Exporter.getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneNames[z], boneWeights[z], vertex.position); } } float[] tangents = new float[3]; if (vertex.tangent == null) { tangents[0] = vertex.normal[0]; tangents[1] = vertex.normal[1]; tangents[2] = vertex.normal[2]; } else { tangents[0] = vertex.tangent[0]; tangents[1] = vertex.tangent[1]; tangents[2] = vertex.tangent[2]; } float[] binormals = new float[3]; if (vertex.binormal == null) { binormals[0] = vertex.normal[0]; binormals[1] = vertex.normal[1]; binormals[2] = vertex.normal[2]; } else { binormals[0] = vertex.binormal[0]; binormals[1] = vertex.binormal[1]; binormals[2] = vertex.binormal[2]; } outputWriter.WriteLine(vertex.position[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.position[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.position[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.normal[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.normal[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.normal[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + tangents[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + tangents[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + tangents[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + binormals[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + binormals[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + binormals[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.uv[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.uv[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + 0.00000000f.ToString(numberFormat, CultureInfo.InvariantCulture) + " " + 0.00000000f.ToString(numberFormat, CultureInfo.InvariantCulture) + " " + 0.00000000f.ToString(numberFormat, CultureInfo.InvariantCulture) + " " + 0.00000000f.ToString(numberFormat, CultureInfo.InvariantCulture) + " " + boneIds[0] + " " + boneIds[1] + " " + boneIds[2] + " " + boneIds[3] + " 0 0 0 0 " + vertex.boneWeights[0] + " " + vertex.boneWeights[1] + " " + vertex.boneWeights[2] + " " + vertex.boneWeights[3] + " 0 0 0 0 " ); } // Write Triangles outputWriter.WriteLine("triangles"); for (int ti = 0; ti < grannyMeshInfo.triangles.Count; ti++) { int[] triangle = grannyMeshInfo.triangles[ti]; outputWriter.WriteLine(triangle[0] + " " + triangle[1] + " " + triangle[2] + " 0"); } } } outputWriter.WriteLine("end"); outputWriter.Close(); WriteModelToCN6Response response = new WriteModelToCN6Response(decalMeshNames, textureMaps); return(response); }
public static void exportNB2Model(IGrannyFile grannyFile, int modelId) { string fileExtension = ".nb2"; string outputFilename = ""; string numberFormat = "f6"; if (grannyFile.Models.Count > 1) { string modelFilename = "__" + grannyFile.Models[modelId].Name + fileExtension; outputFilename = grannyFile.Filename.Replace(".gr2", modelFilename); outputFilename = outputFilename.Replace(".GR2", modelFilename); } else { outputFilename = grannyFile.Filename.Replace(".gr2", fileExtension); outputFilename = outputFilename.Replace(".GR2", fileExtension); } StreamWriter outputWriter = new StreamWriter(new FileStream(outputFilename.ToLower(), FileMode.Create)); IGrannyModel model = grannyFile.Models[modelId]; IGrannySkeleton skeleton = model.Skeleton; // Lookup so we can identify the meshes belonging the current model in the list of file meshes Dictionary <int, int> meshBindingToMesh = new Dictionary <int, int>(); HashSet <string> distinctMeshNames = new HashSet <string>(); for (int i = 0; i < model.MeshBindings.Count; i++) { for (int j = 0; j < grannyFile.Meshes.Count; j++) { GrannyMeshWrapper modelMesh = new GrannyMeshWrapper(model.MeshBindings[i]); IGrannyMesh fileMesh = grannyFile.Meshes[j]; if (modelMesh.meshEqual(fileMesh)) { meshBindingToMesh.Add(i, j); } } distinctMeshNames.Add(model.MeshBindings[i].Name); } // Used to give meshes distinct names where we have multiple meshes with the same name in our source gr2 Dictionary <string, int> meshNameCount = new Dictionary <string, int>(); foreach (string meshName in distinctMeshNames) { meshNameCount.Add(meshName, 0); } List <GrannyMeshInfo> grannyMeshInfos = new List <GrannyMeshInfo>(); for (int i = 0; i < model.MeshBindings.Count; i++) { GrannyMeshWrapper meshWrapper = new GrannyMeshWrapper(model.MeshBindings[i]); grannyMeshInfos.Add(meshWrapper.getMeshInfo()); } BiLookup <int, string> boneLookup = new BiLookup <int, string>(); for (int i = 0; i < skeleton.Bones.Count; i++) { boneLookup.Add(i, skeleton.Bones[i].Name); } Dictionary <string, double[]> boneNameToPositionMap = new Dictionary <string, double[]>(); double[] bonePosition; foreach (IGrannyBone bone in skeleton.Bones) { try { bonePosition = getBoneWorldPosition(bone); boneNameToPositionMap.Add(bone.Name, bonePosition); } catch (ArgumentException) { } } outputWriter.WriteLine("// Nexus Buddy NB2 - Exported from Nexus Buddy 2"); outputWriter.WriteLine("Frames: 30"); outputWriter.WriteLine("Frame: 1"); List <IndieMaterial> modelMaterials = new List <IndieMaterial>(); foreach (IGrannyMesh mesh in model.MeshBindings) { IGrannyMaterial material = mesh.MaterialBindings[0]; foreach (ListViewItem materialListItem in NexusBuddyApplicationForm.form.materialList.Items) { IndieMaterial shader = (IndieMaterial)materialListItem.Tag; GrannyMaterialWrapper matWrap1 = new GrannyMaterialWrapper(shader.GetMaterial()); GrannyMaterialWrapper matWrap2 = new GrannyMaterialWrapper(material); if (matWrap1.getName().Equals(matWrap2.getName()) && !modelMaterials.Contains(shader)) { modelMaterials.Add(shader); } } } // Write Meshes outputWriter.WriteLine("Meshes: " + model.MeshBindings.Count); for (int mi = 0; mi < grannyMeshInfos.Count; mi++) { GrannyMeshInfo grannyMeshInfo = grannyMeshInfos[mi]; string meshName = model.MeshBindings[mi].Name; meshNameCount[meshName]++; if (meshNameCount[meshName] > 1) { meshName += meshNameCount[meshName]; } var materialBindingName = model.MeshBindings[mi].MaterialBindings[0].Name; var materialIndex = 0; foreach (IndieMaterial material in modelMaterials) { if (materialBindingName.Equals(material.GetMaterial().Name)) { break; } materialIndex++; } outputWriter.WriteLine("\"" + meshName + "\" 0 " + materialIndex); // Write Vertices outputWriter.WriteLine(grannyMeshInfo.vertices.Count); for (int vi = 0; vi < grannyMeshInfo.vertices.Count; vi++) { GrannyVertexInfo vertex = grannyMeshInfo.vertices[vi]; string boneName0 = grannyMeshInfo.boneBindings[vertex.boneIndices[0]]; float boneWeight0 = (float)vertex.boneWeights[0] / 255; int boneId0 = getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName0, boneWeight0, vertex.position); string boneName1 = grannyMeshInfo.boneBindings[vertex.boneIndices[1]]; float boneWeight1 = (float)vertex.boneWeights[1] / 255; int boneId1 = getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName1, boneWeight1, vertex.position); string boneName2 = grannyMeshInfo.boneBindings[vertex.boneIndices[2]]; float boneWeight2 = (float)vertex.boneWeights[2] / 255; int boneId2 = getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName2, boneWeight2, vertex.position); string boneName3 = grannyMeshInfo.boneBindings[vertex.boneIndices[3]]; float boneWeight3 = (float)vertex.boneWeights[3] / 255; int boneId3 = getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName3, boneWeight3, vertex.position); outputWriter.WriteLine("0 " + vertex.position[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.position[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.position[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.uv[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.uv[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + boneId0 + " " + boneWeight0.ToString(numberFormat, CultureInfo.InvariantCulture) + " " + boneId1 + " " + boneWeight1.ToString(numberFormat, CultureInfo.InvariantCulture) + " " + boneId2 + " " + boneWeight2.ToString(numberFormat, CultureInfo.InvariantCulture) + " " + boneId3 + " " + boneWeight3.ToString(numberFormat, CultureInfo.InvariantCulture) ); } // Write Normals outputWriter.WriteLine(grannyMeshInfo.vertices.Count); for (int ni = 0; ni < grannyMeshInfo.vertices.Count; ni++) { GrannyVertexInfo vertex = grannyMeshInfo.vertices[ni]; outputWriter.WriteLine(vertex.normal[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.normal[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.normal[2].ToString(numberFormat, CultureInfo.InvariantCulture)); } // Write Triangles outputWriter.WriteLine(grannyMeshInfo.triangles.Count); for (int ti = 0; ti < grannyMeshInfo.triangles.Count; ti++) { int[] triangle = grannyMeshInfo.triangles[ti]; outputWriter.WriteLine("0 " + triangle[0] + " " + triangle[1] + " " + triangle[2] + " " + triangle[0] + " " + triangle[1] + " " + triangle[2] + " 1"); } } // Write Materials outputWriter.WriteLine("Materials: " + modelMaterials.Count); for (int i = 0; i < modelMaterials.Count; i++) { outputWriter.WriteLine("\"" + modelMaterials[i].GetMaterial().Name + "\""); outputWriter.WriteLine("0.200000 0.200000 0.200000 1.000000"); outputWriter.WriteLine("0.800000 0.800000 0.800000 1.000000"); outputWriter.WriteLine("0.000000 0.000000 0.000000 1.000000"); outputWriter.WriteLine("0.000000 0.000000 0.000000 1.000000"); outputWriter.WriteLine("0.000000"); outputWriter.WriteLine("1.000000"); string map1 = "ColorMap_" + i; string map2 = "AlphaMap_" + i; string baseMap; string srefmap; IndieMaterial shader = modelMaterials[i]; if (shader.GetType() == typeof(IndieBuildingShader)) { baseMap = shader.Diffuse; srefmap = shader.BuildingSREF; } else if (shader.GetType() == typeof(IndieLandmarkStencilShader)) { baseMap = shader.BaseTextureMap; srefmap = shader.SpecTextureMap; } else { baseMap = shader.BaseTextureMap; srefmap = shader.SREFMap; } if (!String.IsNullOrEmpty(baseMap)) { map1 = baseMap; } if (!String.IsNullOrEmpty(srefmap)) { map2 = srefmap; } outputWriter.WriteLine("\"" + map1 + "\""); outputWriter.WriteLine("\"" + map2 + "\""); } // Write Bones outputWriter.WriteLine("Bones: " + skeleton.Bones.Count); for (int bi = 0; bi < skeleton.Bones.Count; bi++) { IGrannyBone bone = skeleton.Bones[bi]; string boneName = bone.Name; outputWriter.WriteLine("\"" + boneName + "\""); if (bone.ParentIndex == -1) { outputWriter.WriteLine("\"\""); } else { string parentBoneName = skeleton.Bones[bone.ParentIndex].Name; outputWriter.WriteLine("\"" + parentBoneName + "\""); } IGrannyTransform transform = bone.LocalTransform; float[] orientation = transform.Orientation; float[] position = transform.Position; //Matrix3D boneWorldMatrix = getBoneWorldMatrix(bone); //ETransformFlags transformFlags = transform.Flags; //bool hasPosition = transformFlags.HasFlag(ETransformFlags.GrannyHasPosition); //bool hasOrientation = transformFlags.HasFlag(ETransformFlags.GrannyHasOrientation); // bone: flags, posx, posy, posz, quatx, quaty, quatz, quatw outputWriter.WriteLine("0 " + position[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + position[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + position[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[2].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + orientation[3].ToString(numberFormat, CultureInfo.InvariantCulture)); // number of position keys outputWriter.WriteLine("0"); // number of rotation keys outputWriter.WriteLine("0"); } outputWriter.Close(); }