Example #1
0
        public unsafe static void importBR2(string sourceFilename, string outputFilename, GrannyContext grannyContext)
        {
            IGrannyFile file = CivNexusSixApplicationForm.form.OpenFileAsTempFileCopy(CivNexusSixApplicationForm.form.modelTemplateFilename, "tempimport");

            GrannyFileWrapper fileWrapper = new GrannyFileWrapper(file);

            fileWrapper.setNumMeshes(0);
            fileWrapper.setNumVertexDatas(0);
            fileWrapper.setNumSkeletons(0);
            fileWrapper.setNumTriTopologies(0);

            GrannyModelInfo modelInfo = loadModelInfo(sourceFilename);

            doBoneBindings(modelInfo);

            List <IGrannyFile> meshFileList = new List <IGrannyFile>();

            foreach (GrannyMeshInfo meshInfo in modelInfo.meshBindings)
            {
                meshFileList.Add(writeMesh(meshInfo));
            }

            IGrannyModel       model        = file.Models[0];
            GrannyModelWrapper modelWrapper = new GrannyModelWrapper(model);

            modelWrapper.setNumMeshBindings(0);
            model.MeshBindings.Clear();

            foreach (IGrannyFile meshFile in meshFileList)
            {
                doAppendMeshBinding(file, meshFile, 0);
            }

            fileWrapper.setNumMeshes(0);
            file.Meshes.Clear();

            foreach (IGrannyMesh mesh in file.Models[0].MeshBindings)
            {
                file.AddMeshReference(mesh);
            }

            GrannySkeletonWrapper skeletonWrapper = new GrannySkeletonWrapper(file.Models[0].Skeleton);

            skeletonWrapper.writeSkeletonInfo(modelInfo.skeleton);

            string worldBoneName = modelInfo.skeleton.bones[0].name;

            modelWrapper.setName(worldBoneName);
            skeletonWrapper.setName(worldBoneName);

            fileWrapper.setFromArtToolInfo("Blender", 2, 0);
            float[] matrix = { 1f, 0f, 0f, 0f, 0f, 1f, 0f, -1f, 0f };
            fileWrapper.setMatrix(matrix);
            CivNexusSixApplicationForm.SetExporterInfo(fileWrapper);
            fileWrapper.setFromFileName(sourceFilename);

            fileWrapper.addSkeletonPointer((int)skeletonWrapper.m_pkSkeleton);

            CivNexusSixApplicationForm.form.SaveAsAction(file, outputFilename, false);
        }
 public static void exportAllModelsToNB2(IGrannyFile grannyFile)
 {
     for (int i = 0; i < grannyFile.Models.Count; i++)
     {
         exportNB2Model(grannyFile, i);
     }
 }
Example #3
0
        public unsafe static IGrannyFile writeMesh(GrannyMeshInfo meshInfo)
        {
            bool useLeaderTemplate = NexusBuddyApplicationForm.form.useLeaderTemplate();
            bool useSceneTemplate  = NexusBuddyApplicationForm.form.useSceneTemplate();

            string templateFilename;

            if (useLeaderTemplate)
            {
                templateFilename = NexusBuddyApplicationForm.form.leaderTemplateFilename;
            }
            else if (useSceneTemplate)
            {
                templateFilename = NexusBuddyApplicationForm.form.sceneTemplateFilename;
            }
            else
            {
                templateFilename = NexusBuddyApplicationForm.form.modelTemplateFilename;
            }

            IGrannyFile appendFile = NexusBuddyApplicationForm.form.openFileAsTempFileCopy(templateFilename, "tempappend");

            appendFile.Meshes.RemoveRange(1, appendFile.Meshes.Count - 1);
            IGrannyMesh mesh = appendFile.Models[0].MeshBindings[0];

            GrannyMeshWrapper meshWrapper = new GrannyMeshWrapper(mesh);

            meshWrapper.writeMeshInfo(meshInfo, useLeaderTemplate, useSceneTemplate);

            return(appendFile);
        }
Example #4
0
 public static void exportAllModelsToCN6(IGrannyFile grannyFile)
 {
     for (int i = 0; i < grannyFile.Models.Count; i++)
     {
         cn6Export(grannyFile, i);
     }
 }
Example #5
0
        public unsafe static void doAppendMeshBinding(IGrannyFile inputFile, IGrannyFile appendFile, Int32 currentModelIndex)
        {
            // Get wrappers
            IGrannyModel       inputModel        = inputFile.Models[currentModelIndex];
            GrannyModelWrapper inputModelWrapper = new GrannyModelWrapper(inputModel);

            IGrannyModel       appendModel        = appendFile.Models[0];
            GrannyModelWrapper appendModelWrapper = new GrannyModelWrapper(appendModel);

            // Update model
            inputModel.MeshBindings.Add(appendFile.Meshes[0]);

            int meshCountInput       = inputModelWrapper.getNumMeshBindings();
            int newMeshBindingsCount = meshCountInput + 1;

            inputModelWrapper.setNumMeshBindings(newMeshBindingsCount);

            // Update model mesh bindings
            int oldMeshBindingsPtr = *(int *)inputModelWrapper.getMeshBindingsPtr();

            *(int *)inputModelWrapper.getMeshBindingsPtr() = (int)Marshal.AllocHGlobal(newMeshBindingsCount * 8);
            int newMeshBindingsPtr = *(int *)inputModelWrapper.getMeshBindingsPtr();

            int modelMeshBindingsPtrAppend = *(int *)appendModelWrapper.getMeshBindingsPtr();

            if (meshCountInput > 0)
            {
                MemoryUtil.MemCpy((void *)newMeshBindingsPtr, (void *)oldMeshBindingsPtr, (uint)(meshCountInput * 8));
            }
            MemoryUtil.MemCpy((void *)(newMeshBindingsPtr + meshCountInput * 8), (void *)modelMeshBindingsPtrAppend, 8);
        }
Example #6
0
        public static void overwriteMeshes(IGrannyFile file, string sourceFilename, GrannyContext grannyContext, int currentModelIndex, int vertexFormat)
        {
            string filename = file.Filename;

            GrannyModelInfo modelInfo = loadModelInfos(sourceFilename, vertexFormat)[0];

            doBoneBindings(modelInfo);

            GrannyFileWrapper fileWrapper = new GrannyFileWrapper(file);

            List <IGrannyFile> meshFileList = new List <IGrannyFile>();

            foreach (GrannyMeshInfo meshInfo in modelInfo.meshBindings)
            {
                meshFileList.Add(writeMesh(meshInfo, getTemplateFilename(vertexFormat)));
            }

            IGrannyModel       model        = file.Models[currentModelIndex];
            GrannyModelWrapper modelWrapper = new GrannyModelWrapper(model);

            modelWrapper.setNumMeshBindings(0);
            model.MeshBindings.Clear();

            foreach (IGrannyFile meshFile in meshFileList)
            {
                doAppendMeshBinding(file, meshFile, currentModelIndex);
            }

            fileWrapper.setNumMeshes(0);
            fileWrapper.setNumTriTopologies(0);
            fileWrapper.setNumVertexDatas(0);
            file.Meshes.Clear();

            int meshesCount = 0;

            foreach (IGrannyModel loopModel in file.Models)
            {
                foreach (IGrannyMesh mesh in loopModel.MeshBindings)
                {
                    file.AddMeshReference(mesh);
                    meshesCount++;
                }
            }

            fileWrapper.setFromArtToolInfo("Blender", 2, 0);
            //fileWrapper.setUnitsPerMeter(10.7f);
            CivNexusSixApplicationForm.SetExporterInfo(fileWrapper);
            fileWrapper.setFromFileName(sourceFilename);

            fileWrapper.setNumMeshes(meshesCount);
            CivNexusSixApplicationForm.form.SaveAsAction(file, filename, false);

            List <GrannyModelInfo> modelInfos = new List <GrannyModelInfo>();

            modelInfos.Add(modelInfo);

            createAndBindMaterials(filename, file, modelInfos);
        }
Example #7
0
        public GrannyFileWrapper(IGrannyFile inputFile)
        {
            wrappedFile = inputFile;
            Type      myType  = inputFile.GetType();
            FieldInfo fm_info = myType.GetField("m_info", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            Pointer   pm_info = (Pointer)fm_info.GetValue(inputFile);

            m_info = Pointer.Unbox(pm_info);
        }
Example #8
0
        public static List <string> exportAllModelsToCN6(IGrannyFile grannyFile, bool isBatch)
        {
            List <string> fileTextureMaps = new List <string>();

            for (int i = 0; i < grannyFile.Models.Count; i++)
            {
                List <string> textureMaps = cn6Export(grannyFile, i, isBatch);
                fileTextureMaps.AddRange(textureMaps);
            }

            return(fileTextureMaps);
        }
Example #9
0
        public unsafe static void overwriteMeshes(IGrannyFile file, string sourceFilename, GrannyContext grannyContext, Int32 currentModelIndex)
        {
            string filename = file.Filename;

            GrannyModelInfo modelInfo = loadModelInfo(sourceFilename);

            doBoneBindings(modelInfo);

            GrannyFileWrapper fileWrapper = new GrannyFileWrapper(file);

            List <IGrannyFile> meshFileList = new List <IGrannyFile>();

            foreach (GrannyMeshInfo meshInfo in modelInfo.meshBindings)
            {
                meshFileList.Add(writeMesh(meshInfo));
            }

            IGrannyModel       model        = file.Models[currentModelIndex];
            GrannyModelWrapper modelWrapper = new GrannyModelWrapper(model);

            modelWrapper.setNumMeshBindings(0);
            model.MeshBindings.Clear();

            foreach (IGrannyFile meshFile in meshFileList)
            {
                doAppendMeshBinding(grannyContext, file, meshFile, currentModelIndex);
            }

            fileWrapper.setNumMeshes(0);
            fileWrapper.setNumTriTopologies(0);
            fileWrapper.setNumVertexDatas(0);
            file.Meshes.Clear();

            int meshesCount = 0;

            foreach (IGrannyModel loopModel in file.Models)
            {
                foreach (IGrannyMesh mesh in loopModel.MeshBindings)
                {
                    file.AddMeshReference(mesh);
                    meshesCount++;
                }
            }

            fileWrapper.setFromArtToolInfo("Blender", 2, 0);
            fileWrapper.setUnitsPerMeter(10.7f);
            NexusBuddyApplicationForm.setExporterInfo(fileWrapper);
            fileWrapper.setFromFileName(sourceFilename);

            fileWrapper.setNumMeshes(meshesCount);
            NexusBuddyApplicationForm.form.saveAsAction(file, filename, false);
        }
Example #10
0
        public static List <string> cn6Export(IGrannyFile grannyFile, int currentModelIndex, bool isBatch)
        {
            IGrannyModel model = grannyFile.Models[currentModelIndex];

            WriteModelToCN6Response response = WriteModelToCN6(grannyFile, isBatch, model, null);

            foreach (string decalMeshName in response.decalMeshNames)
            {
                WriteModelToCN6(grannyFile, isBatch, model, decalMeshName);
            }

            return(response.textureMaps);
        }
Example #11
0
        public static IGrannyFile writeMesh(GrannyMeshInfo meshInfo, string templateFilename)
        {
            IGrannyFile appendFile = CivNexusSixApplicationForm.form.OpenFileAsTempFileCopy(templateFilename, "tempappend");

            appendFile.Meshes.RemoveRange(1, appendFile.Meshes.Count - 1);
            IGrannyMesh mesh = appendFile.Models[0].MeshBindings[0];

            GrannyMeshWrapper meshWrapper = new GrannyMeshWrapper(mesh);

            meshWrapper.writeMeshInfo(meshInfo, false, false);

            return(appendFile);
        }
Example #12
0
        public static void WriteGeometrySet(IGrannyFile file, string assetClassName)
        {
            string filenameNoExt = Path.GetFileNameWithoutExtension(file.Filename);
            string directory     = Path.GetDirectoryName(file.Filename);
            string fileExtension = "_GeometrySet.xml";
            string geoFilename   = filenameNoExt + fileExtension;

            StreamWriter       outputWriter = new StreamWriter(new FileStream(directory + "\\" + geoFilename, FileMode.Create));
            List <IGrannyFile> files        = new List <IGrannyFile>()
            {
                file
            };

            WriteGeometrySetMetadataToStream(files, outputWriter, null, assetClassName);
            outputWriter.Close();
        }
Example #13
0
        public static void batchExport(GrannyContext grannyContext, string unitListFile)
        {
            StreamReader streamReader = new StreamReader(unitListFile);

            string directory = Path.GetDirectoryName(unitListFile);

            string regexString = "(.+);(.*);(.*);(.*)";

            string       outFilename  = unitListFile.Replace(".dat", "_new.dat");
            StreamWriter outputWriter = new StreamWriter(new FileStream(outFilename, FileMode.Create));

            while (!streamReader.EndOfStream)
            {
                string currentLine = streamReader.ReadLine();

                Regex           regex = new Regex(regexString);
                MatchCollection mc    = regex.Matches(currentLine);
                foreach (Match m in mc)
                {
                    string      gr2Filename = m.Groups[1].Value.Trim().ToLower();
                    IGrannyFile grannyFile  = grannyContext.LoadGrannyFile(directory + "\\" + gr2Filename);
                    NexusBuddyApplicationForm.loadedFile = grannyFile;
                    NexusBuddyApplicationForm.form.refreshAppData();
                    List <string> fileTextureMaps = exportAllModelsToCN6(grannyFile, true);

                    string animationFilenames = m.Groups[2].Value.Trim();
                    string textureFilenames   = m.Groups[3].Value.Trim();
                    string prettyName         = m.Groups[4].Value.Trim();

                    var fileTextureSet = new HashSet <string>(fileTextureMaps);

                    if (String.IsNullOrEmpty(textureFilenames))
                    {
                        textureFilenames = string.Join(",", fileTextureSet);
                    }

                    string newline = gr2Filename + ";" + animationFilenames + ";" + textureFilenames + ";" + prettyName;

                    outputWriter.WriteLine(newline);
                }
            }
            streamReader.Close();
            outputWriter.Close();
            File.Delete(unitListFile);
            File.Move(outFilename, unitListFile);
        }
Example #14
0
        //// todo - update to create new memory areas
        //public unsafe static void doAppendMeshBinding(GrannyContext grannyContext, IGrannyFile inputFile, IGrannyFile appendFile)
        //{
        //    // UNPACK CURRENT MODEL
        //    IGrannyModel inputModel = inputFile.Models[0];
        //    GrannyModelWrapper inputModelWrapper = new GrannyModelWrapper(inputModel);
        //    void* m_pkModel_input = inputModelWrapper.m_pkModel;

        //    // UNPACK APPEND MODEL
        //    IGrannyModel appendModel = appendFile.Models[0];
        //    GrannyModelWrapper appendModelWrapper = new GrannyModelWrapper(appendModel);
        //    void* m_pkModel_app = appendModelWrapper.m_pkModel;

        //    // UNPACK NEW MODEL
        //    IGrannyFile newModelFile = inputFile;
        //    IGrannyModel newModel = newModelFile.Models[0];
        //    GrannyModelWrapper newModelWrapper = new GrannyModelWrapper(newModel);
        //    void* m_pkModel_new = newModelWrapper.m_pkModel;

        //    // UPDATE NEW MODEL
        //    int meshCountInput = *(int*)((IntPtr)m_pkModel_input + 76);

        //    newModel.MeshBindings.Add(appendFile.Meshes[0]);
        //    // update Mesh Count
        //    *(int*)((IntPtr)m_pkModel_new + 76) = meshCountInput + 1;

        //    //update model mesh bindings
        //    int size = meshCountInput;
        //    void* modelMeshBindingsPtrInput = (void*)*(int*)((IntPtr)m_pkModel_input + 80);
        //    MemoryUtil.MemCpy((void*)*(int*)((IntPtr)m_pkModel_new + 80), (void*)modelMeshBindingsPtrInput, (uint)(size * 4));

        //    int writeOffset = meshCountInput;
        //    void* modelMeshBindingsPtrAppend = (void*)*(int*)((IntPtr)m_pkModel_app + 80);
        //    MemoryUtil.MemCpy((void*)(*(int*)((IntPtr)m_pkModel_new + 80) + writeOffset * 4), (void*)modelMeshBindingsPtrAppend, (uint)(1 * 4));

        //    GrannyFileWrapper newModelFileWrapper = new GrannyFileWrapper(newModelFile);
        //    void* m_info = newModelFileWrapper.m_info;
        //    void** grannyMeshPtr = (void**)*(int*)((IntPtr)m_info + 56);

        //    // Add all meshes from input file
        //    *(int*)((IntPtr)m_info + 52) = 0; // Reset Mesh Count to 0
        //    for (int index = 0; index < inputFile.Meshes.Count; index++)
        //    {
        //        IGrannyMesh mesh = inputFile.Meshes[index];
        //        GrannyMeshWrapper meshWrapper = new GrannyMeshWrapper(mesh);
        //        void* m_pkMesh = meshWrapper.m_pkMesh;
        //        MemoryUtil.MemCpy((void*)*(int*)((IntPtr)m_info + 56), (void*)grannyMeshPtr, (uint)(*(int*)((IntPtr)m_info + 52) * 4));
        //        *(int*)(*(int*)((IntPtr)m_info + 56) + *(int*)((IntPtr)m_info + 52) * 4) = (int)m_pkMesh;
        //        *(int*)((IntPtr)m_info + 52) = *(int*)((IntPtr)m_info + 52) + 1;
        //    }

        //    // Add mesh from append file
        //    IGrannyMesh appendMesh = appendFile.Meshes[0];
        //    GrannyMeshWrapper appendMeshWrapper = new GrannyMeshWrapper(appendMesh);
        //    void* m_pkAppendMesh = appendMeshWrapper.m_pkMesh;
        //    MemoryUtil.MemCpy((void*)*(int*)((IntPtr)m_info + 56), (void*)grannyMeshPtr, (uint)(*(int*)((IntPtr)m_info + 52) * 4));
        //    *(int*)(*(int*)((IntPtr)m_info + 56) + *(int*)((IntPtr)m_info + 52) * 4) = (int)m_pkAppendMesh;
        //    *(int*)((IntPtr)m_info + 52) = *(int*)((IntPtr)m_info + 52) + 1;
        //}


        public static IGrannyFile cleardownTemplate(GrannyContext grannyContext)
        {
            //string filename = sourceTemplatePath + "model_template.gr2";

            IGrannyFile file = NexusBuddyApplicationForm.form.openFileAsTempFileCopy(NexusBuddyApplicationForm.form.modelTemplateFilename, "tempimport");

            GrannyFileWrapper fileWrapper = new GrannyFileWrapper(file);

            //GrannyMeshWrapper meshWrapper = new GrannyMeshWrapper(file.Meshes[0]);
            //meshWrapper.setName("BLANK_MESH");
            //meshWrapper.setNumVertices(0);
            //meshWrapper.setNumBoneBindings(0);
            //meshWrapper.setNumIndices(0);
            //meshWrapper.setNumIndices16(0);
            //meshWrapper.setGroup0TriCount(0);

            ////memProbe(meshWrapper.getBoneBindingsPtr());

            //GrannyModelWrapper modelWrapper = new GrannyModelWrapper(file.Models[0]);
            //modelWrapper.setNumMeshBindings(1);
            //modelWrapper.setName("BLANK_MODEL");

            //GrannySkeletonWrapper skeletonWrapper = new GrannySkeletonWrapper(modelWrapper.wrappedModel.Skeleton);
            //skeletonWrapper.setNumBones(0);
            //skeletonWrapper.setName("BLANK_SKELETON");

            fileWrapper.setNumMeshes(0);
            //fileWrapper.setNumModels(0);
            fileWrapper.setNumVertexDatas(0);
            fileWrapper.setNumSkeletons(0);
            fileWrapper.setNumTriTopologies(0);
            fileWrapper.setNumMaterials(0);

            file.Meshes.Clear();

            //fileWrapper.setFromFileName("My lovely lovely filename");
            //fileWrapper.setFromArtToolName("Blender 2.49");
            //fileWrapper.setExporterName("Nexus Buddy 2.0 beta 6");

            return(file);
        }
Example #15
0
        public static void WriteAssetFile(IGrannyFile file, Dictionary <string, string> civ6ShortNameToLongNameLookup, string className, string dsgName, string prettyAssetFilename, List <Dictionary <string, string> > materialBindingToMtlDicts)
        {
            string filenameNoExt = Path.GetFileNameWithoutExtension(file.Filename);

            if (prettyAssetFilename != null && prettyAssetFilename.Length > 0)
            {
                filenameNoExt = prettyAssetFilename;
            }
            string   directory     = Path.GetDirectoryName(file.Filename);
            TextInfo textInfo      = new CultureInfo("en-US", false).TextInfo;
            string   assetFilename = textInfo.ToTitleCase(filenameNoExt) + ".ast";
            string   instanceName  = "Asset";

            StreamWriter outputWriter = new StreamWriter(new FileStream(directory + "\\" + assetFilename, FileMode.Create));

            WriteAssetHeader(instanceName, outputWriter);
            WriteBehaviorMetadataToStream(civ6ShortNameToLongNameLookup, dsgName, outputWriter);
            WriteGeometrySetMetadataToStream(new List <IGrannyFile> {
                file
            }, outputWriter, materialBindingToMtlDicts, className);
            WriteBlankCookParams(outputWriter);
            WriteVersion(outputWriter);

            outputWriter.WriteLine("<m_ParticleEffects/>");
            outputWriter.WriteLine("<m_Geometries/>");
            outputWriter.WriteLine("<m_Animations/>");
            outputWriter.WriteLine("<m_Materials/>");

            WriteClassName(className, outputWriter);

            outputWriter.WriteLine("<m_DataFiles/>");

            WriteFooter(className, textInfo.ToTitleCase(filenameNoExt), instanceName, outputWriter);

            outputWriter.Close();
        }
        public static void batchExport(GrannyContext grannyContext, string unitListFile)
        {
            StreamReader streamReader = new StreamReader(unitListFile);

            string directory = Path.GetDirectoryName(unitListFile);

            string regexString = "(.*);(.*);(.*);(.*)";

            while (!streamReader.EndOfStream)
            {
                string currentLine = streamReader.ReadLine();

                Regex           regex = new Regex(regexString);
                MatchCollection mc    = regex.Matches(currentLine);
                foreach (Match m in mc)
                {
                    string      gr2Filename = m.Groups[1].Value.Trim().ToLower();
                    IGrannyFile grannyFile  = grannyContext.LoadGrannyFile(directory + "\\" + gr2Filename);
                    NexusBuddyApplicationForm.loadedFile = grannyFile;
                    NexusBuddyApplicationForm.form.refreshAppData();
                    exportAllModelsToNB2(grannyFile);
                }
            }
        }
Example #17
0
        private static unsafe void createAndBindMaterials(string outputFilename, IGrannyFile file, List <GrannyModelInfo> modelInfos)
        {
            GrannyFileWrapper fileWrapper2 = new GrannyFileWrapper(CivNexusSixApplicationForm.form.SaveAsAction(file, outputFilename, false));

            CivNexusSixApplicationForm.form.RefreshAppData();

            for (int modelIndex = 0; modelIndex < modelInfos.Count; modelIndex++)
            {
                var modelInfo = modelInfos[modelIndex];
                for (int meshIndex = 0; meshIndex < modelInfo.meshBindings.Count; meshIndex++)
                {
                    GrannyMeshInfo meshInfo = modelInfo.meshBindings[meshIndex];
                    fileWrapper2.createMaterials(modelIndex, meshIndex, meshInfo);
                }
            }

            GrannyFileWrapper fileWrapper3 = new GrannyFileWrapper(CivNexusSixApplicationForm.form.SaveAsAction(fileWrapper2.wrappedFile, outputFilename, false));

            fileWrapper3.pruneMaterials();

            CivNexusSixApplicationForm.form.SaveAsAction(fileWrapper3.wrappedFile, outputFilename, false);

            CivNexusSixApplicationForm.form.RefreshAppData();
        }
Example #18
0
        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);
        }
Example #19
0
        public static void WriteGeoAnimFile(IGrannyFile file, int currentModelIndex, string className)
        {
            string fgxFilename   = Path.GetFileName(file.Filename);
            string filenameNoExt = Path.GetFileNameWithoutExtension(file.Filename);

            string directory = Path.GetDirectoryName(file.Filename);

            string numberFormat = "f6";

            bool   isAnimation   = false;
            string instanceName  = "Geometry";
            string fileExtension = ".geo";

            if (file.Animations.Count > 0 && file.Models.Count == 0)
            {
                isAnimation   = true;
                instanceName  = "Animation";
                fileExtension = ".anm";
            }

            string geoFilename = filenameNoExt + fileExtension;

            string wigFilename = "";

            if (className.Equals("Leader") && instanceName.Equals("Geometry"))
            {
                wigFilename = filenameNoExt + ".wig";
                string wigFullPath = directory + "\\" + wigFilename;
                File.Copy(CivNexusSixApplicationForm.form.dummyWigFilename, wigFullPath, true);
            }

            StreamWriter outputWriter = new StreamWriter(new FileStream(directory + "\\" + geoFilename, FileMode.Create));

            WriteAssetHeader(instanceName, outputWriter);

            WriteBlankCookParams(outputWriter);
            WriteVersion(outputWriter);

            if (isAnimation)
            {
                outputWriter.WriteLine("<m_fDuration>" + file.Animations[0].Duration.ToString(numberFormat, CultureInfo.InvariantCulture) + "</m_fDuration>");
            }
            else
            {
                outputWriter.WriteLine("<m_Meshes>");
                foreach (IGrannyMesh mesh in file.Meshes)
                {
                    GrannyMeshWrapper meshWrapper = new GrannyMeshWrapper(mesh);

                    outputWriter.WriteLine("<Element>");
                    outputWriter.WriteLine("<m_Name text=\"" + mesh.Name + "\"/>");

                    outputWriter.WriteLine("<m_Groups>");

                    int totalTriangles = 0;
                    foreach (IGrannyTriMaterialGroup triMaterialGroup in mesh.TriangleMaterialGroups)
                    {
                        outputWriter.WriteLine("<Element>");
                        outputWriter.WriteLine("<m_Name text=\"" + mesh.MaterialBindings[triMaterialGroup.MaterialIndex].Name + "\"/>");
                        outputWriter.WriteLine("<m_nFirstPrim>" + triMaterialGroup.TriFirst + "</m_nFirstPrim>");
                        outputWriter.WriteLine("<m_nPrims>" + triMaterialGroup.TriCount + "</m_nPrims>");
                        outputWriter.WriteLine("</Element>");

                        totalTriangles += triMaterialGroup.TriCount;
                    }
                    outputWriter.WriteLine("</m_Groups>");

                    outputWriter.WriteLine("<m_nBoundBoneCount>" + mesh.BoneBindings.Count + "</m_nBoundBoneCount>");
                    outputWriter.WriteLine("<m_nPrimitiveCount>" + totalTriangles + "</m_nPrimitiveCount>");
                    outputWriter.WriteLine("<m_nVertexCount>" + mesh.VertexCount + "</m_nVertexCount>");

                    outputWriter.WriteLine("</Element>");
                }
                outputWriter.WriteLine("</m_Meshes>");

                outputWriter.WriteLine("<m_Bones>");
                foreach (IGrannyBone bone in file.Models[currentModelIndex].Skeleton.Bones)
                {
                    outputWriter.WriteLine("<Element text=\"" + bone.Name + "\"/>");
                }
                outputWriter.WriteLine("</m_Bones>");
                outputWriter.WriteLine("<m_ModelName text=\"" + file.Models[currentModelIndex].Name + "\"/>");
            }

            WriteSourcePathAndTimes(outputWriter);

            WriteClassName(className, outputWriter);

            outputWriter.WriteLine("<m_DataFiles>");
            outputWriter.WriteLine("<Element>");
            outputWriter.WriteLine("<m_ID text=\"GR2\"/>");
            outputWriter.WriteLine("<m_RelativePath text=\"" + fgxFilename + "\"/>");
            outputWriter.WriteLine("</Element>");

            if (className.Equals("Leader") && instanceName.Equals("Geometry"))
            {
                outputWriter.WriteLine("<Element>");
                outputWriter.WriteLine("<m_ID text=\"WIG\"/>");
                outputWriter.WriteLine("<m_RelativePath text=\"" + wigFilename + "\"/>");
                outputWriter.WriteLine("</Element>");
            }

            outputWriter.WriteLine("</m_DataFiles>");

            WriteFooter(className, filenameNoExt, instanceName, outputWriter);

            outputWriter.Close();
        }
Example #20
0
        private static void WriteGeometrySetMetadataToStream(List <IGrannyFile> files, StreamWriter outputWriter, List <Dictionary <string, string> > materialBindingToMtlDicts, string assetClassName)
        {
            List <string> stateNames = null;

            if (assetClassName.Equals("TileBase"))
            {
                stateNames = new List <string> {
                    "Unworked", "Worked", "Pillaged", "Unbuilt", "Construction"
                };
            }
            else
            {
                stateNames = new List <string> {
                    "Default"
                };
            }

            outputWriter.WriteLine("<m_GeometrySet>");
            outputWriter.WriteLine("<m_ModelInstances>");
            for (int i = 0; i < files.Count; i++)
            {
                IGrannyFile file = files[i];

                foreach (IGrannyModel model in file.Models)
                {
                    string filenameNoExt = Path.GetFileNameWithoutExtension(file.Filename);

                    string upperModelName = model.Name.ToUpper();
                    bool   isTreeCut      = upperModelName.Contains("TREE") && upperModelName.Contains("CUT");

                    //First pass - check if any valid mesh bindings
                    bool modelHasValidMeshBinding = false;
                    foreach (IGrannyMesh mesh in model.MeshBindings)
                    {
                        string upperMeshName = mesh.Name.ToUpper();
                        bool   isTreeCutMesh = upperMeshName.Contains("TREE") && upperMeshName.Contains("CUT");
                        bool   isShadowMesh  = upperMeshName.Contains("SHADOW");

                        if (!upperMeshName.Contains("DMG") && !isTreeCutMesh && !isShadowMesh)
                        {
                            modelHasValidMeshBinding = true;
                            break;
                        }
                    }

                    if (!isTreeCut && modelHasValidMeshBinding)
                    {
                        outputWriter.WriteLine("<Element>");
                        outputWriter.WriteLine("<m_Name text=\"" + model.Name + "\"/>");
                        outputWriter.WriteLine("<m_GeoName text=\"" + filenameNoExt + "\"/>");

                        outputWriter.WriteLine("<m_GroupStates>");

                        foreach (IGrannyMesh mesh in model.MeshBindings)
                        {
                            string upperMeshName = mesh.Name.ToUpper();
                            bool   isTreeCutMesh = upperMeshName.Contains("TREE") && upperMeshName.Contains("CUT");
                            bool   isShadowMesh  = upperMeshName.Contains("SHADOW");

                            if (!upperMeshName.Contains("DMG") && !isTreeCutMesh && !isShadowMesh)
                            {
                                foreach (IGrannyTriMaterialGroup triMaterialGroup in mesh.TriangleMaterialGroups)
                                {
                                    string materialBindingName = mesh.MaterialBindings[triMaterialGroup.MaterialIndex].Name;

                                    foreach (string stateName in stateNames)
                                    {
                                        if (!materialBindingName.Contains("ColorMap") && !materialBindingName.Contains("Generic_Grey_8") && !materialBindingName.Contains("04 - Default"))
                                        {
                                            string mtlFilename = mesh.MaterialBindings[triMaterialGroup.MaterialIndex].Name;

                                            if (mtlFilename.Contains("."))
                                            {
                                                string[] parts = mtlFilename.Split('.');
                                                mtlFilename = parts[0];
                                            }

                                            outputWriter.WriteLine("<Element>");

                                            outputWriter.WriteLine("<m_Values>");
                                            outputWriter.WriteLine("<m_Values>");

                                            outputWriter.WriteLine("<Element class=\"AssetObjects:ObjectValue\">");

                                            string mtlFilenameToSet = mtlFilename;

                                            if (materialBindingToMtlDicts != null)
                                            {
                                                Dictionary <string, string> materialBindingToMtlDict = materialBindingToMtlDicts[i];
                                                if (materialBindingToMtlDict != null)
                                                {
                                                    if (materialBindingToMtlDict.ContainsKey(materialBindingName))
                                                    {
                                                        mtlFilenameToSet = materialBindingToMtlDict[materialBindingName];
                                                    }
                                                }
                                            }

                                            outputWriter.WriteLine("<m_ObjectName text=\"" + mtlFilenameToSet + "\"/>");
                                            outputWriter.WriteLine("<m_eObjectType>MATERIAL</m_eObjectType>");
                                            outputWriter.WriteLine("<m_ParamName text=\"Material\"/>");
                                            outputWriter.WriteLine("</Element>");

                                            if (assetClassName.Equals("TileBase"))
                                            {
                                                outputWriter.WriteLine("<Element class=\"AssetObjects..BoolValue\">");
                                                outputWriter.WriteLine("<m_bValue>true</m_bValue>");
                                                outputWriter.WriteLine("<m_ParamName text=\"Visible\"/>");
                                                outputWriter.WriteLine("</Element>");
                                            }

                                            outputWriter.WriteLine("</m_Values>");
                                            outputWriter.WriteLine("</m_Values>");

                                            outputWriter.WriteLine("<m_GroupName text=\"" + materialBindingName + "\"/>");

                                            outputWriter.WriteLine("<m_MeshName text=\"" + mesh.Name + "\"/>");

                                            outputWriter.WriteLine("<m_StateName text=\"" + stateName + "\"/>");

                                            outputWriter.WriteLine("</Element>");
                                        }
                                    }
                                }
                            }
                        }
                        outputWriter.WriteLine("</m_GroupStates>");
                        outputWriter.WriteLine("</Element>");
                    }
                }
            }
            outputWriter.WriteLine("</m_ModelInstances>");
            outputWriter.WriteLine("</m_GeometrySet>");
        }
Example #21
0
        public unsafe static void importCN6(string sourceFilename, string outputFilename, GrannyContext grannyContext, int vertexFormat)
        {
            string      templateFilename = getTemplateFilename(vertexFormat);
            IGrannyFile file             = CivNexusSixApplicationForm.form.OpenFileAsTempFileCopy(templateFilename, "tempimport");

            GrannyFileWrapper fileWrapper = new GrannyFileWrapper(file);

            fileWrapper.setNumMeshes(0);
            fileWrapper.setNumVertexDatas(0);
            fileWrapper.setNumSkeletons(0);
            fileWrapper.setNumTriTopologies(0);

            List <GrannyModelInfo> modelInfos = loadModelInfos(sourceFilename, vertexFormat);

            fileWrapper.setNumMeshes(0);
            fileWrapper.setNumModels(0);

            foreach (GrannyModelInfo modelInfo in modelInfos)
            {
                doBoneBindings(modelInfo);

                List <IGrannyFile> meshFileList = new List <IGrannyFile>();
                foreach (GrannyMeshInfo meshInfo in modelInfo.meshBindings)
                {
                    meshFileList.Add(writeMesh(meshInfo, templateFilename));
                }

                IGrannyFile modelFile = CivNexusSixApplicationForm.form.OpenFileAsTempFileCopy(templateFilename, "tempimport");

                IGrannyModel model = modelFile.Models[0];

                GrannyModelWrapper modelWrapper = new GrannyModelWrapper(model);

                modelWrapper.setNumMeshBindings(0);
                model.MeshBindings.Clear();

                GrannySkeletonWrapper skeletonWrapper = new GrannySkeletonWrapper(modelFile.Models[0].Skeleton);
                skeletonWrapper.writeSkeletonInfo(modelInfo.skeleton);

                string worldBoneName = modelInfo.skeleton.bones[0].name;

                string modelName = worldBoneName;
                foreach (GrannyBoneInfo bone in modelInfo.skeleton.bones)
                {
                    if (!bone.name.Contains("ADJUSTMENT_BONE"))
                    {
                        modelName = bone.name;
                        break;
                    }
                }

                modelWrapper.setName(modelName);
                skeletonWrapper.setName(modelName);

                foreach (IGrannyFile meshFile in meshFileList)
                {
                    doAppendMeshBinding(modelFile, meshFile, 0);
                }

                foreach (IGrannyMesh mesh in model.MeshBindings)
                {
                    file.AddMeshReference(mesh);
                }

                file.AddModelReference(model);

                CivNexusSixApplicationForm.form.RefreshAppData();
            }

            fileWrapper.setNumModels(modelInfos.Count());

            fileWrapper.setFromArtToolInfo("Blender", 2, 0);
            float[] matrix = { 1f, 0f, 0f, 0f, 0f, 1f, 0f, -1f, 0f };
            fileWrapper.setMatrix(matrix);
            CivNexusSixApplicationForm.SetExporterInfo(fileWrapper);
            fileWrapper.setFromFileName(sourceFilename);

            createAndBindMaterials(outputFilename, file, modelInfos);
        }
 public static void exportNB2(IGrannyFile grannyFile, Int32 currentModelIndex)
 {
     exportNB2Model(grannyFile, currentModelIndex);
 }
        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();
        }
Example #24
0
        public static void br2Export(IGrannyFile grannyFile, int currentModelIndex)
        {
            string fileExtension  = ".br2";
            string outputFilename = "";
            string numberFormat   = "f8";

            if (grannyFile.Models.Count > 1)
            {
                outputFilename = grannyFile.Filename.Replace(".fgx", "_model" + currentModelIndex + fileExtension);
                outputFilename = outputFilename.Replace(".FGX", "_model" + currentModelIndex + fileExtension);
            }
            else
            {
                outputFilename = grannyFile.Filename.Replace(".fgx", fileExtension);
                outputFilename = outputFilename.Replace(".FGX", fileExtension);
            }

            StreamWriter outputWriter = new StreamWriter(new FileStream(outputFilename, FileMode.Create));

            IGrannyModel    model    = grannyFile.Models[currentModelIndex];
            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[]>();

            foreach (IGrannyBone bone in skeleton.Bones)
            {
                double[] bonePosition = NB2NA2FileOps.getBoneWorldPosition(bone);
                boneNameToPositionMap.Add(bone.Name, bonePosition);

                //MemoryUtil.memLogLine("boneName: " + bone.Name + " bone position:" + bonePosition[0] + " " + bonePosition[1] + " " + bonePosition[2]);
            }

            outputWriter.WriteLine("// Nexus Buddy BR2 - Exported from Nexus Buddy 2");
            outputWriter.WriteLine("skeleton");

            // Write Bones
            //outputWriter.WriteLine("Bones: " + skeleton.Bones.Count);
            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);
            }

            // 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];
                }
                //StringBuilder boneStringBuilder = new StringBuilder();


                outputWriter.WriteLine("mesh:\"" + meshName + "\"");

                // Write Vertices
                outputWriter.WriteLine("vertices");
                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     = NB2NA2FileOps.getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName0, boneWeight0, vertex.position);

                    string boneName1   = grannyMeshInfo.boneBindings[vertex.boneIndices[1]];
                    float  boneWeight1 = (float)vertex.boneWeights[1] / 255;
                    int    boneId1     = NB2NA2FileOps.getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName1, boneWeight1, vertex.position);

                    string boneName2   = grannyMeshInfo.boneBindings[vertex.boneIndices[2]];
                    float  boneWeight2 = (float)vertex.boneWeights[2] / 255;
                    int    boneId2     = NB2NA2FileOps.getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName2, boneWeight2, vertex.position);

                    string boneName3   = grannyMeshInfo.boneBindings[vertex.boneIndices[3]];
                    float  boneWeight3 = (float)vertex.boneWeights[3] / 255;
                    int    boneId3     = NB2NA2FileOps.getBoneIdForBoneName(boneLookup, boneNameToPositionMap, boneName3, boneWeight3, 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) + " " +
                                           vertex.uv[0].ToString(numberFormat, CultureInfo.InvariantCulture) + " " + vertex.uv[1].ToString(numberFormat, CultureInfo.InvariantCulture) + " "
                                           + boneId0 + " " + boneId1 + " " + boneId2 + " " + boneId3 + " "
                                           + vertex.boneWeights[0] + " " + vertex.boneWeights[1] + " " + vertex.boneWeights[2] + " " + vertex.boneWeights[3] + " "
                                           + 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)
                                           );
                }

                // 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]);
                }
            }
            outputWriter.WriteLine("end");

            outputWriter.Close();
        }
Example #25
0
        public static void exportNB2Model(IGrannyFile grannyFile, int modelId)
        {
            string fileExtension  = ".nb2";
            string outputFilename = "";
            string numberFormat   = "f6";

            if (grannyFile.Models.Count > 1)
            {
                outputFilename = grannyFile.Filename.Replace(".fgx", "_model" + modelId + fileExtension);
                outputFilename = outputFilename.Replace(".FGX", "_model" + modelId + fileExtension);
            }
            else
            {
                outputFilename = grannyFile.Filename.Replace(".fgx", fileExtension);
                outputFilename = outputFilename.Replace(".FGX", fileExtension);
            }

            StreamWriter outputWriter = new StreamWriter(new FileStream(outputFilename, FileMode.Create));

            IGrannyModel          model           = grannyFile.Models[modelId];
            IGrannySkeleton       skeleton        = model.Skeleton;
            GrannySkeletonWrapper skeletonWrapper = new GrannySkeletonWrapper(skeleton);

            skeletonWrapper.readSkeletonInfo();

            // 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)
            {
                double[] bonePosition = getBoneWorldPosition(bone);
                boneNameToPositionMap.Add(bone.Name, bonePosition);
            }

            outputWriter.WriteLine("// Nexus Buddy NB2 - Exported from Nexus Buddy 2");
            outputWriter.WriteLine("Frames: 30");
            outputWriter.WriteLine("Frame: 1");

            // 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];
                }
                outputWriter.WriteLine("\"" + meshName + "\" 0 0");

                // 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 Material
            outputWriter.WriteLine("Materials: 1");
            outputWriter.WriteLine("\"Material_0\"");
            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");
            outputWriter.WriteLine("\"Material_0\"");
            outputWriter.WriteLine("\"\"");

            // 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;

                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();
        }