private BabylonShadowGenerator ExportShadowGenerator(IINode lightNode, BabylonScene babylonScene)
        {
            var maxLight = (lightNode.ObjectRef as ILightObject);
            var babylonShadowGenerator = new BabylonShadowGenerator();

            RaiseMessage("Exporting shadow map", 2);

            babylonShadowGenerator.lightId = lightNode.GetGuid().ToString();

            babylonShadowGenerator.mapSize = maxLight.GetMapSize(0, Tools.Forever);

            babylonShadowGenerator.bias = lightNode.GetFloatProperty("babylonjs_shadows_bias", 0.00005f);
            babylonShadowGenerator.forceBackFacesOnly = lightNode.GetBoolProperty("babylonjs_forcebackfaces");

            var shadowsType = lightNode.GetStringProperty("babylonjs_shadows_type", "Blurred Variance");

            switch (shadowsType)
            {
                case "Hard shadows":
                    break;
                case "Poisson Sampling":
                    babylonShadowGenerator.usePoissonSampling = true;
                    break;
                case "Variance":
                    babylonShadowGenerator.useVarianceShadowMap = true;
                    break;
                case"Blurred Variance":
                    babylonShadowGenerator.useBlurVarianceShadowMap = true;
                    babylonShadowGenerator.blurScale = lightNode.GetFloatProperty("babylonjs_shadows_blurScale", 2);
                    babylonShadowGenerator.blurBoxOffset = lightNode.GetFloatProperty("babylonjs_shadows_blurBoxOffset", 1);
                    break;
            }

            
            var list = new List<string>();

            var inclusion = maxLight.ExclList.TestFlag(1); //NT_INCLUDE 
            var checkExclusionList = maxLight.ExclList.TestFlag(4); //NT_AFFECT_SHADOWCAST 

            foreach (var meshNode in Loader.Core.RootNode.NodesListBySuperClass(SClass_ID.Geomobject))
            {
#if MAX2017
                if (meshNode.CastShadows)
#else
                if (meshNode.CastShadows == 1)
#endif
                {
                    var inList = maxLight.ExclList.FindNode(meshNode) != -1;

                    if (!checkExclusionList || (inList && inclusion) || (!inList && !inclusion))
                    {
                        list.Add(meshNode.GetGuid().ToString());
                    }
                }
            }
            babylonShadowGenerator.renderList = list.ToArray();

            babylonScene.ShadowGeneratorsList.Add(babylonShadowGenerator);
            return babylonShadowGenerator;
        }
        private BabylonShadowGenerator ExportShadowGenerator(Node lightNode, BabylonScene babylonScene)
        {
            var maxLight = (lightNode.Object as Light);
            var babylonShadowGenerator = new BabylonShadowGenerator();

            RaiseMessage("Exporting shadow map", true, false, true);

            babylonShadowGenerator.lightId = lightNode.GetGuid().ToString();

            babylonShadowGenerator.mapSize = maxLight.GetMapSize(0, Interval.Forever);

            var maxScene = Kernel.Scene;
            var list = new List<string>();

            var inclusion = maxLight._Light.ExclList.TestFlag(1); //NT_INCLUDE 
            var checkExclusionList = maxLight._Light.ExclList.TestFlag(4); //NT_AFFECT_SHADOWCAST 

            foreach (var meshNode in maxScene.NodesListBySuperClass(SuperClassID.GeometricObject))
            {
                if (meshNode._Node.CastShadows == 1)
                {
                    var inList = maxLight._Light.ExclList.FindNode(meshNode._Node) != -1;

                    if (!checkExclusionList || (inList && inclusion) || (!inList && !inclusion))
                    {
                        list.Add(meshNode.GetGuid().ToString());
                    }
                }
            }
            babylonShadowGenerator.renderList = list.ToArray();

            babylonScene.ShadowGeneratorsList.Add(babylonShadowGenerator);
            return babylonShadowGenerator;
        }
Пример #3
0
        public SceneBuilder(string outputPath, string sceneName, ExportationOptions exportationOptions, BabylonSceneController controller, string scriptPath)
        {
            OutputPath = outputPath;
            SceneName = string.IsNullOrEmpty(sceneName) ? "scene" : sceneName;
            SceneController = controller;
            SceneJavascriptPath = scriptPath;

            materialsDictionary = new Dictionary<string, BabylonMaterial>();
            multiMatDictionary = new Dictionary<string, BabylonMultiMaterial>();
            uniqueGuids = new Dictionary<int, string>();

            babylonScene = new BabylonScene(OutputPath);
            babylonScene.producer = new BabylonProducer
            {
                file = Path.GetFileName(outputPath),
                version = "Unity3D",
                name = SceneName,
                exporter_version = "0.8.1"
            };
            this.exportationOptions = exportationOptions;
            this.ManifestData = String.Empty;
            if (SceneController != null)
            {
                this.ManifestData = "{" + String.Format("\n\t\"version\" : {0},\n\t\"enableSceneOffline\" : {1},\n\t\"enableTexturesOffline\" : {2}\n", SceneController.manifestOptions.manifestVersion, SceneController.manifestOptions.storeSceneOffline.ToString().ToLower(), SceneController.manifestOptions.storeTextureOffline.ToString().ToLower()) + "}";
            }
        }
        private BabylonShadowGenerator ExportShadowGenerator(IINode lightNode, BabylonScene babylonScene)
        {
            var maxLight = (lightNode.ObjectRef as ILightObject);
            var babylonShadowGenerator = new BabylonShadowGenerator();

            RaiseMessage("Exporting shadow map", 2);

            babylonShadowGenerator.lightId = lightNode.GetGuid().ToString();

            babylonShadowGenerator.mapSize = maxLight.GetMapSize(0, Tools.Forever);
            babylonShadowGenerator.usePoissonSampling = maxLight.AbsMapBias >= 1;

            var list = new List<string>();

            var inclusion = maxLight.ExclList.TestFlag(1); //NT_INCLUDE 
            var checkExclusionList = maxLight.ExclList.TestFlag(4); //NT_AFFECT_SHADOWCAST 

            foreach (var meshNode in Loader.Core.RootNode.NodesListBySuperClass(SClass_ID.Geomobject))
            {
                if (meshNode.CastShadows == 1)
                {
                    var inList = maxLight.ExclList.FindNode(meshNode) != -1;

                    if (!checkExclusionList || (inList && inclusion) || (!inList && !inclusion))
                    {
                        list.Add(meshNode.GetGuid().ToString());
                    }
                }
            }
            babylonShadowGenerator.renderList = list.ToArray();

            babylonScene.ShadowGeneratorsList.Add(babylonShadowGenerator);
            return babylonShadowGenerator;
        }
Пример #5
0
        public SceneBuilder(string outputPath, string sceneName, ExportationOptions exportationOptions)
        {
            OutputPath = outputPath;
            SceneName = string.IsNullOrEmpty(sceneName) ? "scene" : sceneName;

            materialsDictionary = new Dictionary<string, BabylonMaterial>();
            multiMatDictionary = new Dictionary<string, BabylonMultiMaterial>();
            uniqueGuids = new Dictionary<int, string>();

            babylonScene = new BabylonScene(OutputPath);

            this.exportationOptions = exportationOptions;
        }
Пример #6
0
        void ExportDefaultLight(BabylonScene babylonScene)
        {
            var babylonLight = new BabylonLight();
            babylonLight.name = "Default light";
            babylonLight.id = Guid.NewGuid().ToString();
            babylonLight.type = 3;
            babylonLight.groundColor = new float[] { 0, 0, 0 };
            babylonLight.direction = new[] { 0, 1.0f, 0 };

            babylonLight.intensity = 1;

            babylonLight.diffuse = new[] { 1.0f, 1.0f, 1.0f };
            babylonLight.specular = new[] { 1.0f, 1.0f, 1.0f };

            babylonScene.LightsList.Add(babylonLight);
        }
        private string GetParentID(IIGameNode parentNode, BabylonScene babylonScene, IIGameScene scene)
        {
            var parentType = parentNode.IGameObject.IGameType;
            var parentId = parentNode.MaxNode.GetGuid().ToString();
            switch (parentType)
            {
                case Autodesk.Max.IGameObject.ObjectTypes.Light:
                case Autodesk.Max.IGameObject.ObjectTypes.Mesh:
                case Autodesk.Max.IGameObject.ObjectTypes.Camera:
                    break;


                default:
                    if (babylonScene.MeshesList.All(m => m.id != parentId))
                    {
                        ExportMesh(scene, parentNode, babylonScene);
                    }
                    break;
            }
            return parentId;
        }
Пример #8
0
        public SceneBuilder(string outputPath, string sceneName, ExportationOptions exportationOptions)
        {
            OutputPath = outputPath;
            SceneName = string.IsNullOrEmpty(sceneName) ? "scene" : sceneName;

            materialsDictionary = new Dictionary<string, BabylonMaterial>();
            multiMatDictionary = new Dictionary<string, BabylonMultiMaterial>();
            uniqueGuids = new Dictionary<int, string>();

            babylonScene = new BabylonScene(OutputPath);

            babylonScene.producer = new BabylonProducer
            {
                file = Path.GetFileName(outputPath),
                version = "Unity3D",
                name = SceneName,
                exporter_version = "0.8"
            };

            this.exportationOptions = exportationOptions;
        }
Пример #9
0
        private void ExportLight(IINode lightNode, BabylonScene babylonScene)
        {
            if (lightNode.GetBoolProperty("babylonjs_noexport"))
            {
                return;
            }

            var maxLight = (lightNode.ObjectRef as ILightObject);
            var babylonLight = new BabylonLight();

            RaiseMessage(lightNode.Name, 1);
            babylonLight.name = lightNode.Name;
            babylonLight.id = lightNode.GetGuid().ToString();

            // Type
            var lightState = Loader.Global.LightState.Create();
            maxLight.EvalLightState(0, Tools.Forever, lightState);
            var directionScale = -1;

            switch (lightState.Type)
            {
                case LightType.OmniLgt:
                    babylonLight.type = 0;
                    break;
                case LightType.SpotLgt:
                    babylonLight.type = 2;
                    babylonLight.angle = (float)(maxLight.GetFallsize(0, Tools.Forever) * Math.PI / 180.0f);
                    babylonLight.exponent = 1;
                    break;
                case LightType.DirectLgt:
                    babylonLight.type = 1;
                    break;
                case LightType.AmbientLgt:
                    babylonLight.type = 3;
                    babylonLight.groundColor = new float[] { 0, 0, 0 };
                    directionScale = 1;
                    break;
            }

            // Shadows
            if (maxLight.ShadowMethod == 1)
            {
                if (lightState.Type == LightType.DirectLgt)
                {
                    ExportShadowGenerator(lightNode, babylonScene);
                }
                else
                {
                    RaiseWarning("Shadows maps are only supported for directional lights", 2);
                }
            }

            // Position
            var wm = lightNode.GetWorldMatrix(0, false);
            var position = wm.Trans;
            babylonLight.position = position.ToArraySwitched();

            // Direction
            var target = lightNode.Target;
            if (target != null)
            {
                var targetWm = target.GetObjTMBeforeWSM(0, Tools.Forever);
                var targetPosition = targetWm.Trans;

                var direction = targetPosition.Subtract(position);
                babylonLight.direction = direction.ToArraySwitched();
            }
            else
            {
                var dir = wm.GetRow(2).MultiplyBy(directionScale);
                babylonLight.direction = dir.ToArraySwitched();
            }

            // Exclusion
            var maxScene = Loader.Core.RootNode;
            var inclusion = maxLight.ExclList.TestFlag(1); //NT_INCLUDE 
            var checkExclusionList = maxLight.ExclList.TestFlag(2); //NT_AFFECT_ILLUM

            if (checkExclusionList)
            {
                var excllist = new List<string>();
                var incllist = new List<string>();

                foreach (var meshNode in maxScene.NodesListBySuperClass(SClass_ID.Geomobject))
                {
                    if (meshNode.CastShadows == 1)
                    {
                        var inList = maxLight.ExclList.FindNode(meshNode) != -1;

                        if (inList)
                        {
                            if (inclusion)
                            {
                                incllist.Add(meshNode.GetGuid().ToString());
                            }
                            else
                            {
                                excllist.Add(meshNode.GetGuid().ToString());
                            }
                        }
                    }
                }

                babylonLight.includedOnlyMeshesIds = incllist.ToArray();
                babylonLight.excludedMeshesIds = excllist.ToArray();
            }

            // Other fields
            babylonLight.intensity = maxLight.GetIntensity(0, Tools.Forever);

            babylonLight.diffuse = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 };
            babylonLight.specular = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 };

            if (maxLight.UseAtten)
            {
                babylonLight.range = maxLight.GetAtten(0, 1, Tools.Forever);
            }

            // Animations
            var animations = new List<BabylonAnimation>();

            if (!ExportVector3Controller(lightNode.TMController.PositionController, "position", animations))
            {
                ExportVector3Animation("position", animations, key =>
                {
                    var worldMatrix = lightNode.GetWorldMatrix(key, lightNode.HasParent());
                    return worldMatrix.Trans.ToArraySwitched();
                });
            }

            ExportVector3Animation("direction", animations, key =>
            {
                var targetNode = lightNode.Target;
                if (targetNode != null)
                {
                    var targetWm = target.GetObjTMBeforeWSM(0, Tools.Forever);
                    var targetPosition = targetWm.Trans;

                    var direction = targetPosition.Subtract(position);
                    return direction.ToArraySwitched();
                }
                
                var dir = wm.GetRow(2).MultiplyBy(directionScale);
                return dir.ToArraySwitched();
            });

            ExportFloatAnimation("intensity", animations, key => new[] { maxLight.GetIntensity(key, Tools.Forever) });

            babylonLight.animations = animations.ToArray();

            if (lightNode.GetBoolProperty("babylonjs_autoanimate"))
            {
                babylonLight.autoAnimate = true;
                babylonLight.autoAnimateFrom = (int)lightNode.GetFloatProperty("babylonjs_autoanimate_from");
                babylonLight.autoAnimateTo = (int)lightNode.GetFloatProperty("babylonjs_autoanimate_to");
                babylonLight.autoAnimateLoop = lightNode.GetBoolProperty("babylonjs_autoanimateloop");
            }

            babylonScene.LightsList.Add(babylonLight);
        }
Пример #10
0
        private void ExportCamera(IINode cameraNode, BabylonScene babylonScene)
        {
            if (cameraNode.GetBoolProperty("babylonjs_noexport"))
            {
                return;
            }

            var maxCamera = (cameraNode.ObjectRef as ICameraObject);
            var babylonCamera = new BabylonCamera();

            RaiseMessage(cameraNode.Name, 1);
            babylonCamera.name = cameraNode.Name;
            babylonCamera.id = cameraNode.GetGuid().ToString();
            if (cameraNode.HasParent())
            {
                babylonCamera.parentId = cameraNode.ParentNode.GetGuid().ToString();
            }

            babylonCamera.fov = Tools.ConvertFov(maxCamera.GetFOV(0, Tools.Forever));
            babylonCamera.minZ = maxCamera.GetEnvRange(0, 0, Tools.Forever);
            babylonCamera.maxZ = maxCamera.GetEnvRange(0, 1, Tools.Forever);

            if (babylonCamera.minZ == 0.0f)
            {
                babylonCamera.minZ = 0.1f;
            }

            // Control
            babylonCamera.speed = cameraNode.GetFloatProperty("babylonjs_speed", 1.0f);
            babylonCamera.inertia = cameraNode.GetFloatProperty("babylonjs_inertia", 0.9f);

            // Collisions
            babylonCamera.checkCollisions = cameraNode.GetBoolProperty("babylonjs_checkcollisions");
            babylonCamera.applyGravity = cameraNode.GetBoolProperty("babylonjs_applygravity");
            babylonCamera.ellipsoid = cameraNode.GetVector3Property("babylonjs_ellipsoid");

            // Position
            var wm = cameraNode.GetWorldMatrix(0, cameraNode.HasParent());
            var position = wm.Trans;
            babylonCamera.position = position.ToArraySwitched();

            // Target
            var target = cameraNode.Target;
            if (target != null)
            {
                babylonCamera.lockedTargetId = target.GetGuid().ToString();
            }
            else
            {
                var dir = wm.GetRow(2).MultiplyBy(-1);
                babylonCamera.target = position.Add(dir).ToArraySwitched();
            }

            // Animations
            var animations = new List<BabylonAnimation>();
            if (!ExportVector3Controller(cameraNode.TMController.PositionController, "position", animations))
            {
                ExportVector3Animation("position", animations, key =>
                {
                    var worldMatrix = cameraNode.GetWorldMatrix(key, cameraNode.HasParent());
                    return worldMatrix.Trans.ToArraySwitched();
                });
            }

            ExportFloatAnimation("fov", animations, key => new[] {Tools.ConvertFov(maxCamera.GetFOV(key, Tools.Forever))});

            babylonCamera.animations = animations.ToArray();

            if (cameraNode.GetBoolProperty("babylonjs_autoanimate"))
            {
                babylonCamera.autoAnimate = true;
                babylonCamera.autoAnimateFrom = (int)cameraNode.GetFloatProperty("babylonjs_autoanimate_from");
                babylonCamera.autoAnimateTo = (int)cameraNode.GetFloatProperty("babylonjs_autoanimate_to");
                babylonCamera.autoAnimateLoop = cameraNode.GetBoolProperty("babylonjs_autoanimateloop");
            }

            babylonScene.CamerasList.Add(babylonCamera);
        }
Пример #11
0
        private BabylonMesh ExportMesh(Node meshNode, BabylonScene babylonScene, CancellationToken token)
        {
            var babylonMesh = new BabylonMesh();
            int vx1, vx2, vx3;

            RaiseMessage(meshNode.Name, true);
            babylonMesh.name = meshNode.Name;
            babylonMesh.id = meshNode.GetGuid().ToString();
            if (meshNode.HasParent())
            {
                babylonMesh.parentId = meshNode.Parent.GetGuid().ToString();
            }

            // Misc.
            babylonMesh.isVisible = meshNode._Node.Renderable == 1;
            babylonMesh.pickable = meshNode._Node.GetBoolProperty("babylonjs_checkpickable");
            babylonMesh.receiveShadows = meshNode._Node.RcvShadows == 1;
            babylonMesh.showBoundingBox = meshNode._Node.GetBoolProperty("babylonjs_showboundingbox");
            babylonMesh.showSubMeshesBoundingBox = meshNode._Node.GetBoolProperty("babylonjs_showsubmeshesboundingbox");

            // Collisions
            babylonMesh.checkCollisions = meshNode._Node.GetBoolProperty("babylonjs_checkcollisions");

            // Position / rotation / scaling
            var wm = meshNode.GetWorldMatrix(0, meshNode.HasParent());
            babylonMesh.position = wm.Trans.ToArraySwitched();

            var parts = Loader.Global.AffineParts.Create();
            Loader.Global.DecompAffine(wm, parts);

            //var rotate = new float[3];

            //IntPtr xPtr = Marshal.AllocHGlobal(sizeof(float));
            //IntPtr yPtr = Marshal.AllocHGlobal(sizeof(float));
            //IntPtr zPtr = Marshal.AllocHGlobal(sizeof(float));
            //parts.Q.GetEuler(xPtr, yPtr, zPtr);

            //Marshal.Copy(xPtr, rotate, 0, 1);
            //Marshal.Copy(yPtr, rotate, 1, 1);
            //Marshal.Copy(zPtr, rotate, 2, 1);

            //var temp = -rotate[1];
            //rotate[0] = rotate[0] * parts.F;
            //rotate[1] = -rotate[2] * parts.F;
            //rotate[2] = temp * parts.F;

            //babylonMesh.rotation = rotate;

            babylonMesh.rotationQuaternion = parts.Q.ToArray();

            babylonMesh.scaling = parts.K.ToArraySwitched();

            if (wm.Parity)
            {
                vx1 = 2;
                vx2 = 1;
                vx3 = 0;
            }
            else
            {
                vx1 = 0;
                vx2 = 1;
                vx3 = 2;
            }

            // Pivot
            var pivotMatrix = Matrix3.Identity._IMatrix3;
            pivotMatrix.PreTranslate(meshNode._Node.ObjOffsetPos);
            Loader.Global.PreRotateMatrix(pivotMatrix, meshNode._Node.ObjOffsetRot);
            Loader.Global.ApplyScaling(pivotMatrix, meshNode._Node.ObjOffsetScale);
            babylonMesh.pivotMatrix = pivotMatrix.ToArray();

            // Mesh
            var objectState = meshNode._Node.EvalWorldState(0, false);
            var mesh = objectState.Obj.GetMesh();
            var computedMesh = meshNode.GetMesh();

            if (mesh != null)
            {
                mesh.BuildNormals();

                if (mesh.NumFaces < 1)
                {
                    RaiseError(string.Format("Mesh {0} has no face", babylonMesh.name));
                }

                if (mesh.NumVerts < 3)
                {
                    RaiseError(string.Format("Mesh {0} has not enough vertices", babylonMesh.name));
                }

                if (mesh.NumVerts >= 65536)
                {
                    RaiseError(string.Format("Mesh {0} has too many vertices (more than 65535)", babylonMesh.name));
                }

                // Material
                var mtl = meshNode.Material;
                var multiMatsCount = 1;

                if (mtl != null)
                {
                    babylonMesh.materialId = mtl.GetGuid().ToString();

                    if (!referencedMaterials.Contains(mtl))
                    {
                        referencedMaterials.Add(mtl);
                    }

                    multiMatsCount = Math.Max(mtl.NumSubMaterials, 1);
                }

                babylonMesh.visibility = meshNode._Node.GetVisibility(0, Interval.Forever._IInterval);

                var vertices = new List<GlobalVertex>();
                var indices = new List<int>();
                var matIDs = new List<int>();

                var hasUV = mesh.NumTVerts > 0;
                var hasUV2 = mesh.GetNumMapVerts(2) > 0;

                var noOptimize = meshNode._Node.GetBoolProperty("babylonjs_nooptimize");

                for (var face = 0; face < mesh.NumFaces; face++)
                {
                    indices.Add(CreateGlobalVertex(mesh, computedMesh, face, vx1, vertices, hasUV, hasUV2, noOptimize));
                    indices.Add(CreateGlobalVertex(mesh, computedMesh, face, vx2, vertices, hasUV, hasUV2, noOptimize));
                    indices.Add(CreateGlobalVertex(mesh, computedMesh, face, vx3, vertices, hasUV, hasUV2, noOptimize));
                    matIDs.Add(mesh.Faces[face].MatID % multiMatsCount);
                    if (token.IsCancellationRequested) token.ThrowIfCancellationRequested();
                }

                if (vertices.Count >= 65536)
                {
                    RaiseError(string.Format("Mesh {0} has too many vertices: {1} (limit is 65535)", babylonMesh.name, vertices.Count));
                }

                // Buffers
                babylonMesh.positions = vertices.SelectMany(v => v.Position.ToArraySwitched()).ToArray();
                babylonMesh.normals = vertices.SelectMany(v => v.Normal.ToArraySwitched()).ToArray();
                if (hasUV)
                {
                    babylonMesh.uvs = vertices.SelectMany(v => v.UV.ToArray()).ToArray();
                }
                if (hasUV2)
                {
                    babylonMesh.uvs2 = vertices.SelectMany(v => v.UV2.ToArray()).ToArray();
                }

                // Submeshes
                var sortedIndices = new List<int>();
                var subMeshes = new List<BabylonSubMesh>();
                var indexStart = 0;
                for (var index = 0; index < multiMatsCount; index++)
                {
                    var subMesh = new BabylonSubMesh();
                    var indexCount = 0;
                    var minVertexIndex = int.MaxValue;
                    var maxVertexIndex = int.MinValue;

                    subMesh.indexStart = indexStart;
                    subMesh.materialIndex = index;

                    for (var face = 0; face < matIDs.Count; face++)
                    {
                        if (matIDs[face] == index)
                        {
                            var a = indices[3 * face];
                            var b = indices[3 * face + 1];
                            var c = indices[3 * face + 2];

                            sortedIndices.Add(a);
                            sortedIndices.Add(b);
                            sortedIndices.Add(c);
                            indexCount += 3;

                            if (a < minVertexIndex)
                            {
                                minVertexIndex = a;
                            }

                            if (b < minVertexIndex)
                            {
                                minVertexIndex = b;
                            }

                            if (c < minVertexIndex)
                            {
                                minVertexIndex = c;
                            }

                            if (a > maxVertexIndex)
                            {
                                maxVertexIndex = a;
                            }

                            if (b > maxVertexIndex)
                            {
                                maxVertexIndex = b;
                            }

                            if (c > maxVertexIndex)
                            {
                                maxVertexIndex = c;
                            }
                        }
                    }
                    if (indexCount != 0)
                    {

                        subMesh.indexCount = indexCount;
                        subMesh.verticesStart = minVertexIndex;
                        subMesh.verticesCount = maxVertexIndex - minVertexIndex + 1;

                        indexStart += indexCount;

                        subMeshes.Add(subMesh);
                    }
                    if (token.IsCancellationRequested) token.ThrowIfCancellationRequested();
                }
                babylonMesh.subMeshes = subMeshes.ToArray();


                // Buffers - Indices
                babylonMesh.indices = sortedIndices.ToArray();
            }


            // Animations
            var animations = new List<BabylonAnimation>();
            ExportVector3Animation("position", animations, key =>
            {
                var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
                return worldMatrix.Trans.ToArraySwitched();
            });

            ExportQuaternionAnimation("rotationQuaternion", animations, key =>
            {
                var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());

                var affineParts = Loader.Global.AffineParts.Create();
                Loader.Global.DecompAffine(worldMatrix, affineParts);

                return affineParts.Q.ToArray();
            });

            ExportVector3Animation("scaling", animations, key =>
            {
                var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());

                var affineParts = Loader.Global.AffineParts.Create();
                Loader.Global.DecompAffine(worldMatrix, affineParts);

                return affineParts.K.ToArraySwitched();
            });

            ExportFloatAnimation("visibility", animations, key => new []{meshNode._Node.GetVisibility(key, Interval.Forever._IInterval)});


            babylonMesh.animations = animations.ToArray();

            if (meshNode._Node.GetBoolProperty("babylonjs_autoanimate"))
            {
                babylonMesh.autoAnimate = true;
                babylonMesh.autoAnimateFrom = (int)meshNode._Node.GetFloatProperty("babylonjs_autoanimate_from");
                babylonMesh.autoAnimateTo = (int)meshNode._Node.GetFloatProperty("babylonjs_autoanimate_to");
                babylonMesh.autoAnimateLoop = meshNode._Node.GetBoolProperty("babylonjs_autoanimateloop");
            }

            babylonScene.MeshesList.Add(babylonMesh);

            return babylonMesh;
        }
Пример #12
0
        private BabylonTexture ExportTexture(IStdMat2 stdMat, int index, BabylonScene babylonScene, Boolean allowCube = false)
        {
            if (!stdMat.MapEnabled(index))
            {
                return null;
            }
            var babylonTexture = new BabylonTexture();

            var texMap = stdMat.GetSubTexmap(index);
            var texture = texMap.GetParamBlock(0).Owner as IBitmapTex;

            if (texture == null)
            {
                return null;
            }

            babylonTexture.hasAlpha = (texture.AlphaSource != 3);
            babylonTexture.getAlphaFromRGB = (texture.AlphaSource == 2);
            babylonTexture.level = stdMat.GetTexmapAmt(index, 0);

            var uvGen = texture.UVGen;

            switch (uvGen.GetCoordMapping(0))
            {
                case 1: //MAP_SPHERICAL
                    babylonTexture.coordinatesMode = 1;
                    break;
                case 2: //MAP_PLANAR
                    babylonTexture.coordinatesMode = 2;
                    break;
                default:
                    babylonTexture.coordinatesMode = 0;
                    break;
            }

            babylonTexture.coordinatesIndex = uvGen.MapChannel - 1;
            if (uvGen.MapChannel > 2)
            {
                RaiseWarning(string.Format("Unsupported map channel, Only channel 1 and 2 are supported."), 2);
            }

            babylonTexture.uOffset = uvGen.GetUOffs(0);
            babylonTexture.vOffset = uvGen.GetVOffs(0);

            babylonTexture.uScale = uvGen.GetUScl(0);
            babylonTexture.vScale = uvGen.GetVScl(0);

            if (Path.GetExtension(texture.MapName).ToLower() == ".dds")
            {
                babylonTexture.vScale *= -1; // Need to invert Y-axis for DDS texture
            }

            babylonTexture.uAng = uvGen.GetUAng(0);
            babylonTexture.vAng = uvGen.GetVAng(0);
            babylonTexture.wAng = uvGen.GetWAng(0);

            babylonTexture.wrapU = 0; // CLAMP
            if ((uvGen.TextureTiling & 1) != 0) // WRAP
            {
                babylonTexture.wrapU = 1;
            }
            else if ((uvGen.TextureTiling & 4) != 0) // MIRROR
            {
                babylonTexture.wrapU = 2;
            }

            babylonTexture.wrapV = 0; // CLAMP
            if ((uvGen.TextureTiling & 2) != 0) // WRAP
            {
                babylonTexture.wrapV = 1;
            }
            else if ((uvGen.TextureTiling & 8) != 0) // MIRROR
            {
                babylonTexture.wrapV = 2;
            }

            babylonTexture.name = Path.GetFileName(texture.MapName);

            // Animations
            var animations = new List<BabylonAnimation>();
            ExportFloatAnimation("uOffset", animations, key => new[] { uvGen.GetUOffs(key) });
            ExportFloatAnimation("vOffset", animations, key => new[] { uvGen.GetVOffs(key) });
            ExportFloatAnimation("uScale", animations, key => new[] { uvGen.GetUScl(key) });
            ExportFloatAnimation("vScale", animations, key => new[] { uvGen.GetVScl(key) });
            ExportFloatAnimation("uAng", animations, key => new[] { uvGen.GetUAng(key) });
            ExportFloatAnimation("vAng", animations, key => new[] { uvGen.GetVAng(key) });
            ExportFloatAnimation("wAng", animations, key => new[] { uvGen.GetWAng(key) });

            babylonTexture.animations = animations.ToArray();

            // Copy texture to output
            try
            {
                if (File.Exists(texture.MapName))
                {
                    if (CopyTexturesToOutput)
                    {
                        File.Copy(texture.MapName, Path.Combine(babylonScene.OutputPath, babylonTexture.name), true);
                    }
                    babylonTexture.isCube = IsTextureCube(texture.MapName);
                }
                else
                {
                    var texturepath = Path.Combine(Path.GetDirectoryName(Loader.Core.CurFilePath), babylonTexture.name);
                    if (File.Exists(texturepath))
                    {
                        if (CopyTexturesToOutput)
                        {
                            File.Copy(texturepath, Path.Combine(babylonScene.OutputPath, babylonTexture.name), true);
                        }
                        babylonTexture.isCube = IsTextureCube(texturepath);
                    }
                    else
                    {
                        RaiseWarning(string.Format("Texture {0} not found.", babylonTexture.name), 2);
                    }
                }
            }
            catch
            {
                // silently fails
            }

            if (babylonTexture.isCube && !allowCube)
            {
                RaiseWarning(string.Format("Cube texture are only supported for reflection channel"), 2);
            }

            return babylonTexture;
        }
        private void ExportMaterial(Material materialNode, BabylonScene babylonScene)
        {
            var name = materialNode._Mtl.Name;
            var id = materialNode.GetGuid().ToString();

            RaiseMessage(name, true);

            if (materialNode.NumSubMaterials > 0)
            {
                var babylonMultimaterial = new BabylonMultiMaterial();
                babylonMultimaterial.name = name;
                babylonMultimaterial.id = id;

                var guids = new List<string>();

                for (var index = 0; index < materialNode.NumSubMaterials; index++)
                {
                    var subMat = materialNode.GetSubMaterial(index) as Material;

                    if (subMat != null)
                    {
                        guids.Add(subMat.GetGuid().ToString());

                        if (!referencedMaterials.Contains(subMat))
                        {
                            referencedMaterials.Add(subMat);
                            ExportMaterial(subMat, babylonScene);
                        }
                    }
                    else
                    {
                        guids.Add(Guid.Empty.ToString());
                    }
                }

                babylonMultimaterial.materials = guids.ToArray();

                babylonScene.MultiMaterialsList.Add(babylonMultimaterial);
                return;
            }


            var babylonMaterial = new BabylonMaterial();
            babylonMaterial.name = name;
            babylonMaterial.id = id;

            babylonMaterial.ambient = materialNode.GetAmbient(0).ToArray();
            babylonMaterial.diffuse = materialNode.GetDiffuse(0).ToArray();
            babylonMaterial.specular = materialNode.GetSpecular(0).Scale(materialNode.GetShinyStrength(0));
            babylonMaterial.specularPower = materialNode.GetShininess(0) * 256;

            babylonMaterial.emissive = materialNode.SelfIlluminationColorOn ? materialNode.GetSelfIllumColor(0).ToArray() : materialNode.GetDiffuse(0).Scale(materialNode.GetSelfIllumination(0));
            babylonMaterial.alpha = 1.0f - materialNode.GetTransparency(0);

            var stdMat = materialNode._Mtl.GetParamBlock(0).Owner as IStdMat2;

            if (stdMat != null)
            {
                // Textures
                babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, babylonScene);    // Ambient
                babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, babylonScene);    // Diffuse
                babylonMaterial.specularTexture = ExportTexture(stdMat, 2, babylonScene);   // Specular
                babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, babylonScene);   // Emissive
                babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, babylonScene);    // Opacity
                babylonMaterial.bumpTexture = ExportTexture(stdMat, 8, babylonScene);       // Bump
                babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, babylonScene); // Reflection

                // Constraints
                if (babylonMaterial.diffuseTexture != null)
                {
                    babylonMaterial.emissive = new [] { 1.0f, 1.0f, 1.0f };
                }

                if (babylonMaterial.emissiveTexture != null)
                {
                    babylonMaterial.emissive = new float[]{0, 0, 0};
                }

                if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null &&
                    babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name &&
                    babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB)
                {
                    // This is a alpha testing purpose
                    babylonMaterial.opacityTexture = null;
                    babylonMaterial.diffuseTexture.hasAlpha = true;
                    RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", true);
                    RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", true);
                }
            }

            babylonScene.MaterialsList.Add(babylonMaterial);
        }
        private void ExportSkin(IIGameSkin skin, BabylonScene babylonScene)
        {
            var babylonSkeleton = new BabylonSkeleton { id = skins.IndexOf(skin) };
            babylonSkeleton.name = "skeleton #" + babylonSkeleton.id;

            RaiseMessage(babylonSkeleton.name, 1);

            var skinIndex = skins.IndexOf(skin);

            var bones = new List<BabylonBone>();
            var gameBones = new List<IIGameNode>();
            var boneIds = new List<int>();
            var bindPoseInfos = new List<BonePoseInfo>();
            for(int i = 0; i < skin.TotalSkinBoneCount; ++i)
            {
                bones.Add(null);
                gameBones.Add(null);
                boneIds.Add(-1);
                bindPoseInfos.Add(null);
            }
            for (var index = 0; index < skin.TotalSkinBoneCount; index++)
            {
                var gameBone = skin.GetIGameBone(index, false);

                var sortedIndex = skinSortedBones[skin].IndexOf(gameBone.NodeID);

                gameBones[sortedIndex] = (gameBone);
                boneIds[sortedIndex] =(gameBone.NodeID);
                bones[sortedIndex]=(new BabylonBone { index = sortedIndex, name = gameBone.Name });

                var boneInitMatrix = gameBone.GetObjectTM(0);
                bindPoseInfos[sortedIndex] = (new BonePoseInfo { AbsoluteTransform = boneInitMatrix });
            }

            // fix hierarchy an generate animation keys
            var exportNonOptimizedAnimations = Loader.Core.RootNode.GetBoolProperty("babylonjs_exportnonoptimizedanimations");

            for (var index = 0; index < skin.TotalSkinBoneCount; index++)
            {
                var gameBone = gameBones[index];
                var parent = gameBone.NodeParent;
                var babBone = bones[index];
                if (parent != null)
                {
                    babBone.parentBoneIndex = boneIds.IndexOf(parent.NodeID);
                }

                if (babBone.parentBoneIndex == -1)
                {
                    bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform;
                }
                else
                {
                    var parentBindPoseInfos = bindPoseInfos[babBone.parentBoneIndex];
                    bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform.Multiply(parentBindPoseInfos.AbsoluteTransform.Inverse);
                }

                babBone.matrix = bindPoseInfos[index].LocalTransform.ToArray();

                var babylonAnimation = new BabylonAnimation
                {
                    name = gameBone.Name + "Animation",
                    property = "_matrix",
                    dataType = (int)BabylonAnimation.DataType.Matrix,
                    loopBehavior = (int)BabylonAnimation.LoopBehavior.Cycle,
                    framePerSecond = Loader.Global.FrameRate
                };

                var start = Loader.Core.AnimRange.Start;
                var end = Loader.Core.AnimRange.End;

                float[] previous = null;
                var keys = new List<BabylonAnimationKey>();
                for (var key = start; key <= end; key += Ticks)
                {
                    var objectTM = gameBone.GetObjectTM(key);
                    var parentNode = gameBone.NodeParent;
                    IGMatrix mat;
                    if (parentNode == null || babBone.parentBoneIndex == -1)
                    {
                        mat = objectTM;
                    }
                    else
                    {
                        mat = objectTM.Multiply(parentNode.GetObjectTM(key).Inverse);
                    }

                    var current = mat.ToArray();
                    if (key == start || key == end || exportNonOptimizedAnimations || !(previous.IsEqualTo(current)))
                    {
                        keys.Add(new BabylonAnimationKey
                        {
                            frame = key / Ticks,
                            values = current
                        });
                    }

                    previous = current;
                }

                babylonAnimation.keys = keys.ToArray();
                babBone.animation = babylonAnimation;
            }

            babylonSkeleton.needInitialSkinMatrix = true;
            babylonSkeleton.bones = bones.ToArray();

            babylonScene.SkeletonsList.Add(babylonSkeleton);
        }
        private void ExportMaterial(IIGameMaterial materialNode, BabylonScene babylonScene)
        {
            var name = materialNode.MaterialName;
            var id = materialNode.MaxMaterial.GetGuid().ToString();

            RaiseMessage(name, 1);

            if (materialNode.SubMaterialCount > 0)
            {
                var babylonMultimaterial = new BabylonMultiMaterial { name = name, id = id };

                var guids = new List<string>();

                for (var index = 0; index < materialNode.SubMaterialCount; index++)
                {
                    var subMat = materialNode.GetSubMaterial(index);

                    if (subMat != null)
                    {
                        guids.Add(subMat.MaxMaterial.GetGuid().ToString());

                        if (!referencedMaterials.Contains(subMat))
                        {
                            referencedMaterials.Add(subMat);
                            ExportMaterial(subMat, babylonScene);
                        }
                    }
                    else
                    {
                        guids.Add(Guid.Empty.ToString());
                    }
                }

                babylonMultimaterial.materials = guids.ToArray();

                babylonScene.MultiMaterialsList.Add(babylonMultimaterial);
                return;
            }

            var babylonMaterial = new BabylonStandardMaterial
            {
                name = name,
                id = id,
                ambient = materialNode.MaxMaterial.GetAmbient(0, false).ToArray(),
                diffuse = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(),
                specular = materialNode.MaxMaterial.GetSpecular(0, false).Scale(materialNode.MaxMaterial.GetShinStr(0, false)),
                specularPower = materialNode.MaxMaterial.GetShininess(0, false) * 256,
                emissive =
                    materialNode.MaxMaterial.GetSelfIllumColorOn(0, false)
                        ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray()
                        : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)),
                alpha = 1.0f - materialNode.MaxMaterial.GetXParency(0, false)
            };


            var stdMat = materialNode.MaxMaterial.GetParamBlock(0).Owner as IStdMat2;

            if (stdMat != null)
            {
                babylonMaterial.backFaceCulling = !stdMat.TwoSided;
                babylonMaterial.wireframe = stdMat.Wire;

                // Textures
                BabylonFresnelParameters fresnelParameters;

                babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, out fresnelParameters, babylonScene);                // Ambient
                babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, out fresnelParameters, babylonScene);                // Diffuse
                if (fresnelParameters != null)
                {
                    babylonMaterial.diffuseFresnelParameters = fresnelParameters;
                }

                babylonMaterial.specularTexture = ExportTexture(stdMat, 2, out fresnelParameters, babylonScene);               // Specular
                babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, out fresnelParameters, babylonScene);               // Emissive
                if (fresnelParameters != null)
                {
                    babylonMaterial.emissiveFresnelParameters = fresnelParameters;
                    if (babylonMaterial.emissive[0] == 0 &&
                        babylonMaterial.emissive[1] == 0 &&
                        babylonMaterial.emissive[2] == 0 &&
                        babylonMaterial.emissiveTexture == null)
                    {
                        babylonMaterial.emissive = new float[] { 1, 1, 1 };
                    }
                }

                babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, out fresnelParameters, babylonScene, false, true);   // Opacity
                if (fresnelParameters != null)
                {
                    babylonMaterial.opacityFresnelParameters = fresnelParameters;
                    if (babylonMaterial.alpha == 1 &&
                         babylonMaterial.opacityTexture == null)
                    {
                        babylonMaterial.alpha = 0;
                    }
                }

                babylonMaterial.bumpTexture = ExportTexture(stdMat, 8, out fresnelParameters, babylonScene);                   // Bump
                babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, out fresnelParameters, babylonScene, true);       // Reflection
                if (fresnelParameters != null)
                {
                    if (babylonMaterial.reflectionTexture == null)
                    {
                        RaiseWarning("Fallout cannot be used with reflection channel without a texture", 2);
                    }
                    else
                    {
                        babylonMaterial.reflectionFresnelParameters = fresnelParameters;
                    }
                }

                // Constraints
                if (babylonMaterial.diffuseTexture != null)
                {
                    babylonMaterial.diffuse = new[] { 1.0f, 1.0f, 1.0f };
                }

                if (babylonMaterial.emissiveTexture != null)
                {
                    babylonMaterial.emissive = new float[] { 0, 0, 0 };
                }

                if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null &&
                    babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name &&
                    babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB)
                {
                    // This is a alpha testing purpose
                    babylonMaterial.opacityTexture = null;
                    babylonMaterial.diffuseTexture.hasAlpha = true;
                    RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", 2);
                    RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", 2);
                }
            }

            babylonScene.MaterialsList.Add(babylonMaterial);
        }
Пример #16
0
        public async Task ExportAsync(string outputFile, bool generateManifest, Form callerForm)
        {
            IsCancelled = false;
            RaiseMessage("Exportation started", Color.Blue);
            ReportProgressChanged(0);
            var babylonScene = new BabylonScene(Path.GetDirectoryName(outputFile));
            var maxScene = Loader.Core.RootNode;
            alreadyExportedTextures.Clear();

            if (!Directory.Exists(babylonScene.OutputPath))
            {
                RaiseError("Exportation stopped: Output folder does not exist");
                ReportProgressChanged(100);
                return;
            }

            var watch = new Stopwatch();
            watch.Start();

            // Save scene
            RaiseMessage("Saving 3ds max file");

            if (AutoSave3dsMaxFile)
            {
                var forceSave = Loader.Core.FileSave;

                if (callerForm != null)
                {
                    callerForm.BringToFront();
                }
            }

            // Global
            babylonScene.autoClear = true;
            babylonScene.clearColor = Loader.Core.GetBackGround(0, Tools.Forever).ToArray();
            babylonScene.ambientColor = Loader.Core.GetAmbient(0, Tools.Forever).ToArray();

            babylonScene.gravity = maxScene.GetVector3Property("babylonjs_gravity");
            exportQuaternionsInsteadOfEulers = maxScene.GetBoolProperty("babylonjs_exportquaternions", 1);

            // Cameras
            BabylonCamera mainCamera = null;

            RaiseMessage("Exporting cameras");
            foreach (var cameraNode in maxScene.NodesListBySuperClass(SClass_ID.Camera))
            {
                ExportCamera(cameraNode, babylonScene);

                if (mainCamera == null && babylonScene.CamerasList.Count > 0)
                {
                    mainCamera = babylonScene.CamerasList[0];
                    babylonScene.activeCameraID = mainCamera.id;
                    RaiseMessage("Active camera set to " + mainCamera.name, Color.Green, 1, true);
                }
            }

            if (mainCamera == null)
            {
                RaiseWarning("No camera defined", 1);
            }
            else
            {
                RaiseMessage(string.Format("Total: {0}", babylonScene.CamerasList.Count), Color.Gray, 1);
            }

            // Fog
            for (var index = 0; index < Loader.Core.NumAtmospheric; index++)
            {
                var atmospheric = Loader.Core.GetAtmospheric(index);

                if (atmospheric.Active(0) && atmospheric.ClassName == "Fog")
                {
                    var fog = atmospheric as IStdFog;

                    if (fog != null)
                    {
                        RaiseMessage("Exporting fog");

                        babylonScene.fogColor = fog.GetColor(0).ToArray();
                        babylonScene.fogDensity = fog.GetDensity(0);
                        babylonScene.fogMode = fog.GetType_ == 0 ? 3 : 1;

                        if (mainCamera != null)
                        {
                            babylonScene.fogStart = mainCamera.minZ*fog.GetNear(0);
                            babylonScene.fogEnd = mainCamera.maxZ*fog.GetFar(0);
                        }
                    }
                }
            }

            // Meshes
            ReportProgressChanged(10);
            RaiseMessage("Exporting meshes");
            var meshes = maxScene.NodesListBySuperClasses(new[] { SClass_ID.Geomobject, SClass_ID.Helper });
            var progressionStep = 80.0f / meshes.Count();
            var progression = 10.0f;
            foreach (var meshNode in meshes)
            {
                Tools.PreparePipeline(meshNode, true);
                ExportMesh(meshNode, babylonScene);
                Tools.PreparePipeline(meshNode, false);

                progression += progressionStep;
                ReportProgressChanged((int)progression);

                CheckCancelled();
            }
            RaiseMessage(string.Format("Total: {0}", babylonScene.MeshesList.Count), Color.Gray, 1);

            // Materials
            RaiseMessage("Exporting materials");
            var matsToExport = referencedMaterials.ToArray(); // Snapshot because multimaterials can export new materials
            foreach (var mat in matsToExport)
            {
                ExportMaterial(mat, babylonScene);
                CheckCancelled();
            }
            RaiseMessage(string.Format("Total: {0}", babylonScene.MaterialsList.Count + babylonScene.MultiMaterialsList.Count), Color.Gray, 1);

            // Lights
            RaiseMessage("Exporting lights");
            foreach (var lightNode in maxScene.NodesListBySuperClass(SClass_ID.Light))
            {
                ExportLight(lightNode, babylonScene);
                CheckCancelled();
            }

            if (babylonScene.LightsList.Count == 0)
            {
                RaiseWarning("No light defined", 1);
                RaiseWarning("A default hemispheric light was added for your convenience", 1);
                ExportDefaultLight(babylonScene);
            }
            else
            {
                RaiseMessage(string.Format("Total: {0}", babylonScene.LightsList.Count), Color.Gray, 1);
            }

            // Skeletons
            if (skins.Count > 0)
            {
                RaiseMessage("Exporting skeletons");
                foreach (var skin in skins)
                {
                    ExportSkin(skin, babylonScene);
                    skin.Dispose();
                }
            }

            // Output
            RaiseMessage("Saving to output file");
            babylonScene.Prepare(false);
            var jsonSerializer = JsonSerializer.Create();
            var sb = new StringBuilder();
            var sw = new StringWriter(sb, CultureInfo.InvariantCulture);

            await Task.Run(() =>
            {
                using (var jsonWriter = new JsonTextWriterOptimized(sw))
                {
                    jsonWriter.Formatting = Formatting.None;
                    jsonSerializer.Serialize(jsonWriter, babylonScene);
                }
                File.WriteAllText(outputFile, sb.ToString());

                if (generateManifest)
                {
                    File.WriteAllText(outputFile + ".manifest",
                        "{\r\n\"version\" : 1,\r\n\"enableSceneOffline\" : true,\r\n\"enableTexturesOffline\" : true\r\n}");
                }
            });

            ReportProgressChanged(100);
            watch.Stop();
            RaiseMessage(string.Format("Exportation done in {0:0.00}s", watch.ElapsedMilliseconds / 1000.0), Color.Blue);
        }
Пример #17
0
        private void ExportLight(IIGameScene scene, IIGameNode lightNode, BabylonScene babylonScene)
        {
            if (lightNode.MaxNode.GetBoolProperty("babylonjs_noexport"))
            {
                return;
            }

            var gameLight = lightNode.IGameObject.AsGameLight();
            var initialized = gameLight.InitializeData;
            var babylonLight = new BabylonLight();

            RaiseMessage(lightNode.Name, 1);
            babylonLight.name = lightNode.Name;
            babylonLight.id = lightNode.MaxNode.GetGuid().ToString();
            if (lightNode.NodeParent != null)
            {
                babylonLight.parentId = GetParentID(lightNode.NodeParent, babylonScene, scene);
            }

            // Type

            var maxLight = (lightNode.MaxNode.ObjectRef as ILightObject);
            var lightState = Loader.Global.LightState.Create();
            maxLight.EvalLightState(0, Tools.Forever, lightState);

            switch (lightState.Type)
            {
                case LightType.OmniLgt:
                    babylonLight.type = 0;
                    break;
                case LightType.SpotLgt:
                    babylonLight.type = 2;
                    babylonLight.angle = (float)(maxLight.GetFallsize(0, Tools.Forever) * Math.PI / 180.0f);
                    babylonLight.exponent = 1;
                    break;
                case LightType.DirectLgt:
                    babylonLight.type = 1;
                    break;
                case LightType.AmbientLgt:
                    babylonLight.type = 3;
                    babylonLight.groundColor = new float[] { 0, 0, 0 };
                    break;
            }


            // Shadows 
            if (maxLight.ShadowMethod == 1)
            {
                if (lightState.Type == LightType.DirectLgt || lightState.Type == LightType.SpotLgt)
                {
                    ExportShadowGenerator(lightNode.MaxNode, babylonScene);
                }
                else
                {
                    RaiseWarning("Shadows maps are only supported for directional and spot lights", 2);
                }
            }

            // Position
            var wm = lightNode.GetObjectTM(0);
            if (lightNode.NodeParent != null)
            {
                var parentWorld = lightNode.NodeParent.GetObjectTM(0);
                wm.MultiplyBy(parentWorld.Inverse);
            }
            var position = wm.Translation;
            babylonLight.position = new[] { position.X, position.Y, position.Z };

            // Direction
            var target = gameLight.LightTarget;
            if (target != null)
            {
                var targetWm = target.GetObjectTM(0);
                var targetPosition = targetWm.Translation;

                var direction = targetPosition.Subtract(position).Normalize;
                babylonLight.direction = new[] { direction.X, direction.Y, direction.Z };
            }
            else
            {
                var vDir = Loader.Global.Point3.Create(0, -1, 0);
                vDir = wm.ExtractMatrix3().VectorTransform(vDir).Normalize;
                babylonLight.direction = new[] { vDir.X, vDir.Y, vDir.Z };
            }

            var maxScene = Loader.Core.RootNode;

            // Exclusion
            var inclusion = maxLight.ExclList.TestFlag(1); //NT_INCLUDE 
            var checkExclusionList = maxLight.ExclList.TestFlag(2); //NT_AFFECT_ILLUM

            if (checkExclusionList)
            {
                var excllist = new List<string>();
                var incllist = new List<string>();

                foreach (var meshNode in maxScene.NodesListBySuperClass(SClass_ID.Geomobject))
                {
                    if (meshNode.CastShadows == 1)
                    {
                        var inList = maxLight.ExclList.FindNode(meshNode) != -1;

                        if (inList)
                        {
                            if (inclusion)
                            {
                                incllist.Add(meshNode.GetGuid().ToString());
                            }
                            else
                            {
                                excllist.Add(meshNode.GetGuid().ToString());
                            }
                        }
                    }
                }

                babylonLight.includedOnlyMeshesIds = incllist.ToArray();
                babylonLight.excludedMeshesIds = excllist.ToArray();
            }

            // Other fields 
            babylonLight.intensity = maxLight.GetIntensity(0, Tools.Forever);


            babylonLight.diffuse = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 };
            babylonLight.specular = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 };


            if (maxLight.UseAtten)
            {
                babylonLight.range = maxLight.GetAtten(0, 1, Tools.Forever);
            }


            // Animations
            var animations = new List<BabylonAnimation>();

            ExportVector3Animation("position", animations, key =>
            {
                var mat = lightNode.GetObjectTM(key);
                if (lightNode.NodeParent != null)
                {
                    var parentWorld = lightNode.NodeParent.GetObjectTM(key);
                    mat.MultiplyBy(parentWorld.Inverse);
                }
                var pos = mat.Translation;
                return new[] { pos.X, pos.Y, pos.Z };
            });

            ExportVector3Animation("direction", animations, key =>
            {
                var wmLight = lightNode.GetObjectTM(key);
                if (lightNode.NodeParent != null)
                {
                    var parentWorld = lightNode.NodeParent.GetObjectTM(key);
                    wmLight.MultiplyBy(parentWorld.Inverse);
                }
                var positionLight = wmLight.Translation;
                var lightTarget = gameLight.LightTarget;
                if (lightTarget != null)
                {
                    var targetWm = lightTarget.GetObjectTM(key);
                    var targetPosition = targetWm.Translation;

                    var direction = targetPosition.Subtract(positionLight).Normalize;
                    return new[] { direction.X, direction.Y, direction.Z };
                }
                else
                {
                    var vDir = Loader.Global.Point3.Create(0, -1, 0);
                    vDir = wmLight.ExtractMatrix3().VectorTransform(vDir).Normalize;
                    return new[] { vDir.X, vDir.Y, vDir.Z };
                }
            });

            ExportFloatAnimation("intensity", animations, key => new[] { maxLight.GetIntensity(key, Tools.Forever) });

            babylonLight.animations = animations.ToArray();

            if (lightNode.MaxNode.GetBoolProperty("babylonjs_autoanimate"))
            {
                babylonLight.autoAnimate = true;
                babylonLight.autoAnimateFrom = (int)lightNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_from");
                babylonLight.autoAnimateTo = (int)lightNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_to");
                babylonLight.autoAnimateLoop = lightNode.MaxNode.GetBoolProperty("babylonjs_autoanimateloop");
            }

            babylonScene.LightsList.Add(babylonLight);
        }
Пример #18
0
        private BabylonTexture ExportTexture(IStdMat2 stdMat, int index, out BabylonFresnelParameters fresnelParameters, BabylonScene babylonScene, bool allowCube = false, bool forceAlpha = false)
        {
            fresnelParameters = null;

            if (!stdMat.MapEnabled(index))
            {
                return null;
            }
            var babylonTexture = new BabylonTexture();

            var texMap = stdMat.GetSubTexmap(index);

            // Fallout
            if (texMap.ClassName == "Falloff") // This is the only way I found to detect it. This is crappy but it works
            {
                fresnelParameters = new BabylonFresnelParameters();

                var paramBlock = texMap.GetParamBlock(0);
                var color1 = paramBlock.GetColor(0, 0, 0);
                var color2 = paramBlock.GetColor(4, 0, 0);

                fresnelParameters.isEnabled = true;
                fresnelParameters.leftColor = color2.ToArray();
                fresnelParameters.rightColor = color1.ToArray();

                if (paramBlock.GetInt(8, 0, 0) == 2)
                {
                    fresnelParameters.power = paramBlock.GetFloat(12, 0, 0);
                }
                else
                {
                    fresnelParameters.power = 1;
                }
                var texMap1 = paramBlock.GetTexmap(2, 0, 0);
                var texMap1On = paramBlock.GetInt(3, 0, 0);

                var texMap2 = paramBlock.GetTexmap(6, 0, 0);
                var texMap2On = paramBlock.GetInt(7, 0, 0);

                if (texMap1 != null && texMap1On != 0)
                {
                    texMap = texMap1;
                    fresnelParameters.rightColor = new float[] { 1, 1, 1 };

                    if (texMap2 != null && texMap2On != 0)
                    {
                        RaiseWarning(string.Format("You cannot specify two textures for falloff. Only one is supported"), 2);
                    }
                }
                else if (texMap2 != null && texMap2On != 0)
                {
                    fresnelParameters.leftColor = new float[] { 1, 1, 1 };
                    texMap = texMap2;
                }
                else
                {
                    return null;
                }
            }

            // Bitmap
            var texture = texMap.GetParamBlock(0).Owner as IBitmapTex;

            if (texture == null)
            {
                return null;
            }

            if (forceAlpha)
            {
                babylonTexture.hasAlpha = true;
                babylonTexture.getAlphaFromRGB = (texture.AlphaSource == 2) || (texture.AlphaSource == 3);
            }
            else
            {
                babylonTexture.hasAlpha = (texture.AlphaSource != 3);
                babylonTexture.getAlphaFromRGB = (texture.AlphaSource == 2);
            }


            babylonTexture.level = stdMat.GetTexmapAmt(index, 0);

            var uvGen = texture.UVGen;

            switch (uvGen.GetCoordMapping(0))
            {
                case 1: //MAP_SPHERICAL
                    babylonTexture.coordinatesMode = 1;
                    break;
                case 2: //MAP_PLANAR
                    babylonTexture.coordinatesMode = 2;
                    break;
                default:
                    babylonTexture.coordinatesMode = 0;
                    break;
            }

            babylonTexture.coordinatesIndex = uvGen.MapChannel - 1;
            if (uvGen.MapChannel > 2)
            {
                RaiseWarning(string.Format("Unsupported map channel, Only channel 1 and 2 are supported."), 2);
            }

            babylonTexture.uOffset = uvGen.GetUOffs(0);
            babylonTexture.vOffset = uvGen.GetVOffs(0);

            babylonTexture.uScale = uvGen.GetUScl(0);
            babylonTexture.vScale = uvGen.GetVScl(0);

            if (Path.GetExtension(texture.MapName).ToLower() == ".dds")
            {
                babylonTexture.vScale *= -1; // Need to invert Y-axis for DDS texture
            }

            babylonTexture.uAng = uvGen.GetUAng(0);
            babylonTexture.vAng = uvGen.GetVAng(0);
            babylonTexture.wAng = uvGen.GetWAng(0);

            babylonTexture.wrapU = 0; // CLAMP
            if ((uvGen.TextureTiling & 1) != 0) // WRAP
            {
                babylonTexture.wrapU = 1;
            }
            else if ((uvGen.TextureTiling & 4) != 0) // MIRROR
            {
                babylonTexture.wrapU = 2;
            }

            babylonTexture.wrapV = 0; // CLAMP
            if ((uvGen.TextureTiling & 2) != 0) // WRAP
            {
                babylonTexture.wrapV = 1;
            }
            else if ((uvGen.TextureTiling & 8) != 0) // MIRROR
            {
                babylonTexture.wrapV = 2;
            }

            babylonTexture.name = Path.GetFileName(texture.MapName);

            // Animations
            var animations = new List<BabylonAnimation>();
            ExportFloatAnimation("uOffset", animations, key => new[] { uvGen.GetUOffs(key) });
            ExportFloatAnimation("vOffset", animations, key => new[] { uvGen.GetVOffs(key) });
            ExportFloatAnimation("uScale", animations, key => new[] { uvGen.GetUScl(key) });
            ExportFloatAnimation("vScale", animations, key => new[] { uvGen.GetVScl(key) });
            ExportFloatAnimation("uAng", animations, key => new[] { uvGen.GetUAng(key) });
            ExportFloatAnimation("vAng", animations, key => new[] { uvGen.GetVAng(key) });
            ExportFloatAnimation("wAng", animations, key => new[] { uvGen.GetWAng(key) });

            babylonTexture.animations = animations.ToArray();
            var absolutePath = texture.Map.FullFilePath;
            // Copy texture to output
            try
            {
                if (File.Exists(absolutePath))
                {
                    babylonTexture.isCube = IsTextureCube(absolutePath);
                    if (CopyTexturesToOutput)
                    {
                        File.Copy(absolutePath, Path.Combine(babylonScene.OutputPath, babylonTexture.name), true);
                    }
                }
                else
                {
                    RaiseWarning(string.Format("Texture {0} not found.", babylonTexture.name), 2);
                }

            }
            catch
            {
                // silently fails
            }

            if (babylonTexture.isCube && !allowCube)
            {
                RaiseWarning(string.Format("Cube texture are only supported for reflection channel"), 2);
            }

            return babylonTexture;
        }
Пример #19
0
        private void ExportMesh(IIGameScene scene, IIGameNode meshNode, BabylonScene babylonScene)
        {
            if (meshNode.MaxNode.IsInstance())
            {
                return;
            }

            if (meshNode.MaxNode.GetBoolProperty("babylonjs_noexport"))
            {
                return;
            }

            if (!ExportHiddenObjects && meshNode.MaxNode.IsHidden(NodeHideFlags.None, false))
            {
                return;
            }

            var gameMesh = meshNode.IGameObject.AsGameMesh();
            bool initialized = gameMesh.InitializeData; //needed, the property is in fact a method initializing the exporter that has wrongly been auto 
            // translated into a property because it has no parameters

            var babylonMesh = new BabylonMesh { name = meshNode.Name, id = meshNode.MaxNode.GetGuid().ToString() };

            if (meshNode.NodeParent != null)
            {
                babylonMesh.parentId = GetParentID(meshNode.NodeParent, babylonScene, scene);
            }

            // Sounds
            var soundName = meshNode.MaxNode.GetStringProperty("babylonjs_sound_filename", "");
            if (!string.IsNullOrEmpty(soundName))
            {
                var filename = Path.GetFileName(soundName);

                var meshSound = new BabylonSound
                {
                    name = filename,
                    autoplay = meshNode.MaxNode.GetBoolProperty("babylonjs_sound_autoplay", 1),
                    loop = meshNode.MaxNode.GetBoolProperty("babylonjs_sound_loop", 1),
                    volume = meshNode.MaxNode.GetFloatProperty("babylonjs_sound_volume", 1.0f),
                    playbackRate = meshNode.MaxNode.GetFloatProperty("babylonjs_sound_playbackrate", 1.0f),
                    connectedMeshId = babylonMesh.id,
                    isDirectional = false,
                    spatialSound = false,
                    distanceModel = meshNode.MaxNode.GetStringProperty("babylonjs_sound_distancemodel", "linear"),
                    maxDistance = meshNode.MaxNode.GetFloatProperty("babylonjs_sound_maxdistance", 100f),
                    rolloffFactor = meshNode.MaxNode.GetFloatProperty("babylonjs_sound_rolloff", 1.0f),
                    refDistance = meshNode.MaxNode.GetFloatProperty("babylonjs_sound_refdistance", 1.0f),
                };

                var isDirectional = meshNode.MaxNode.GetBoolProperty("babylonjs_sound_directional", 0);
                
                if (isDirectional)
                {
                    meshSound.isDirectional = true;
                    meshSound.coneInnerAngle = meshNode.MaxNode.GetFloatProperty("babylonjs_sound_coneinnerangle", 360f);
                    meshSound.coneOuterAngle = meshNode.MaxNode.GetFloatProperty("babylonjs_sound_coneouterangle", 360f);
                    meshSound.coneOuterGain = meshNode.MaxNode.GetFloatProperty("babylonjs_sound_coneoutergain", 1.0f);
                }

                babylonScene.SoundsList.Add(meshSound);

                try
                {
                    File.Copy(soundName, Path.Combine(babylonScene.OutputPath, filename), true);
                }
                catch
                {
                }
            }

            // Misc.
            babylonMesh.isVisible = meshNode.MaxNode.Renderable == 1;
            babylonMesh.pickable = meshNode.MaxNode.GetBoolProperty("babylonjs_checkpickable");
            babylonMesh.receiveShadows = meshNode.MaxNode.RcvShadows == 1;
            babylonMesh.showBoundingBox = meshNode.MaxNode.GetBoolProperty("babylonjs_showboundingbox");
            babylonMesh.showSubMeshesBoundingBox = meshNode.MaxNode.GetBoolProperty("babylonjs_showsubmeshesboundingbox");
            babylonMesh.applyFog = meshNode.MaxNode.ApplyAtmospherics == 1;
            babylonMesh.alphaIndex = (int)meshNode.MaxNode.GetFloatProperty("babylonjs_alphaindex", 1000);

            // Actions
            babylonMesh.actions = ExportNodeAction(meshNode);

            // Collisions
            babylonMesh.checkCollisions = meshNode.MaxNode.GetBoolProperty("babylonjs_checkcollisions");

            var isSkinned = gameMesh.IsObjectSkinned;
            var skin = gameMesh.IGameSkin;
            var unskinnedMesh = gameMesh;
            IGMatrix skinInitPoseMatrix = Loader.Global.GMatrix.Create(Loader.Global.Matrix3.Create(true));
            List<int> boneIds = null;
            if (isSkinned)
            {
                bonesCount = skin.TotalSkinBoneCount;
                skins.Add(skin);

                skinnedNodes.Add(meshNode);
                babylonMesh.skeletonId = skins.IndexOf(skin);
                skin.GetInitSkinTM(skinInitPoseMatrix);
                boneIds = SortBones(skin);
                skinSortedBones[skin] = boneIds;
            }

            // Position / rotation / scaling
            var localTM = meshNode.GetObjectTM(0);
            if (meshNode.NodeParent != null)
            {
                var parentWorld = meshNode.NodeParent.GetObjectTM(0);
                localTM.MultiplyBy(parentWorld.Inverse);
            }

            var meshTrans = localTM.Translation;
            var meshRotation = localTM.Rotation;
            var meshScale = localTM.Scaling;
            var exportQuaternions = Loader.Core.RootNode.GetBoolProperty("babylonjs_exportquaternions");

            babylonMesh.position = new[] { meshTrans.X, meshTrans.Y, meshTrans.Z };

            if (exportQuaternions)
            {
                babylonMesh.rotationQuaternion = new[] { meshRotation.X, meshRotation.Y, meshRotation.Z, -meshRotation.W };
            }
            else
            {
                RotationToEulerAngles(babylonMesh, meshRotation);
            }

            babylonMesh.scaling = new[] { meshScale.X, meshScale.Y, meshScale.Z };

            // Mesh
            RaiseMessage(meshNode.Name, 1);

            if (unskinnedMesh.IGameType == Autodesk.Max.IGameObject.ObjectTypes.Mesh && unskinnedMesh.MaxMesh != null)
            {
                if (unskinnedMesh.NumberOfFaces < 1)
                {
                    RaiseError(string.Format("Mesh {0} has no face", babylonMesh.name), 2);
                }

                if (unskinnedMesh.NumberOfVerts < 3)
                {
                    RaiseError(string.Format("Mesh {0} has not enough vertices", babylonMesh.name), 2);
                }

                if (unskinnedMesh.NumberOfVerts >= 65536)
                {
                    RaiseWarning(string.Format("Mesh {0} has tmore than 65536 vertices which means that it will require specific WebGL extension to be rendered. This may impact portability of your scene on low end devices.", babylonMesh.name), 2);
                }

                // Physics
                var impostorText = meshNode.MaxNode.GetStringProperty("babylonjs_impostor", "None");

                if (impostorText != "None")
                {
                    switch (impostorText)
                    {
                        case "Sphere":
                            babylonMesh.physicsImpostor = 1;
                            break;
                        case "Box":
                            babylonMesh.physicsImpostor = 2;
                            break;
                        case "Plane":
                            babylonMesh.physicsImpostor = 3;
                            break;
                        default:
                            babylonMesh.physicsImpostor = 0;
                            break;
                    }

                    babylonMesh.physicsMass = meshNode.MaxNode.GetFloatProperty("babylonjs_mass");
                    babylonMesh.physicsFriction = meshNode.MaxNode.GetFloatProperty("babylonjs_friction", 0.2f);
                    babylonMesh.physicsRestitution = meshNode.MaxNode.GetFloatProperty("babylonjs_restitution", 0.2f);
                }

                // Material
                var mtl = meshNode.NodeMaterial;
                var multiMatsCount = 1;

                if (mtl != null)
                {
                    babylonMesh.materialId = mtl.MaxMaterial.GetGuid().ToString();

                    if (!referencedMaterials.Contains(mtl))
                    {
                        referencedMaterials.Add(mtl);
                    }

                    multiMatsCount = Math.Max(mtl.SubMaterialCount, 1);
                }

                babylonMesh.visibility = meshNode.MaxNode.GetVisibility(0, Tools.Forever);

                var vertices = new List<GlobalVertex>();
                var indices = new List<int>();
                var mappingChannels = unskinnedMesh.ActiveMapChannelNum;
                bool hasUV = false;
                bool hasUV2 = false;
                for (int i = 0; i < mappingChannels.Count; ++i)
                {
                    var indexer = new IntPtr(i);
                    var channelNum = mappingChannels[indexer];
                    if (channelNum == 1)
                    {
                        hasUV = true;
                    }
                    else if (channelNum == 2)
                    {
                        hasUV2 = true;
                    }
                }
                var hasColor = unskinnedMesh.NumberOfColorVerts > 0;
                var hasAlpha = unskinnedMesh.GetNumberOfMapVerts(-2) > 0;

                var optimizeVertices = meshNode.MaxNode.GetBoolProperty("babylonjs_optimizevertices");

                // Compute normals
                List<GlobalVertex>[] verticesAlreadyExported = null;

                if (optimizeVertices)
                {
                    verticesAlreadyExported = new List<GlobalVertex>[unskinnedMesh.NumberOfVerts];
                }

                var subMeshes = new List<BabylonSubMesh>();
                var indexStart = 0;


                for (int i = 0; i < multiMatsCount; ++i)
                {
                    int materialId = meshNode.NodeMaterial == null ? 0 : meshNode.NodeMaterial.GetMaterialID(i);
                    var indexCount = 0;
                    var minVertexIndex = int.MaxValue;
                    var maxVertexIndex = int.MinValue;
                    var subMesh = new BabylonSubMesh { indexStart = indexStart, materialIndex = i };

                    if (multiMatsCount == 1)
                    {
                        for (int j = 0; j < unskinnedMesh.NumberOfFaces; ++j)
                        {
                            var face = unskinnedMesh.GetFace(j);
                            ExtractFace(skin, unskinnedMesh, vertices, indices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, ref indexCount, ref minVertexIndex, ref maxVertexIndex, face, boneIds);
                        }
                    }
                    else
                    {
                        ITab<IFaceEx> materialFaces = unskinnedMesh.GetFacesFromMatID(materialId);
                        for (int j = 0; j < materialFaces.Count; ++j)
                        {
                            var faceIndexer = new IntPtr(j);
                            var face = materialFaces[faceIndexer];

                            Marshal.FreeHGlobal(faceIndexer);
                            ExtractFace(skin, unskinnedMesh, vertices, indices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, ref indexCount, ref minVertexIndex, ref maxVertexIndex, face, boneIds);
                        }
                    }

                    if (indexCount != 0)
                    {

                        subMesh.indexCount = indexCount;
                        subMesh.verticesStart = minVertexIndex;
                        subMesh.verticesCount = maxVertexIndex - minVertexIndex + 1;

                        indexStart += indexCount;

                        subMeshes.Add(subMesh);
                    }
                }

                if (vertices.Count >= 65536)
                {
                    RaiseWarning(string.Format("Mesh {0} has {1} vertices. This may prevent your scene to work on low end devices where 32 bits indice are not supported", babylonMesh.name, vertices.Count), 2);

                    if (!optimizeVertices)
                    {
                        RaiseError("You can try to optimize your object using [Try to optimize vertices] option", 2);
                    }
                }

                RaiseMessage(string.Format("{0} vertices, {1} faces", vertices.Count, indices.Count / 3), 2);

                // Buffers
                babylonMesh.positions = vertices.SelectMany(v => new[] { v.Position.X, v.Position.Y, v.Position.Z }).ToArray();
                babylonMesh.normals = vertices.SelectMany(v => new[] { v.Normal.X, v.Normal.Y, v.Normal.Z }).ToArray();
                if (hasUV)
                {
                    babylonMesh.uvs = vertices.SelectMany(v => new[] { v.UV.X, 1 - v.UV.Y }).ToArray();
                }
                if (hasUV2)
                {
                    babylonMesh.uvs2 = vertices.SelectMany(v => new[] { v.UV2.X, 1 - v.UV2.Y }).ToArray();
                }

                if (skin != null)
                {
                    babylonMesh.matricesWeights = vertices.SelectMany(v => v.Weights.ToArray()).ToArray();
                    babylonMesh.matricesIndices = vertices.Select(v => v.BonesIndices).ToArray();
                }

                if (hasColor)
                {
                    babylonMesh.colors = vertices.SelectMany(v => v.Color.ToArray()).ToArray();
                    babylonMesh.hasVertexAlpha = hasAlpha;
                }

                babylonMesh.subMeshes = subMeshes.ToArray();

                // Buffers - Indices
                babylonMesh.indices = indices.ToArray();

            }

            // Instances
            var tabs = Loader.Global.NodeTab.Create();

            Loader.Global.IInstanceMgr.InstanceMgr.GetInstances(meshNode.MaxNode, tabs);
            var instances = new List<BabylonAbstractMesh>();

            for (var index = 0; index < tabs.Count; index++)
            {
                var indexer = new IntPtr(index);
                var tab = tabs[indexer];

                Marshal.FreeHGlobal(indexer);

                if (meshNode.MaxNode.GetGuid() == tab.GetGuid())
                {
                    continue;
                }
                var instanceGameNode = scene.GetIGameNode(tab);
                if (instanceGameNode == null)
                {
                    continue;
                }
                tab.MarkAsInstance();

                var instance = new BabylonAbstractMesh { name = tab.Name };
                {
                    var instanceLocalTM = instanceGameNode.GetObjectTM(0);

                    var instanceTrans = instanceLocalTM.Translation;
                    var instanceRotation = instanceLocalTM.Rotation;
                    var instanceScale = instanceLocalTM.Scaling;

                    instance.position = new[] { instanceTrans.X, instanceTrans.Y, instanceTrans.Z };

                    if (exportQuaternions)
                    {
                        instance.rotationQuaternion = new[] { instanceRotation.X, instanceRotation.Y, instanceRotation.Z, -instanceRotation.W };
                    }
                    else
                    {
                        RotationToEulerAngles(instance, instanceRotation);
                    }

                    instance.scaling = new[] { instanceScale.X, instanceScale.Y, instanceScale.Z };
                }
                var instanceAnimations = new List<BabylonAnimation>();
                GenerateCoordinatesAnimations(meshNode, instanceAnimations);
                instance.animations = instanceAnimations.ToArray();

                instances.Add(instance);
            }

            babylonMesh.instances = instances.ToArray();

            // Animations
            var animations = new List<BabylonAnimation>();

            GenerateCoordinatesAnimations(meshNode, animations);

            if (!ExportFloatController(meshNode.MaxNode.VisController, "visibility", animations))
            {
                ExportFloatAnimation("visibility", animations, key => new[] { meshNode.MaxNode.GetVisibility(key, Tools.Forever) });
            }

            babylonMesh.animations = animations.ToArray();

            if (meshNode.MaxNode.GetBoolProperty("babylonjs_autoanimate", 1))
            {
                babylonMesh.autoAnimate = true;
                babylonMesh.autoAnimateFrom = (int)meshNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_from");
                babylonMesh.autoAnimateTo = (int)meshNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_to", 100);
                babylonMesh.autoAnimateLoop = meshNode.MaxNode.GetBoolProperty("babylonjs_autoanimateloop", 1);
            }

            babylonScene.MeshesList.Add(babylonMesh);
        }
        private void ExportCamera(IIGameScene scene,  IIGameNode cameraNode, BabylonScene babylonScene)
        {
            if (cameraNode.MaxNode.GetBoolProperty("babylonjs_noexport"))
            {
                return;
            }
            var gameCamera = cameraNode.IGameObject.AsGameCamera();
            var maxCamera = gameCamera.MaxObject as ICameraObject;
            var initialized = gameCamera.InitializeData;
            var babylonCamera = new BabylonCamera();

            RaiseMessage(cameraNode.Name, 1);
            babylonCamera.name = cameraNode.Name;
            babylonCamera.id = cameraNode.MaxNode.GetGuid().ToString();
            if (cameraNode.NodeParent != null)
            {
                babylonCamera.parentId = GetParentID(cameraNode.NodeParent, babylonScene, scene);
            }

            babylonCamera.fov = Tools.ConvertFov(maxCamera.GetFOV(0, Tools.Forever));

            if (maxCamera.ManualClip == 1)
            {
                babylonCamera.minZ = maxCamera.GetClipDist(0, 1, Tools.Forever);
                babylonCamera.maxZ = maxCamera.GetClipDist(0, 2, Tools.Forever);
            }
            else
            {
                babylonCamera.minZ = 0.1f;
                babylonCamera.maxZ = 10000.0f;
            }

            if (babylonCamera.minZ == 0.0f)
            {
                babylonCamera.minZ = 0.1f;
            }

            // Type
            babylonCamera.type = cameraNode.MaxNode.GetStringProperty("babylonjs_type", "FreeCamera");

            // Control
            babylonCamera.speed = cameraNode.MaxNode.GetFloatProperty("babylonjs_speed", 1.0f);
            babylonCamera.inertia = cameraNode.MaxNode.GetFloatProperty("babylonjs_inertia", 0.9f);

            // Collisions
            babylonCamera.checkCollisions = cameraNode.MaxNode.GetBoolProperty("babylonjs_checkcollisions");
            babylonCamera.applyGravity = cameraNode.MaxNode.GetBoolProperty("babylonjs_applygravity");
            babylonCamera.ellipsoid = cameraNode.MaxNode.GetVector3Property("babylonjs_ellipsoid");

            // Position
            var wm = cameraNode.GetLocalTM(0);
            if (cameraNode.NodeParent != null)
            {
                var parentWorld = cameraNode.NodeParent.GetObjectTM(0);
                wm.MultiplyBy(parentWorld.Inverse);
            }
            var position = wm.Translation;
            babylonCamera.position = new [] { position.X, position.Y, position.Z };

            // Target
            var target = gameCamera.CameraTarget;
            if (target != null)
            {
                babylonCamera.lockedTargetId = target.MaxNode.GetGuid().ToString();
            }
            else
            {
                var dir = wm.GetRow(3);
                babylonCamera.target = new [] { position.X - dir.X, position.Y - dir.Y, position.Z - dir.Z };
            }

            // Animations
            var animations = new List<BabylonAnimation>();

            ExportVector3Animation("position", animations, key =>
            {
                var tm = cameraNode.GetLocalTM(key);
                if (cameraNode.NodeParent != null)
                {
                    var parentWorld = cameraNode.NodeParent.GetObjectTM(key);
                    tm.MultiplyBy(parentWorld.Inverse);
                }
                var translation = tm.Translation;
                return new [] { translation.X, translation.Y, translation.Z };
            });

            if (gameCamera.CameraTarget == null)
            {
                ExportVector3Animation("target", animations, key =>
                {
                    var tm = cameraNode.GetLocalTM(key);
                    if (cameraNode.NodeParent != null)
                    {
                        var parentWorld = cameraNode.NodeParent.GetObjectTM(key);
                        tm.MultiplyBy(parentWorld.Inverse);
                    }
                    var translation = tm.Translation;
                    var dir = tm.GetRow(3);
                    return new float[] { translation.X - dir.X, translation.Y - dir.Y, translation.Z - dir.Z };
                });
            }

            ExportFloatAnimation("fov", animations, key => new[] { Tools.ConvertFov((gameCamera.MaxObject as ICameraObject).GetFOV(key, Tools.Forever)) });

            babylonCamera.animations = animations.ToArray();

            if (cameraNode.MaxNode.GetBoolProperty("babylonjs_autoanimate"))
            {
                babylonCamera.autoAnimate = true;
                babylonCamera.autoAnimateFrom = (int)cameraNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_from");
                babylonCamera.autoAnimateTo = (int)cameraNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_to");
                babylonCamera.autoAnimateLoop = cameraNode.MaxNode.GetBoolProperty("babylonjs_autoanimateloop");
            }

            babylonScene.CamerasList.Add(babylonCamera);
        }
Пример #21
0
        public async Task ExportAsync(string outputFile, bool generateManifest, bool onlySelected, bool generateBinary, Form callerForm)
        {
            var gameConversionManger = Loader.Global.ConversionManager;
            gameConversionManger.CoordSystem = Autodesk.Max.IGameConversionManager.CoordSystem.D3d;

            var gameScene = Loader.Global.IGameInterface;
            gameScene.InitialiseIGame(onlySelected);
            gameScene.SetStaticFrame(0);

            MaxSceneFileName = gameScene.SceneFileName;

            IsCancelled = false;
            RaiseMessage("Exportation started", Color.Blue);
            ReportProgressChanged(0);
            var babylonScene = new BabylonScene(Path.GetDirectoryName(outputFile));
            var rawScene = Loader.Core.RootNode;

            if (!Directory.Exists(babylonScene.OutputPath))
            {
                RaiseError("Exportation stopped: Output folder does not exist");
                ReportProgressChanged(100);
                return;
            }

            var watch = new Stopwatch();
            watch.Start();

            // Save scene
            RaiseMessage("Saving 3ds max file");

            if (AutoSave3dsMaxFile)
            {
                var forceSave = Loader.Core.FileSave;

                if (callerForm != null)
                {
                    callerForm.BringToFront();
                }
            }

            // Global
            babylonScene.autoClear = true;
            babylonScene.clearColor = Loader.Core.GetBackGround(0, Tools.Forever).ToArray();
            babylonScene.ambientColor = Loader.Core.GetAmbient(0, Tools.Forever).ToArray();

            babylonScene.gravity = rawScene.GetVector3Property("babylonjs_gravity");
            ExportQuaternionsInsteadOfEulers = rawScene.GetBoolProperty("babylonjs_exportquaternions", 1);

            // Sounds
            var soundName = rawScene.GetStringProperty("babylonjs_sound_filename", "");

            if (!string.IsNullOrEmpty(soundName))
            {
                var filename = Path.GetFileName(soundName);

                var globalSound = new BabylonSound
                {
                    autoplay = rawScene.GetBoolProperty("babylonjs_sound_autoplay", 1),
                    loop = rawScene.GetBoolProperty("babylonjs_sound_loop", 1),
                    name = filename
                };

                babylonScene.SoundsList.Add(globalSound);

                try
                {
                    File.Copy(soundName, Path.Combine(babylonScene.OutputPath, filename), true);
                }
                catch
                {
                }
            }

            // Cameras
            BabylonCamera mainCamera = null;
            ICameraObject mainCameraNode = null;

            RaiseMessage("Exporting cameras");
            var camerasTab = gameScene.GetIGameNodeByType(Autodesk.Max.IGameObject.ObjectTypes.Camera);
            for (int ix = 0; ix < camerasTab.Count; ++ix)
            {
                var indexer = new IntPtr(ix);
                var cameraNode = camerasTab[indexer];
                Marshal.FreeHGlobal(indexer);
                ExportCamera(gameScene, cameraNode, babylonScene);

                if (mainCamera == null && babylonScene.CamerasList.Count > 0)
                {
                    mainCameraNode = (cameraNode.MaxNode.ObjectRef as ICameraObject);
                    mainCamera = babylonScene.CamerasList[0];
                    babylonScene.activeCameraID = mainCamera.id;
                    RaiseMessage("Active camera set to " + mainCamera.name, Color.Green, 1, true);
                }
            }

            if (mainCamera == null)
            {
                RaiseWarning("No camera defined", 1);
            }
            else
            {
                RaiseMessage(string.Format("Total: {0}", babylonScene.CamerasList.Count), Color.Gray, 1);
            }

            // Fog
            for (var index = 0; index < Loader.Core.NumAtmospheric; index++)
            {
                var atmospheric = Loader.Core.GetAtmospheric(index);

                if (atmospheric.Active(0) && atmospheric.ClassName == "Fog")
                {
                    var fog = atmospheric as IStdFog;

                    RaiseMessage("Exporting fog");

                    if (fog != null)
                    {
                        babylonScene.fogColor = fog.GetColor(0).ToArray();
                        babylonScene.fogMode = 3;
                    }
#if !MAX2015 && !MAX2016
                    else
                    {
                        var paramBlock = atmospheric.GetReference(0) as IIParamBlock;

                        babylonScene.fogColor = Tools.GetParamBlockValueColor(paramBlock, "Fog Color");
                        babylonScene.fogMode = 3;
                    }
#endif
                    if (mainCamera != null)
                    {
                        babylonScene.fogStart = mainCameraNode.GetEnvRange(0, 0, Tools.Forever);
                        babylonScene.fogEnd = mainCameraNode.GetEnvRange(0, 1, Tools.Forever);
                    }
                }
            }

            // Meshes
            ReportProgressChanged(10);
            RaiseMessage("Exporting meshes");
            var meshes = gameScene.GetIGameNodeByType(Autodesk.Max.IGameObject.ObjectTypes.Mesh);
            var progressionStep = 80.0f / meshes.Count;
            var progression = 10.0f;
            for (int ix = 0; ix < meshes.Count; ++ix)
            {
                var indexer = new IntPtr(ix);
                var meshNode = meshes[indexer];
                Marshal.FreeHGlobal(indexer);
                ExportMesh(gameScene, meshNode, babylonScene);


                ReportProgressChanged((int)progression);

                progression += progressionStep;

                CheckCancelled();
            }


            // Materials
            RaiseMessage("Exporting materials");
            var matsToExport = referencedMaterials.ToArray(); // Snapshot because multimaterials can export new materials
            foreach (var mat in matsToExport)
            {
                ExportMaterial(mat, babylonScene);
                CheckCancelled();
            }
            RaiseMessage(string.Format("Total: {0}", babylonScene.MaterialsList.Count + babylonScene.MultiMaterialsList.Count), Color.Gray, 1);

            // Lights
            RaiseMessage("Exporting lights");
            var lightNodes = gameScene.GetIGameNodeByType(Autodesk.Max.IGameObject.ObjectTypes.Light);
            for (var i = 0; i < lightNodes.Count; ++i)
            {
                ExportLight(gameScene, lightNodes[new IntPtr(i)], babylonScene);
                CheckCancelled();
            }


            if (babylonScene.LightsList.Count == 0)
            {
                RaiseWarning("No light defined", 1);
                RaiseWarning("A default hemispheric light was added for your convenience", 1);
                ExportDefaultLight(babylonScene);
            }
            else
            {
                RaiseMessage(string.Format("Total: {0}", babylonScene.LightsList.Count), Color.Gray, 1);
            }

            // Skeletons
            if (skins.Count > 0)
            {
                RaiseMessage("Exporting skeletons");
                foreach (var skin in skins)
                {
                    ExportSkin(skin, babylonScene);
                }
            }

            // Actions
            babylonScene.actions = ExportNodeAction(gameScene.GetIGameNode(rawScene));

            // Output
            RaiseMessage("Saving to output file");
            babylonScene.Prepare(false);
            var jsonSerializer = JsonSerializer.Create(new JsonSerializerSettings());
            var sb = new StringBuilder();
            var sw = new StringWriter(sb, CultureInfo.InvariantCulture);

            await Task.Run(() =>
            {
                using (var jsonWriter = new JsonTextWriterOptimized(sw))
                {
                    jsonWriter.Formatting = Formatting.None;
                    jsonSerializer.Serialize(jsonWriter, babylonScene);
                }
                File.WriteAllText(outputFile, sb.ToString());

                if (generateManifest)
                {
                    File.WriteAllText(outputFile + ".manifest",
                        "{\r\n\"version\" : 1,\r\n\"enableSceneOffline\" : true,\r\n\"enableTexturesOffline\" : true\r\n}");
                }
            });

            // Binary
            if (generateBinary)
            {
                RaiseMessage("Generating binary files");
                BabylonFileConverter.BinaryConverter.Convert(outputFile, Path.GetDirectoryName(outputFile) + "\\Binary",
                    message => RaiseMessage(message, 1),
                    error => RaiseError(error, 1));
            }

            ReportProgressChanged(100);
            watch.Stop();
            RaiseMessage(string.Format("Exportation done in {0:0.00}s", watch.ElapsedMilliseconds / 1000.0), Color.Blue);
        }
Пример #22
0
        private void ExportMesh(IINode meshNode, BabylonScene babylonScene)
        {
            if (meshNode.GetBoolProperty("babylonjs_noexport"))
            {
                return;
            }

            if (!ExportHiddenObjects && meshNode.IsHidden(NodeHideFlags.None, false))
            {
                return;
            }

            var babylonMesh = new BabylonMesh();
            int vx1, vx2, vx3;

            babylonMesh.name = meshNode.Name;
            babylonMesh.id = meshNode.GetGuid().ToString();
            if (meshNode.HasParent())
            {
                babylonMesh.parentId = meshNode.ParentNode.GetGuid().ToString();
            }

            // Misc.
            babylonMesh.isVisible = meshNode.Renderable == 1;
            babylonMesh.pickable = meshNode.GetBoolProperty("babylonjs_checkpickable");
            babylonMesh.receiveShadows = meshNode.RcvShadows == 1;
            babylonMesh.showBoundingBox = meshNode.GetBoolProperty("babylonjs_showboundingbox");
            babylonMesh.showSubMeshesBoundingBox = meshNode.GetBoolProperty("babylonjs_showsubmeshesboundingbox");

            // Collisions
            babylonMesh.checkCollisions = meshNode.GetBoolProperty("babylonjs_checkcollisions");

            // Skin
            var skin = GetSkinModifier(meshNode);

            if (skin != null)
            {
                babylonMesh.skeletonId = skins.IndexOf(skin);
                bonesCount = skin.NumBones;
            }

            // Position / rotation / scaling
            var wm = meshNode.GetWorldMatrix(0, meshNode.HasParent());
            babylonMesh.position = wm.Trans.ToArraySwitched();

            var parts = Loader.Global.AffineParts.Create();
            Loader.Global.DecompAffine(wm, parts);

            if (exportQuaternionsInsteadOfEulers)
            {
                babylonMesh.rotationQuaternion = parts.Q.ToArray();
            }
            else
            {
                var rotate = new float[3];

                IntPtr xPtr = Marshal.AllocHGlobal(sizeof(float));
                IntPtr yPtr = Marshal.AllocHGlobal(sizeof(float));
                IntPtr zPtr = Marshal.AllocHGlobal(sizeof(float));
                parts.Q.GetEuler(xPtr, yPtr, zPtr);

                Marshal.Copy(xPtr, rotate, 0, 1);
                Marshal.Copy(yPtr, rotate, 1, 1);
                Marshal.Copy(zPtr, rotate, 2, 1);

                var temp = rotate[1];
                rotate[0] = -rotate[0] * parts.F;
                rotate[1] = -rotate[2] * parts.F;
                rotate[2] = -temp * parts.F;

                babylonMesh.rotation = rotate;                
            }

            babylonMesh.scaling = parts.K.ToArraySwitched();

            if (wm.Parity)
            {
                vx1 = 2;
                vx2 = 1;
                vx3 = 0;
            }
            else
            {
                vx1 = 0;
                vx2 = 1;
                vx3 = 2;
            }

            // Pivot
            var pivotMatrix = Tools.Identity;
            pivotMatrix.PreTranslate(meshNode.ObjOffsetPos);
            Loader.Global.PreRotateMatrix(pivotMatrix, meshNode.ObjOffsetRot);
            Loader.Global.ApplyScaling(pivotMatrix, meshNode.ObjOffsetScale);
            babylonMesh.pivotMatrix = pivotMatrix.ToArray();

            // Mesh
            var objectState = meshNode.EvalWorldState(0, false);
            var triObject = objectState.Obj.GetMesh();
            var mesh = triObject != null ? triObject.Mesh : null;

            RaiseMessage(meshNode.Name, 1);

            if (mesh != null)
            {
                mesh.BuildNormals();

                if (mesh.NumFaces < 1)
                {
                    RaiseError(string.Format("Mesh {0} has no face", babylonMesh.name), 2);
                }

                if (mesh.NumVerts < 3)
                {
                    RaiseError(string.Format("Mesh {0} has not enough vertices", babylonMesh.name), 2);
                }

                if (mesh.NumVerts >= 65536)
                {
                    RaiseError(string.Format("Mesh {0} has too many vertices (more than 65535)", babylonMesh.name), 2);
                }

                // Material
                var mtl = meshNode.Mtl;
                var multiMatsCount = 1;

                if (mtl != null)
                {
                    babylonMesh.materialId = mtl.GetGuid().ToString();

                    if (!referencedMaterials.Contains(mtl))
                    {
                        referencedMaterials.Add(mtl);
                    }

                    multiMatsCount = Math.Max(mtl.NumSubMtls, 1);
                }

                babylonMesh.visibility = meshNode.GetVisibility(0, Tools.Forever);

                var vertices = new List<GlobalVertex>();
                var indices = new List<int>();
                var matIDs = new List<int>();

                var hasUV = mesh.NumTVerts > 0;
                var hasUV2 = mesh.GetNumMapVerts(2) > 0;

                var optimizeVertices = meshNode.GetBoolProperty("babylonjs_optimizevertices");

                // Skin
                IISkinContextData skinContext = null;

                if (skin != null)
                {
                    skinContext = skin.GetContextInterface(meshNode);
                }

                // Compute normals
                VNormal[] vnorms = Tools.ComputeNormals(mesh, optimizeVertices);
                List<GlobalVertex>[] verticesAlreadyExported = null;

                if (optimizeVertices)
                {
                    verticesAlreadyExported = new List<GlobalVertex>[mesh.NumVerts];
                }

                for (var face = 0; face < mesh.NumFaces; face++)
                {
                    indices.Add(CreateGlobalVertex(mesh, face, vx1, vertices, hasUV, hasUV2, vnorms, verticesAlreadyExported, skinContext));
                    indices.Add(CreateGlobalVertex(mesh, face, vx2, vertices, hasUV, hasUV2, vnorms, verticesAlreadyExported, skinContext));
                    indices.Add(CreateGlobalVertex(mesh, face, vx3, vertices, hasUV, hasUV2, vnorms, verticesAlreadyExported, skinContext));
                    matIDs.Add(mesh.Faces[face].MatID % multiMatsCount);
                    CheckCancelled();
                }

                if (vertices.Count >= 65536)
                {
                    RaiseError(string.Format("Mesh {0} has too many vertices: {1} (limit is 65535)", babylonMesh.name, vertices.Count), 2);

                    if (!optimizeVertices)
                    {
                        RaiseError("You can try to optimize your object using [Try to optimize vertices] option", 2);
                    }
                }

                RaiseMessage(string.Format("{0} vertices, {1} faces", vertices.Count, indices.Count / 3), 2);

                // Buffers
                babylonMesh.positions = vertices.SelectMany(v => v.Position.ToArraySwitched()).ToArray();
                babylonMesh.normals = vertices.SelectMany(v => v.Normal.ToArraySwitched()).ToArray();
                if (hasUV)
                {
                    babylonMesh.uvs = vertices.SelectMany(v => v.UV.ToArray()).ToArray();
                }
                if (hasUV2)
                {
                    babylonMesh.uvs2 = vertices.SelectMany(v => v.UV2.ToArray()).ToArray();
                }

                if (skin != null)
                {
                    babylonMesh.matricesWeights = vertices.SelectMany(v => v.Weights.ToArray()).ToArray();
                    babylonMesh.matricesIndices = vertices.Select(v => v.BonesIndices).ToArray();
                }

                // Submeshes
                var sortedIndices = new List<int>();
                var subMeshes = new List<BabylonSubMesh>();
                var indexStart = 0;
                for (var index = 0; index < multiMatsCount; index++)
                {
                    var subMesh = new BabylonSubMesh();
                    var indexCount = 0;
                    var minVertexIndex = int.MaxValue;
                    var maxVertexIndex = int.MinValue;

                    subMesh.indexStart = indexStart;
                    subMesh.materialIndex = index;

                    for (var face = 0; face < matIDs.Count; face++)
                    {
                        if (matIDs[face] == index)
                        {
                            var a = indices[3 * face];
                            var b = indices[3 * face + 1];
                            var c = indices[3 * face + 2];

                            sortedIndices.Add(a);
                            sortedIndices.Add(b);
                            sortedIndices.Add(c);
                            indexCount += 3;

                            if (a < minVertexIndex)
                            {
                                minVertexIndex = a;
                            }

                            if (b < minVertexIndex)
                            {
                                minVertexIndex = b;
                            }

                            if (c < minVertexIndex)
                            {
                                minVertexIndex = c;
                            }

                            if (a > maxVertexIndex)
                            {
                                maxVertexIndex = a;
                            }

                            if (b > maxVertexIndex)
                            {
                                maxVertexIndex = b;
                            }

                            if (c > maxVertexIndex)
                            {
                                maxVertexIndex = c;
                            }
                        }
                    }
                    if (indexCount != 0)
                    {

                        subMesh.indexCount = indexCount;
                        subMesh.verticesStart = minVertexIndex;
                        subMesh.verticesCount = maxVertexIndex - minVertexIndex + 1;

                        indexStart += indexCount;

                        subMeshes.Add(subMesh);
                    }
                    CheckCancelled();
                }
                babylonMesh.subMeshes = subMeshes.ToArray();


                // Buffers - Indices
                babylonMesh.indices = sortedIndices.ToArray();

                triObject.Dispose();
            }


            // Animations
            var animations = new List<BabylonAnimation>();

            if (!ExportVector3Controller(meshNode.TMController.PositionController, "position", animations))
            {
                ExportVector3Animation("position", animations, key =>
                {
                    var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
                    return worldMatrix.Trans.ToArraySwitched();
                });
            }

            if (!ExportQuaternionController(meshNode.TMController.RotationController, "rotationQuaternion", animations))
            {
                ExportQuaternionAnimation("rotationQuaternion", animations, key =>
                {
                    var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());

                    var affineParts = Loader.Global.AffineParts.Create();
                    Loader.Global.DecompAffine(worldMatrix, affineParts);

                    return affineParts.Q.ToArray();
                });
            }

            if (!ExportVector3Controller(meshNode.TMController.ScaleController, "scaling", animations))
            {
                ExportVector3Animation("scaling", animations, key =>
                {
                    var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());

                    var affineParts = Loader.Global.AffineParts.Create();
                    Loader.Global.DecompAffine(worldMatrix, affineParts);

                    return affineParts.K.ToArraySwitched();
                });
            }

            if (!ExportFloatController(meshNode.VisController, "visibility", animations))
            {
                ExportFloatAnimation("visibility", animations, key => new[] { meshNode.GetVisibility(key, Tools.Forever) });
            }

            babylonMesh.animations = animations.ToArray();

            if (meshNode.GetBoolProperty("babylonjs_autoanimate", 1))
            {
                babylonMesh.autoAnimate = true;
                babylonMesh.autoAnimateFrom = (int)meshNode.GetFloatProperty("babylonjs_autoanimate_from");
                babylonMesh.autoAnimateTo = (int)meshNode.GetFloatProperty("babylonjs_autoanimate_to", 100);
                babylonMesh.autoAnimateLoop = meshNode.GetBoolProperty("babylonjs_autoanimateloop", 1);
            }

            babylonScene.MeshesList.Add(babylonMesh);
        }
Пример #23
0
        public void Export(string outputFile)
        {
            IsCancelled = false;
            RaiseMessage("Exportation started");
            ReportProgressChanged(0);
            var babylonScene = new BabylonScene(Path.GetDirectoryName(outputFile));
            var maxScene = Kernel.Scene;
            alreadyExportedTextures.Clear();

            if (!Directory.Exists(babylonScene.OutputPath))
            {
                RaiseError("Exportation stopped: Output folder does not exist");
                ReportProgressChanged(100);
                return;
            }

            // Save scene
            RaiseMessage("Saving 3ds max file");
            var forceSave = Loader.Core.FileSave;

            // Global
            babylonScene.autoClear = true;
            babylonScene.clearColor = Loader.Core.GetBackGround(0, Interval.Forever._IInterval).ToArray();
            babylonScene.ambientColor = Loader.Core.GetAmbient(0, Interval.Forever._IInterval).ToArray();

            babylonScene.gravity = maxScene.RootNode._Node.GetVector3Property("babylonjs_gravity");

            // Cameras
            BabylonCamera mainCamera = null;

            RaiseMessage("Exporting cameras");
            foreach (var cameraNode in maxScene.NodesListBySuperClass(SuperClassID.Camera))
            {
                ExportCamera(cameraNode, babylonScene);

                if (mainCamera == null && babylonScene.CamerasList.Count > 0)
                {
                    mainCamera = babylonScene.CamerasList[0];
                    babylonScene.activeCameraID = mainCamera.id;
                    RaiseMessage("Active camera set to " + mainCamera.name, true, true);
                }
            }

            if (mainCamera == null)
            {
                RaiseWarning("No camera defined", true);
            }

            // Fog
            for (var index = 0; index < Loader.Core.NumAtmospheric; index++)
            {
                var atmospheric = Loader.Core.GetAtmospheric(index);

                if (atmospheric.Active(0) && atmospheric.ClassName == "Fog")
                {
                    RaiseMessage("Exporting fog");
                    var reference = atmospheric.GetReference(0);
                    var parameters = Animatable.CreateWrapper<ParameterBlock1>(reference);

                    babylonScene.fogColor = (parameters["fog color"].Value as IColor).ToArray();
                    babylonScene.fogDensity = (float)parameters["density"].Value;
                    babylonScene.fogMode = ((int)parameters["fog type"].Value) == 0 ? 3 : 1;

                    if (mainCamera != null)
                    {
                        babylonScene.fogStart = mainCamera.minZ * (float)parameters["near %"].Value;
                        babylonScene.fogEnd = mainCamera.maxZ * (float)parameters["far %"].Value;
                    }
                }
            }

            // Meshes
            ReportProgressChanged(10);
            RaiseMessage("Exporting meshes");
            var meshes = maxScene.NodesListBySuperClasses(new[] {SuperClassID.GeometricObject, SuperClassID.Helper});
            var progressionStep = 80.0f / meshes.Count();
            var progression = 10.0f;
            foreach (var meshNode in meshes)
            {
                Tools.PreparePipeline(meshNode._Node, true);
                ExportMesh(meshNode, babylonScene);
                Tools.PreparePipeline(meshNode._Node, false);

                progression += progressionStep;
                ReportProgressChanged((int)progression);

                CheckCancelled();
            }

            // Materials
            RaiseMessage("Exporting materials");
            var matsToExport = referencedMaterials.ToArray(); // Snapshot because multimaterials can export new materials
            foreach (var mat in matsToExport)
            {
                ExportMaterial(mat, babylonScene);
                CheckCancelled();
            }

            // Lights
            RaiseMessage("Exporting lights");
            foreach (var lightNode in maxScene.NodesListBySuperClass(SuperClassID.Light))
            {
                ExportLight(lightNode, babylonScene);
                CheckCancelled();
            }

            if (babylonScene.LightsList.Count == 0)
            {
                RaiseWarning("No light defined", true);
            }

            // Skeletons
            RaiseMessage("Exporting skeletons");
            foreach (var skin in skins)
            {
                ExportSkin(skin, babylonScene);
                skin.Dispose();
            }

            // Output
            babylonScene.Prepare(false);
            var jsonSerializer = JsonSerializer.Create();
            var sb = new StringBuilder();
            var sw = new StringWriter(sb, CultureInfo.InvariantCulture);
            using (var jsonWriter = new JsonTextWriterOptimized(sw))
            {
                jsonWriter.Formatting = Formatting.None;
                jsonSerializer.Serialize(jsonWriter, babylonScene);
            }
            File.WriteAllText(outputFile, sb.ToString());

            ReportProgressChanged(100);

            RaiseMessage("Exportation done");
        }
Пример #24
0
 public virtual void OnExportGameObject(ref Unity3D2Babylon.ExportationOptions exportOptions, ref GameObject unityGameObject, ref UnityMetaData metaData, ref BabylonScene sceneBuilder, string outputPath) { }
        private void ExportSkin(IISkin skin, BabylonScene babylonScene)
        {
            var babylonSkeleton = new BabylonSkeleton {id = skins.IndexOf(skin)};
            babylonSkeleton.name = "skeleton #" + babylonSkeleton.id;

            RaiseMessage(babylonSkeleton.name, 1);

            var bones = new List<BabylonBone>();

            for (var index = 0; index < skin.NumBones; index++)
            {
                var bone = new BabylonBone {name = skin.GetBoneName(index), index = index};

                var maxBone = skin.GetBone(index);
                var parentNode = maxBone.ParentNode;

                if (parentNode != null)
                {
                    for (var recurseIndex = 0; recurseIndex < index; recurseIndex++)
                    {
                        if (skin.GetBone(recurseIndex).GetGuid() == parentNode.GetGuid())
                        {
                            bone.parentBoneIndex = recurseIndex;
                            break;
                        }
                    }
                }
                var hasParent = bone.parentBoneIndex != -1;
                bone.matrix = GetBoneMatrix(skin, maxBone, 0, hasParent);

                // Animation
                var babylonAnimation = new BabylonAnimation
                {
                    name = bone.name + "Animation", 
                    property = "_matrix", 
                    dataType = BabylonAnimation.DataType.Matrix, 
                    loopBehavior = BabylonAnimation.LoopBehavior.Cycle,
                    framePerSecond = Loader.Global.FrameRate
                };

                var start = Loader.Core.AnimRange.Start;
                var end = Loader.Core.AnimRange.End;

                float[] previous = null;
                var keys = new List<BabylonAnimationKey>();
                for (var key = start; key <= end; key += Ticks)
                {
                    var current = GetBoneMatrix(skin, maxBone, key, hasParent);

                    if (key == start || key == end || !(previous.IsEqualTo(current)))
                    {
                        keys.Add(new BabylonAnimationKey
                        {
                            frame = key / Ticks,
                            values = current
                        });
                    }

                    previous = current;
                }

                babylonAnimation.keys = keys.ToArray();
                bone.animation = babylonAnimation;

                bones.Add(bone);
            }

            babylonSkeleton.bones = bones.ToArray();

            babylonScene.SkeletonsList.Add(babylonSkeleton);
        }