Example #1
0
        public static void ExportTo3DS(string filePath, GeometryModel3D modelData, Image textureFileData)
        {
            //sanity checks
            if (modelData == null)
            {
                throw new ArgumentException("Geometry model info not supplied.");
            }
            if (!(modelData.Geometry != null && modelData.Geometry is MeshGeometry3D))
            {
                throw new ArgumentException("Passed model is not of type mesh geometry 3d");
            }

            //read specific values from xaml file
            var modelColor          = GetModelColor(modelData);
            var mesh                = ((MeshGeometry3D)modelData.Geometry);
            var containsTextureInfo = ContainsTextureInfo(mesh);
            var positionCount       = mesh.Positions.Count;
            var points              = mesh.Positions;
            var textures            = mesh.TextureCoordinates;
            var polygons            = mesh.TriangleIndices;

            //Open the 3DS file for writing
            var writer = InitializeFile(filePath);

            //Write Material Info
            var textureFileName = MakeTextureFileName(filePath);

            MaterialChunkWriter.WriteMaterialChunk(modelColor, containsTextureInfo, textureFileName, writer);

            var objectCount = 0;
            _3DSObjectDataHandler objHandler = null;

            ushort[] setIndicesForObj   = null;
            bool[]   isIndicesSetForObj = null;
            ushort   positionIndexInObj = 0;

            for (var ctr = 0; ctr < polygons.Count; ctr += 3)
            {
                var createNewObject = objHandler == null ||
                                      objHandler.PolygonCount >= MaxValForUnsignedShort ||
                                      objHandler.TextureCoodCount >= MaxValForUnsignedShort ||
                                      objHandler.VertexCount >= MaxValForUnsignedShort;

                if (createNewObject)
                {
                    if (objHandler != null)
                    {
                        objHandler.MakeFinalUpdates();
                    }

                    objectCount++;
                    if (objectCount > 9999)
                    {
                        throw new Exception("Error: Cannot create 3ds file.\n The number of objects into which the model can be broken down exceeds 9999");
                    }

                    objHandler         = new _3DSObjectDataHandler(writer, objectCount);
                    setIndicesForObj   = new ushort[positionCount];
                    isIndicesSetForObj = new bool[positionCount];
                    positionIndexInObj = 0;
                }

                var origIndices = new[] { (ushort)polygons[ctr], (ushort)polygons[ctr + 1], (ushort)polygons[ctr + 2] };
                var newIndices  = new List <ushort>();
                foreach (var origIndex in origIndices)
                {
                    if (isIndicesSetForObj[origIndex])
                    {
                        newIndices.Add(setIndicesForObj[origIndex]);
                    }
                    else
                    {//Add the new position
                        //Interchange y and z coordinates and change the sign of y to accomodate
                        //the difference in the axes orientation between the 3ds and xaml format
                        var origPoint = points[origIndex];
                        var point     = new Point3D(origPoint.X, -origPoint.Z, origPoint.Y);
                        objHandler.AddPosition(point);

                        if (textures != null && textures.Count > origIndex)
                        {
                            var texCood = mesh.TextureCoordinates[origIndex];
                            objHandler.AddTextureIndices((float)texCood.X, (float)texCood.Y);
                        }

                        setIndicesForObj[origIndex]   = positionIndexInObj;
                        isIndicesSetForObj[origIndex] = true;

                        newIndices.Add(positionIndexInObj);

                        positionIndexInObj++;
                    }
                }
                objHandler.AddPolygonIndices(newIndices[0], newIndices[1], newIndices[2]);
            }

            //Make the final updation call on object data handler
            if (objHandler != null)
            {
                objHandler.MakeFinalUpdates();
            }

            //Close the 3ds file (after final updations to the header chunks)
            UpdateAndCloseFile(writer);

            //save the texture image data
            SaveTextureImageData(filePath, textureFileData, textureFileName);
        }