Пример #1
0
        public static void PreparePipeline(IINode node, bool deactivate)
        {
            var obj = node.ObjectRef;

            if (obj.SuperClassID != SClass_ID.GenDerivob)
            {
                return;
            }

            var derivedObject = obj as IIDerivedObject;

            if (derivedObject == null)
            {
                return;
            }

            for (var index = 0; index < derivedObject.NumModifiers; index++)
            {
                var modifier = derivedObject.GetModifier(index);

                //if (modifier.ClassID.PartA == 9815843 && modifier.ClassID.PartB == 87654) // Skin
                //{
                //    if (deactivate)
                //    {
                //        modifier.DisableMod();
                //    }
                //    else
                //    {
                //        modifier.EnableMod();
                //    }
                //}
            }
        }
        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;
        }
        float[] GetBoneMatrix(IISkin skin, IINode bone, int t, bool hasParent)
        {
            var maxMatrix = bone.GetWorldMatrix(t, hasParent);

            //var initialMatrix = Loader.Global.Matrix3.Create();
            //skin.GetBoneInitTM(bone, initialMatrix, false);

            //initialMatrix.Invert();

            //maxMatrix = maxMatrix.MultiplyBy(initialMatrix);

            //if (!hasParent)
            //{
            //    initialMatrix = Loader.Global.Matrix3.Create();
            //    skin.GetSkinInitTM(bone, initialMatrix, false);

            //    initialMatrix.Invert();

            //    maxMatrix = maxMatrix.MultiplyBy(initialMatrix);
            //}

            maxMatrix.NoScale();

            var trans = maxMatrix.Trans;

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

            var rotationQuaternion = new Quaternion(parts.Q.X, parts.Q.Z, parts.Q.Y, parts.Q.W);

            var matrix = Matrix.RotationQuaternion(rotationQuaternion) * Matrix.Translation(trans.X, trans.Z, trans.Y);

            return matrix.ToArray();
        }
        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;
        }
Пример #5
0
   /// <summary>
   /// Tests if an inode is a plugin with the supplied ClassID.
   /// </summary>
   public static bool IsClass(IINode node, uint cidA, uint cidB)
   {
      if (node == null)
         return false;

      return IsClass(node.ObjectRef, cidA, cidB);
   }
Пример #6
0
   /// <summary>
   /// Tests if an object is a plugin with the supplied SuperClass.
   /// </summary>
   public static bool IsSuperClass(IINode node, SClass_ID scid)
   {
      if (node == null)
         return false;

      return IsSuperClass(node.ObjectRef, scid);
   }
Пример #7
0
 private void FillTree(IINode node)
 {
    this.AddNode(node, this.Tree.Nodes);
    for (int i = 0; i < node.NumberOfChildren; i++)
    {
       this.FillTree(node.GetChildNode(i));
    }
 }
Пример #8
0
        private IEnumerable<IINode> GetChildNodesRecursive(IINode start)
        {
            for (int i = 0; i < start.NumChildren; i++)
            {
                yield return start.GetChildNode(i);

                foreach(var n in GetChildNodesRecursive(start.GetChildNode(i)))
                    yield return n;
            }
        }
 private IEnumerable<IINode> getChildren(IINode node)
 {
    List<IINode> nodes = new List<IINode>();
    for (int i = 0; i < node.NumberOfChildren; i++)
    {
       IINode child = node.GetChildNode(i);
       nodes.Add(child);
       nodes.AddRange(getChildren(child));
    }
    return nodes;
 }
Пример #10
0
 private static void SetLocks(IINode node, List<Boolean> locks)
 {
    node.SetTransformLock(0, 0, locks[0]);
    node.SetTransformLock(0, 1, locks[1]);
    node.SetTransformLock(0, 2, locks[2]);
    node.SetTransformLock(1, 0, locks[3]);
    node.SetTransformLock(1, 1, locks[4]);
    node.SetTransformLock(1, 2, locks[5]);
    node.SetTransformLock(2, 0, locks[6]);
    node.SetTransformLock(2, 1, locks[7]);
    node.SetTransformLock(2, 2, locks[8]);
 }
Пример #11
0
   private static IEnumerable<INodeWrapper> GetChildObjects(IINode node)
   {
      for (int i = 0; i < node.NumberOfChildren; i++)
      {
         IINode childNode = node.GetChildNode(i);
         yield return new INodeWrapper(childNode);

         foreach (INodeWrapper child in GetChildObjects(childNode))
         {
            yield return child;
         }
      }
   }
Пример #12
0
 private List<Boolean> GetLocks(IINode node)
 {
    List<Boolean> locks = new List<Boolean>(9);
    locks.Add(node.GetTransformLock(0, 0));
    locks.Add(node.GetTransformLock(0, 1));
    locks.Add(node.GetTransformLock(0, 2));
    locks.Add(node.GetTransformLock(1, 0));
    locks.Add(node.GetTransformLock(1, 1));
    locks.Add(node.GetTransformLock(1, 2));
    locks.Add(node.GetTransformLock(2, 0));
    locks.Add(node.GetTransformLock(2, 1));
    locks.Add(node.GetTransformLock(2, 2));
    return locks;
 }
Пример #13
0
 public void UpdateMeshAnimation(IINode node, MyMesh mesh)
 {
     switch (mesh.AnimationType)
     {
         case AnimationType.None:
             break;
         case AnimationType.Keyframes:
             UpdateMeshAnimation((node.ObjectRef as ITriObject), mesh.Keyframes);
             break;
         case AnimationType.PointCache:
             UpdateMeshAnimation_PointCache(node, mesh.Keyframes);
             break;
     }
 }
Пример #14
0
        protected void CreateSkinning(IINode mesh, MyMesh myMesh, Dictionary<string, IINode> skeletonMap)
        {
            IModifier skin_modifier = GetSkinModifier(mesh);
            IISkinImportData skin = skin_modifier.GetInterface((InterfaceID)InterfaceIDs.I_SKINIMPORTDATA) as IISkinImportData;

            foreach (var bone in skeletonMap.Values)
            {
                skin.AddBoneEx(bone, false);
            }

            mesh.EvalWorldState(0, true); //must be called after adding bones, but before adding weights (presumably so that something in the graph realises the bones have been added when the weights need them

            List<vertexWeightMap> vertexWeights = GetWeightMapsByVertex(myMesh, skeletonMap);
            for (int i = 0; i < vertexWeights.Count; i++)
            {
                skin.AddWeights(mesh, i, vertexWeights[i].GetBonesITab(), vertexWeights[i].GetWeightsITab());
            }
        }
Пример #15
0
        private void ActionsBuilderForm_Load(object sender, EventArgs e)
        {
            if (Loader.Core.SelNodeCount > 0)
            {
                isRootNode = false;
                _node = Loader.Core.GetSelNode(0);
            }
            else
            {
                isRootNode = true;
                _node = Loader.Core.RootNode;
            }
            _objectName = _node.Name;

            // Set url (webview)
            string assemblyPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase);
            ActionsBuilderWebView.Url = new Uri(string.Format("{0}/BabylonActionsBuilder/index.html", assemblyPath), System.UriKind.Absolute);
        }
Пример #16
0
        protected unsafe GeometryNode CreateGeometryUpdate(IINode node)
        {
            IObject obj = node.EvalWorldState(0, false).Obj;
            if (obj.CanConvertToType(_gi.Class_ID.Create(TRIOBJ_CLASS_ID, 0)) > 0)
            {
                ITriObject triobj = obj.ConvertToType(0, _gi.Class_ID.Create(TRIOBJ_CLASS_ID, 0)) as ITriObject;

                GeometryNode u = CreateGeometryUpdate(node, triobj);

                if (obj.Handle != triobj.Handle) /*If the triobject was created by the call above instead of existing prior to this*/
                {
                    triobj.DeleteMe();
                }

                return u;
            }

            return null;
        }
Пример #17
0
        protected unsafe GeometryNode CreateGeometryUpdate(IINode node, ITriObject maxGeometry)
        {
            GeometryNode update = new GeometryNode();

            update.Name = node.Name;
            update.Parent = node.ParentNode.Name;

            update.Transform = GetTransform(node);

            /*
             * Scene objects have one, or none, material. This member will be that materials name, even if that material is a container like a Composite 
             * or Shell material. 
             * The client will attach the Material ID of the face when/if the materials are split out, which will allow the materials
             * processing code to identify and import the correct material properties later. (In practice, we dont even need to store this - since knowing
             * the node name will allow us to find it - but sending it allows us to match the functionality of the FBX importer.
             */

            if (node.Mtl != null)
            {
                update.MaterialName = node.Mtl.Name;
            }

            IMesh mesh = maxGeometry.Mesh;

            /* Get the master face array and vertex positions. We split by material id here also for convenience. */

            var facesAndPositions = GetTriMeshFacesAndPositions(mesh);

            update.FaceGroups.AddRange(MakeFaceGroupsFromMaterialIds(facesAndPositions.face_materialIds));
            update.faceFlags = facesAndPositions.face_flags;
            update.Channels.Add(facesAndPositions.positions_channel);

            /* Get the remaining properties, such as normals and texture coordinates */

            update.Channels.Add(GetTriMeshNormals(mesh));
            update.Channels.AddRange(GetTriMeshMapChannels(mesh));

            return update;
        }
        IISkin GetSkinModifier(IINode node)
        {
            var obj = node.ObjectRef;

            if (obj.SuperClassID != SClass_ID.GenDerivob)
            {
                return null;
            }

            var derivedObject = obj as IIDerivedObject;

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

            for (var index = 0; index < derivedObject.NumModifiers; index++)
            {
                var modifier = derivedObject.GetModifier(index);

                if (modifier.ClassID.PartA == 9815843 && modifier.ClassID.PartB == 87654) // Skin
                {
                    var skin = modifier.GetInterface((InterfaceID)0x00010000) as IISkin;

                    if (!skins.Contains(skin))
                    {
                        skins.Add(skin);                        
                    }

                    return skin;
                }
            }


            return null;
        }
Пример #19
0
 public static void PrepareTextBox(TextBox textBox, IINode node, string propertyName, string defaultValue = "")
 {
     var state = node.GetStringProperty(propertyName, defaultValue);
     textBox.Text = state;
 }
Пример #20
0
        private void confirmButton_Click(object sender, EventArgs e)
        {
            if (currentInfo == null)
            {
                return;
            }

            AnimationGroup confirmedInfo = currentInfo;

            string newName = nameTextBox.Text;

            bool newKeepEmpty       = keepStaticAnimBox.Checked;
            bool newKeepNonAnimated = keepNonAnimatedBox.Checked;

            int newFrameStart;

            if (!int.TryParse(startTextBox.Text, out newFrameStart))
            {
                newFrameStart = confirmedInfo.FrameStart;
            }
            int newFrameEnd;

            if (!int.TryParse(endTextBox.Text, out newFrameEnd))
            {
                newFrameEnd = confirmedInfo.FrameEnd;
            }

            List <uint>  newHandles;
            bool         nodesChanged = MaxNodeTree.ApplyQueuedChanges(out newHandles);
            IList <Guid> newMaterialGUIDs;
            bool         materialsChanged = maxMaterialView.ApplyMaterialsChanges(out newMaterialGUIDs);

            bool changed = newKeepEmpty != confirmedInfo.KeepStaticAnimation ||
                           newName != confirmedInfo.Name ||
                           newFrameStart != confirmedInfo.FrameStart ||
                           newFrameEnd != confirmedInfo.FrameEnd ||
                           nodesChanged ||
                           materialsChanged ||
                           newKeepNonAnimated != confirmedInfo.KeepNonAnimated;

            if (!changed)
            {
                return;
            }

            confirmedInfo.Name                = newName;
            confirmedInfo.FrameStart          = newFrameStart;
            confirmedInfo.FrameEnd            = newFrameEnd;
            confirmedInfo.KeepStaticAnimation = newKeepEmpty;
            confirmedInfo.KeepNonAnimated     = newKeepNonAnimated;

            if (nodesChanged)
            {
                confirmedInfo.NodeGuids = newHandles.ToGuids();
                if (confirmedInfo.AnimationGroupNodes == null)
                {
                    confirmedInfo.AnimationGroupNodes = new List <AnimationGroupNode>();
                }

                foreach (uint handle in newHandles)
                {
                    IINode node = Loader.Core.GetINodeByHandle(handle);
                    if (node != null)
                    {
                        string             name       = node.Name;
                        string             parentName = node.ParentNode.Name;
                        AnimationGroupNode nodeData   = new AnimationGroupNode(node.GetGuid(), name, parentName);
                        confirmedInfo.AnimationGroupNodes.Add(nodeData);
                    }
                }
            }

            if (materialsChanged)
            {
                confirmedInfo.MaterialGuids = newMaterialGUIDs;

                if (confirmedInfo.AnimationGroupMaterials == null)
                {
                    confirmedInfo.AnimationGroupMaterials = new List <AnimationGroupMaterial>();
                }

                foreach (Guid guid in newMaterialGUIDs)
                {
                    IMtl mat = Tools.GetIMtlByGuid(guid);
                    if (mat != null)
                    {
                        string name = mat.Name;
                        AnimationGroupMaterial matData = new AnimationGroupMaterial(guid, name);
                        confirmedInfo.AnimationGroupMaterials.Add(matData);
                    }
                }
            }

            ResetChangedTextBoxColors();
            MaxNodeTree.SelectedNode = null;

            InfoChanged?.Invoke(confirmedInfo);
            ConfirmPressed?.Invoke(confirmedInfo);
        }
Пример #21
0
 public override void Do()
 {
    IINodeTab nodeTab = this.nodes.ToIINodeTab();
    this.containerNode = MaxInterfaces.ContainerManager.CreateContainer(nodeTab);
    this.containerNode.SetAFlag(AnimatableFlags.Held);
 }
Пример #22
0
        public void LoadFromData(string propertyName, IINode dataNode)
        {
            if (!Guid.TryParse(propertyName, out serializedId))
            {
                throw new Exception("Invalid ID, can't deserialize.");
            }

            string propertiesString = string.Empty;

            if (!dataNode.GetUserPropString(propertyName, ref propertiesString))
            {
                return;
            }

            string[] properties = propertiesString.Split(s_PropertySeparator);

            if (properties.Length < 4)
            {
                throw new Exception("Invalid number of properties, can't deserialize.");
            }

            // set dirty explicitly just before we start loading, set to false when loading is done
            // if any exception is thrown, it will have a correct value
            IsDirty = true;

            name = properties[0];
            if (!int.TryParse(properties[1], out ticksStart))
            {
                throw new Exception("Failed to parse FrameStart property.");
            }
            if (!int.TryParse(properties[2], out ticksEnd))
            {
                throw new Exception("Failed to parse FrameEnd property.");
            }

            if (string.IsNullOrEmpty(properties[3]))
            {
                return;
            }

            int numNodeIDs = properties.Length - 3;

            if (nodeGuids.Capacity < numNodeIDs)
            {
                nodeGuids.Capacity = numNodeIDs;
            }
            int numFailed = 0;

            for (int i = 0; i < numNodeIDs; ++i)
            {
                Guid guid;
                if (!Guid.TryParse(properties[3 + i], out guid))
                {
                    uint id;
                    if (!uint.TryParse(properties[3 + i], out id))
                    {
                        ++numFailed;
                        continue;
                    }
                    //node is serialized in the old way ,force the reassignation of a new Guid on
                    IINode node = Loader.Core.GetINodeByHandle(id);
                    if (node != null)
                    {
                        guid = node.GetGuid();
                    }
                }
                nodeGuids.Add(guid);
            }

            AnimationGroupNodes = new List <AnimationGroupNode>();
            foreach (Guid nodeGuid in nodeGuids)
            {
                IINode node = Tools.GetINodeByGuid(nodeGuid);

                if (node != null)
                {
                    string             name       = node.Name;
                    string             parentName = node.ParentNode.Name;
                    AnimationGroupNode nodeData   = new AnimationGroupNode(nodeGuid, name, parentName);
                    AnimationGroupNodes.Add(nodeData);
                }
            }

            if (numFailed > 0)
            {
                throw new Exception(string.Format("Failed to parse {0} node ids.", numFailed));
            }

            IsDirty = false;
        }
Пример #23
0
        public void LoadFromJson(string jsonContent, bool merge = false)
        {
            List <string> animationPropertyNameList = Loader.Core.RootNode.GetStringArrayProperty(s_AnimationListPropertyName).ToList();

            if (!merge)
            {
                animationPropertyNameList = new List <string>();
                Clear();
            }

            List <AnimationGroup> animationGroupsData = JsonConvert.DeserializeObject <List <AnimationGroup> >(jsonContent);

            foreach (AnimationGroup animData in animationGroupsData)
            {
                List <Guid> nodeGuids = new List <Guid>();

                if (animData.AnimationGroupNodes != null)
                {
                    string missingNodes = "";
                    string movedNodes   = "";
                    foreach (AnimationGroupNode nodeData in animData.AnimationGroupNodes)
                    {
                        //check here if something changed between export\import
                        // a node handle is reassigned the moment the node is created
                        // it is no possible to have consistency at 100% sure between two file
                        // we need to prevent artists
                        IINode node = Loader.Core.GetINodeByName(nodeData.Name);
                        if (node == null)
                        {
                            //node is missing
                            missingNodes += nodeData.Name + "\n";
                            continue;
                        }

                        if (node.ParentNode.Name != nodeData.ParentName)
                        {
                            //node has been moved in hierarchy
                            movedNodes += node.Name + "\n";
                            continue;
                        }

                        nodeGuids.Add(node.GetGuid());
                    }

                    if (!string.IsNullOrEmpty(movedNodes))
                    {
                        //skip restoration of evaluated animation group
                        nodeGuids = new List <Guid>();
                        MessageBox.Show(string.Format("{0} has been moved in hierarchy,{1} import skipped", movedNodes, animData.Name));
                    }

                    if (!string.IsNullOrEmpty(missingNodes))
                    {
                        //skip restoration of evaluated animation group
                        nodeGuids = new List <Guid>();
                        MessageBox.Show(string.Format("{0} does not exist,{1} import skipped", missingNodes, animData.Name));
                    }
                }

                animData.NodeGuids = nodeGuids;
                string nodes = string.Join(AnimationGroup.s_PropertySeparator.ToString(), animData.NodeGuids);

                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.AppendFormat(AnimationGroup.s_PropertyFormat, animData.Name, animData.TicksStart, animData.TicksEnd, nodes);

                Loader.Core.RootNode.SetStringProperty(animData.SerializedId.ToString(), stringBuilder.ToString());
            }

            foreach (AnimationGroup animData in animationGroupsData)
            {
                string id = animData.SerializedId.ToString();

                if (merge)
                {
                    //if json are merged check if the same animgroup is already in list
                    //and skip in that case
                    if (!animationPropertyNameList.Contains(id))
                    {
                        animationPropertyNameList.Add(animData.SerializedId.ToString());
                    }
                }
                else
                {
                    animationPropertyNameList.Add(animData.SerializedId.ToString());
                }
            }

            Loader.Core.RootNode.SetStringArrayProperty(s_AnimationListPropertyName, animationPropertyNameList);

            LoadFromData(Loader.Core.RootNode);
        }
Пример #24
0
        public static IMatrix3 ExtractCoordinates(IINode meshNode, BabylonAbstractMesh babylonMesh, bool exportQuaternionsInsteadOfEulers)
        {
            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();

            return wm;
        }
Пример #25
0
 public void QueueRemoveNode(IINode node)
 {
     QueueRemoveNode(node.Handle);
 }
Пример #26
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);
        }
Пример #27
0
 public static bool HasParent(this IINode node)
 {
     return(node.ParentNode != null && node.ParentNode.ObjectRef != null);
 }
Пример #28
0
        private static void ResolveMultipleInheritedContainer(IIContainerObject container)
        {
            int b = 0;

            if (container.ContainerNode.GetUserPropBool("flightsim_resolved", ref b))
            {
                return;
            }

            string helperPropBuffer = string.Empty;

            container.BabylonContainerHelper().GetUserPropBuffer(ref helperPropBuffer);

            List <IINode> containerHierarchy = new List <IINode>()
            {
            };

            containerHierarchy.AddRange(container.ContainerNode.ContainerNodeTree(false));

            int containerID = 1;

            container.ContainerNode.GetUserPropInt("babylonjs_ContainerID", ref containerID);

            int    idIndex              = container.ContainerNode.Name.LastIndexOf("_");
            string firstContainer       = container.ContainerNode.Name.Substring(0, idIndex);
            IINode firstContainerObject = Loader.Core.GetINodeByName(firstContainer + "_1");

            if (firstContainerObject == null)
            {
                MessageBox.Show("ERROR resolve ID with FlightSim/BabylonUtilities/UpdateContainerID");
                return;
            }


            //manage multiple containers inherithed from the same source
            foreach (IINode n in containerHierarchy)
            {
                if (n.IsBabylonContainerHelper())
                {
                    continue;
                }
                //change the guid of the node
                //replace the guid in the babylon helper
                string oldGuid = n.GetStringProperty("babylonjs_GUID", Guid.NewGuid().ToString());
                n.DeleteProperty("babylonjs_GUID");
                Guid newGuid = n.GetGuid();
                helperPropBuffer = helperPropBuffer.Replace(oldGuid, newGuid.ToString());

                n.Name = $"{n.Name}_{containerID}";
                if (n.Mtl != null && FlightSimMaterialUtilities.HasFlightSimMaterials(n.Mtl) && FlightSimMaterialUtilities.HasRuntimeAccess(n.Mtl))
                {
                    if (n.Mtl.IsMultiMtl)
                    {
                        throw new Exception($@"Material {n.Mtl.Name} has a property ""Unique In Container"" enabled, cannot be child of a multi material");
                    }
                    else
                    {
                        string cmd = $"mNode = maxOps.getNodeByHandle {n.Handle} \r\n" +
                                     $"newMat = copy mNode.material \r\n" +
                                     $"newMat.name = \"{n.Mtl.Name}_{containerID}\" \r\n" +
                                     $"mNode.material = newMat";

                        MaxscriptSDK.ExecuteMaxscriptCommand(cmd);
                    }
                }
            }

            //replace animationList guid to have distinct list of AnimationGroup for each container
            string animationListStr = string.Empty;

            container.BabylonContainerHelper().GetUserPropString(s_AnimationListPropertyName, ref animationListStr);
            if (!string.IsNullOrEmpty(animationListStr))
            {
                string[] animationGroupGuid = animationListStr.Split(AnimationGroup.s_PropertySeparator);
                foreach (string guidStr in animationGroupGuid)
                {
                    Guid newAnimGroupGuid = Guid.NewGuid();
                    helperPropBuffer = helperPropBuffer.Replace(guidStr, newAnimGroupGuid.ToString());
                }

                container.BabylonContainerHelper().SetUserPropBuffer(helperPropBuffer);

                //add ID of container to animationGroup name to identify animation in viewer
                container.BabylonContainerHelper().GetUserPropString(s_AnimationListPropertyName, ref animationListStr);
                string[] newAnimationGroupGuid = animationListStr.Split(AnimationGroup.s_PropertySeparator);

                foreach (string guidStr in newAnimationGroupGuid)
                {
                    string propertiesString = string.Empty;
                    if (!container.BabylonContainerHelper().GetUserPropString(guidStr, ref propertiesString))
                    {
                        return;
                    }

                    string[] properties = propertiesString.Split(AnimationGroup.s_PropertySeparator);
                    if (properties.Length < 4)
                    {
                        throw new Exception("Invalid number of properties, can't deserialize.");
                    }

                    string name = properties[0];
                    if (!string.IsNullOrEmpty(name))
                    {
                        propertiesString = propertiesString.Replace(name, name + "_" + containerID);
                        container.BabylonContainerHelper().SetUserPropString(guidStr, propertiesString);
                    }
                }
            }
            container.ContainerNode.SetUserPropBool("flightsim_resolved", true);
        }
        /// <summary>
        /// This is the routine to convert the input node to polygon faces.
        /// </summary>
        /// <param name="nodeHandle"> Input the node by handle. </param>
        /// <param name="convertToTri"> Input whether to convert to a poly object first. </param>
        /// <param name="addShell"> Input whether to add the shell modifier when finished converting to face. </param>
        /// <param name="shell"> Input the shell thickness amount. </param>
        /// <param name="addEditMesh"> Input whether to add the Edit Mesh modifier when finished converting to face. </param>
        /// <param name="collapseNode"> Input whether to collapse the node afterwards. </param>
        /// <param name="centerPivot"> Input whether to center the pivot on each new face. </param>
        /// <returns> Returns 1 if successful or -1 if not. </returns>
        static public int ConvertToPolygonFaces(uint nodeHandle,
                                                bool convertToPoly = true, // C# now supports default parameters
                                                bool addShell      = true,
                                                float shell        = 0.1f,
                                                bool addEditMesh   = true,
                                                bool collapseNode  = true,
                                                bool centerPivot   = true)
        {
            try
            {
                IGlobal      global = Autodesk.Max.GlobalInterface.Instance;
                IInterface14 ip     = global.COREInterface14;

                IINode node = ip.GetINodeByHandle(nodeHandle);
                if (node == null)
                {
                    return(-1);
                }

                // Get it's current object state. If a modifier has been applied, for example,
                // it is going to return the OS of the mesh in it's current form in the timeline.
                IObjectState os = node.ObjectRef.Eval(ip.Time);

                // Now grab the object itself.
                IObject objOriginal = os.Obj;

                IPolyObject polyObject = objOriginal as IPolyObject;

                IClass_ID   cid     = global.Class_ID.Create((uint)BuiltInClassIDA.POLYOBJ_CLASS_ID, 0);
                IPolyObject polyObj = ip.CreateInstance(SClass_ID.Geomobject, cid as IClass_ID) as IPolyObject;

                if (polyObject == null && convertToPoly)
                {
                    if (objOriginal.CanConvertToType(global.TriObjectClassID) == 1)
                    {
                        objOriginal = objOriginal.ConvertToType(ip.Time, global.TriObjectClassID);
                    }
                    else
                    {
                        return(-1);
                    }
                    ITriObject triOriginal = objOriginal as ITriObject;
                    polyObj.Mesh.AddTri(triOriginal.Mesh);
                    polyObj.Mesh.FillInMesh();
                    polyObj.Mesh.EliminateBadVerts(0);
                    polyObj.Mesh.MakePolyMesh(0, true);
                }
                else if (polyObject == null)
                {
                    polyObj = polyObject;
                }
                else
                {
                    return(-1);
                }

                IMatrix3    mat              = node.GetNodeTM(0, null);
                IPoint3     ptOffsetPos      = node.ObjOffsetPos;
                IQuat       quatOffsetRot    = node.ObjOffsetRot;
                IScaleValue scaleOffsetScale = node.ObjOffsetScale;

                // We can grab the faces as a List and iterate them in .NET API.

                int nNumFaces = polyObj.Mesh.FNum;
                if (m_bUsingProgress)
                {
                    m_ctrlProgress.PB_ProgressMaxNum = nNumFaces;
                }

                ADN_UserBreakCheck checkUserBreak = new ADN_UserBreakCheck();

                for (int i = 0; i < nNumFaces; i++)
                {
                    if (checkUserBreak.Check() == true)
                    {
                        return(-1);
                    }
                    if (m_bUsingProgress)
                    {
                        m_ctrlProgress.PB_ProgressCurrNum = i;
                    }

                    // Create a new poly object for each new face.
                    object objectNewFace = ip.CreateInstance(SClass_ID.Geomobject, cid as IClass_ID);

                    // Create a new node to hold it in the scene.
                    IObject objNewFace = (IObject)objectNewFace;
                    IINode  n          = global.COREInterface.CreateObjectNode(objNewFace);

                    // Name it and ensure it is unique...
                    string newname = "ADN-Sample-Face";
                    ip.MakeNameUnique(ref newname);
                    n.Name = newname;

                    // Based on what we created above, we can safely cast it to TriObject
                    IPolyObject polyNewFace = objNewFace as IPolyObject;

                    // Setup the new poly object with 1 face, and the vertex count from the original object's face we are processing
                    polyNewFace.Mesh.SetNumFaces(1);
                    polyNewFace.Mesh.SetMapNum(2);
                    IMNFace f = polyObj.Mesh.F(i);

                    polyNewFace.Mesh.F(0).Assign(f);

                    IMNFace fnew = polyNewFace.Mesh.F(0);

                    IList <int> vtx = f.Vtx;

                    polyNewFace.Mesh.SetNumVerts(vtx.Count);
                    for (int k = 0; k < vtx.Count; k++)
                    {
                        int     nvindex = vtx[k];
                        IMNVert vert    = polyObj.Mesh.V(nvindex);
                        Debug.Print("\nVertex = " + k + ", " + nvindex);
                        polyNewFace.Mesh.V(k).Assign(vert);
                        fnew.Vtx[k] = k;
                    }


                    int     nedge = nedge = polyNewFace.Mesh.SimpleNewEdge(0, 1);
                    IMNEdge edge  = polyNewFace.Mesh.E(nedge);
                    edge.Track = -1;
                    edge.F1    = 0;
                    edge.F2    = -1;
                    polyNewFace.Mesh.SetEdgeVis(nedge, true);

                    nedge      = polyNewFace.Mesh.SimpleNewEdge(1, 2);
                    edge       = polyNewFace.Mesh.E(nedge);
                    edge.Track = -1;
                    edge.F1    = 0;
                    edge.F2    = -1;
                    polyNewFace.Mesh.SetEdgeVis(nedge, true);

                    nedge      = polyNewFace.Mesh.SimpleNewEdge(2, 3);
                    edge       = polyNewFace.Mesh.E(nedge);
                    edge.Track = -1;
                    edge.F1    = 0;
                    edge.F2    = -1;
                    polyNewFace.Mesh.SetEdgeVis(nedge, true);

                    nedge      = polyNewFace.Mesh.SimpleNewEdge(3, 0);
                    edge       = polyNewFace.Mesh.E(nedge);
                    edge.Track = -1;
                    edge.F1    = 0;
                    edge.F2    = -1;
                    polyNewFace.Mesh.SetEdgeVis(nedge, true);

                    polyNewFace.Mesh.FillInMesh();
                    // make it update.
                    polyNewFace.Mesh.InvalidateGeomCache();

                    if (addShell)
                    {
                        AddOsmShell(n.Handle, shell);
                    }

                    if (addEditMesh)
                    {
                        AddOsmEditMesh(n.Handle);
                    }

                    if (collapseNode)
                    {
                        ip.CollapseNode(n, true);
                    }

                    // update transform to match object being exploded.
                    n.SetNodeTM(0, mat);
                    n.ObjOffsetPos   = ptOffsetPos;
                    n.ObjOffsetRot   = quatOffsetRot;
                    n.ObjOffsetScale = scaleOffsetScale;
                    n.ObjOffsetPos   = ptOffsetPos;
                    if (centerPivot)
                    {
                        n.CenterPivot(0, false);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
                return(-1);
            }

            return(1);
        }
Пример #30
0
        public static AnimationGroupList InitAnimationGroups(ILoggingProvider logger)
        {
            AnimationGroupList animationList = new AnimationGroupList();

            animationList.LoadFromData(Loader.Core.RootNode);

            if (animationList.Count > 0)
            {
                int timelineStart = Loader.Core.AnimRange.Start / Loader.Global.TicksPerFrame;
                int timelineEnd   = Loader.Core.AnimRange.End / Loader.Global.TicksPerFrame;

                List <string> warnings = new List <string>();
                foreach (AnimationGroup animGroup in animationList)
                {
                    // ensure min <= start <= end <= max
                    warnings.Clear();
                    if (animGroup.FrameStart < timelineStart || animGroup.FrameStart > timelineEnd)
                    {
                        warnings.Add("Start frame '" + animGroup.FrameStart + "' outside of timeline range [" + timelineStart + ", " + timelineEnd + "]. Set to timeline start time '" + timelineStart + "'");
                        animGroup.FrameStart = timelineStart;
                    }
                    if (animGroup.FrameEnd < timelineStart || animGroup.FrameEnd > timelineEnd)
                    {
                        warnings.Add("End frame '" + animGroup.FrameEnd + "' outside of timeline range [" + timelineStart + ", " + timelineEnd + "]. Set to timeline end time '" + timelineEnd + "'");
                        animGroup.FrameEnd = timelineEnd;
                    }
                    if (animGroup.FrameEnd <= animGroup.FrameStart)
                    {
                        if (animGroup.FrameEnd < animGroup.FrameStart)
                        {
                            // Strict
                            warnings.Add("End frame '" + animGroup.FrameEnd + "' lower than Start frame '" + animGroup.FrameStart + "'. Start frame set to timeline start time '" + timelineStart + "'. End frame set to timeline end time '" + timelineEnd + "'.");
                        }
                        else
                        {
                            // Equal
                            warnings.Add("End frame '" + animGroup.FrameEnd + "' equal to Start frame '" + animGroup.FrameStart + "'. Single frame animation are not allowed. Start frame set to timeline start time '" + timelineStart + "'. End frame set to timeline end time '" + timelineEnd + "'.");
                        }

                        animGroup.FrameStart = timelineStart;
                        animGroup.FrameEnd   = timelineEnd;
                    }
                    foreach (Guid guid in animGroup.NodeGuids)
                    {
                        IINode node = Tools.GetINodeByGuid(guid);
                        if (node != null)
                        {
                            if (!(node.TMController.IsKeyAtTime(animGroup.TicksStart, (1 << 0)) || node.TMController.IsKeyAtTime(animGroup.TicksStart, (1 << 1)) || node.TMController.IsKeyAtTime(animGroup.TicksStart, (1 << 2))))
                            {
                                int    key = animGroup.TicksStart / 160;
                                string msg = string.Format("Node {0} has no key on min frame: {1} of animation group {2}", node.NodeName, key, animGroup.Name);
                                warnings.Add(msg);
                            }
                            if (!(node.TMController.IsKeyAtTime(animGroup.TicksEnd, (1 << 0)) || node.TMController.IsKeyAtTime(animGroup.TicksEnd, (1 << 1)) || node.TMController.IsKeyAtTime(animGroup.TicksEnd, (1 << 2))))
                            {
                                int    key = animGroup.TicksEnd / 160;
                                string msg = string.Format("Node {0} has no key on max frame: {1} of animation group {2}", node.NodeName, key, animGroup.Name);
                                warnings.Add(msg);
                            }
                        }
                    }

                    // Print animation group warnings if any
                    // Nothing printed otherwise
                    if (warnings.Count > 0)
                    {
                        logger.RaiseWarning(animGroup.Name, 1);
                        foreach (string warning in warnings)
                        {
                            logger.RaiseWarning(warning, 2);
                        }
                    }
                }
            }

            return(animationList);
        }
Пример #31
0
 public static Guid GetGuid(this IINode node)
 {
     return(GetGuid(Animatable.CreateWrapper <Node>(node)));
 }
Пример #32
0
        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 ESM");

            switch (shadowsType)
            {
            case "Hard shadows":
                break;

            case "Poisson Sampling":
                babylonShadowGenerator.usePoissonSampling = true;
                break;

            case "ESM":
                babylonShadowGenerator.useExponentialShadowMap = true;
                break;

            case "Blurred ESM":
                babylonShadowGenerator.useBlurExponentialShadowMap = 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 || MAX2018
                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);
        }
Пример #33
0
        public static void UpdateCheckBox(CheckBox checkBox, IINode node, string propertyName)
        {
            if (checkBox.CheckState != CheckState.Indeterminate)
            {
#if MAX2015 || MAX2016
                node.SetUserPropBool(propertyName, checkBox.CheckState == CheckState.Checked);
#else
                node.SetUserPropBool(ref propertyName, checkBox.CheckState == CheckState.Checked);
#endif
            }
        }
Пример #34
0
 private void CreateFacesFromNode(IINode node)
 {
 }
Пример #35
0
        public static void UpdateVector3Control(Vector3Control vector3Control, IINode node, string propertyName)
        {
            string name = propertyName + "_x";
#if MAX2015 || MAX2016
            node.SetUserPropFloat(name, vector3Control.X);
#else
            node.SetUserPropFloat(ref name, vector3Control.X);
#endif

            name = propertyName + "_y";
#if MAX2015 || MAX2016
            node.SetUserPropFloat(name, vector3Control.Y);
#else
            node.SetUserPropFloat(ref name, vector3Control.Y);
#endif

            name = propertyName + "_z";
#if MAX2015 || MAX2016
            node.SetUserPropFloat(name, vector3Control.Z);
#else
            node.SetUserPropFloat(ref name, vector3Control.Z);
#endif
        }
        /// <summary>
        /// This is the routine to convert the input node to triangle faces.
        /// </summary>
        /// <param name="nodeHandle"> Input the node by handle. </param>
        /// <param name="convertToTri"> Input whether to convert to a tri object first. </param>
        /// <param name="addShell"> Input whether to add the shell modifier when finished converting to face. </param>
        /// <param name="shell"> Input the shell thickness amount. </param>
        /// <param name="addEditMesh"> Input whether to add the Edit Mesh modifier when finished converting to face. </param>
        /// <param name="collapseNode"> Input whether to collapse the node afterwards. </param>
        /// <param name="centerPivot"> Input whether to center the pivot on each new face. </param>
        /// <returns> Returns 1 if successful or -1 if not. </returns>
        static public int ConvertToTriangleFaces(uint nodeHandle,
                                                 bool convertToTri = true, // C# now supports default parameters
                                                 bool addShell     = true,
                                                 float shell       = 0.1f,
                                                 bool addEditMesh  = true,
                                                 bool collapseNode = true,
                                                 bool centerPivot  = true)
        {
            try
            {
                IGlobal      global = Autodesk.Max.GlobalInterface.Instance;
                IInterface14 ip     = global.COREInterface14;

                IINode node = ip.GetINodeByHandle(nodeHandle);

                // Get it's current object state. If a modifier has been applied, for example,
                // it is going to return the OS of the mesh in it's current form in the timeline.
                IObjectState os = node.ObjectRef.Eval(ip.Time);

                // Now grab the object itself.
                IObject objOriginal = os.Obj;

                // Let's make sure it is a TriObject, which is the typical kind of object with a mesh
                if (!objOriginal.IsSubClassOf(global.TriObjectClassID))
                {
                    // If it is NOT, see if we can convert it...
                    if (convertToTri && objOriginal.CanConvertToType(global.TriObjectClassID) == 1)
                    {
                        objOriginal = objOriginal.ConvertToType(ip.Time, global.TriObjectClassID);
                    }
                    else
                    {
                        return(-1);
                    }
                }

                // Now we should be safe to know it is a TriObject and we can cast it as such.
                // An exception will be thrown...
                ITriObject triOriginal = objOriginal as ITriObject;


                // Let's first setup a class ID for the type of objects are are creating.
                // New TriObject in this case to hold each face.
                IClass_ID cid = global.Class_ID.Create((uint)BuiltInClassIDA.TRIOBJ_CLASS_ID, 0);

                IMatrix3    mat              = node.GetNodeTM(0, null);
                IPoint3     ptOffsetPos      = node.ObjOffsetPos;
                IQuat       quatOffsetRot    = node.ObjOffsetRot;
                IScaleValue scaleOffsetScale = node.ObjOffsetScale;

                // We can grab the faces as a List and iterate them in .NET API.
                IMesh         mesh  = triOriginal.Mesh;
                IList <IFace> faces = triOriginal.Mesh.Faces;

                int nNumFaces = faces.Count;
                if (m_bUsingProgress)
                {
                    m_ctrlProgress.PB_ProgressMaxNum = nNumFaces;
                }

                ADN_UserBreakCheck checkUserBreak = new ADN_UserBreakCheck();
                int count = 0;
                foreach (IFace face in faces)
                {
                    if (checkUserBreak.Check() == true)
                    {
                        return(-1);
                    }
                    if (m_bUsingProgress)
                    {
                        m_ctrlProgress.PB_ProgressCurrNum = ++count;
                    }

                    // Create a new TriObject for each new face.
                    object objectNewFace = ip.CreateInstance(SClass_ID.Geomobject, cid as IClass_ID);

                    // Create a new node to hold it in the scene.
                    IObject objNewFace = (IObject)objectNewFace;
                    IINode  n          = global.COREInterface.CreateObjectNode(objNewFace);

                    // Name it and ensure it is unique...
                    string newname = "ADN-Sample-Face";
                    ip.MakeNameUnique(ref newname);
                    n.Name = newname;

                    // Based on what we created above, we can safely cast it to TriObject
                    ITriObject triNewFace = objNewFace as ITriObject;

                    // Setup the new TriObject with 1 face, and the vertex count from the original object's face we are processing
                    triNewFace.Mesh.SetNumFaces(1, false, false);
                    triNewFace.Mesh.SetNumVerts(face.V.Count(), false, false);

                    // Finish setting up the face (always face '0' because there will only be one per object).
                    triNewFace.Mesh.Faces[0].SetVerts(0, 1, 2);
                    triNewFace.Mesh.Faces[0].SetEdgeVisFlags(EdgeVisibility.Vis, EdgeVisibility.Vis, EdgeVisibility.Vis);
                    triNewFace.Mesh.Faces[0].SmGroup = 2;

                    // Now, for each vertex, get the old face's points and store into new.
                    for (int i = 0; i < face.V.Count(); i++)
                    {
                        //Get the vertex from the original object's face we are processing
                        IPoint3 point = triOriginal.Mesh.GetVert((int)face.GetVert(i));
                        // Set the vertex point in the new face vertex
                        triNewFace.Mesh.SetVert(i, point);
                    }

                    // make it draw.
                    triNewFace.Mesh.InvalidateGeomCache();

                    if (addShell)
                    {
                        AddOsmShell(n.Handle, shell);
                    }

                    if (addEditMesh)
                    {
                        AddOsmEditMesh(n.Handle);
                    }

                    if (collapseNode)
                    {
                        ip.CollapseNode(n, true);
                    }

                    // update transform to match object being exploded.
                    n.SetNodeTM(0, mat);
                    n.ObjOffsetPos   = ptOffsetPos;
                    n.ObjOffsetRot   = quatOffsetRot;
                    n.ObjOffsetScale = scaleOffsetScale;
                    n.ObjOffsetPos   = ptOffsetPos;
                    if (centerPivot)
                    {
                        n.CenterPivot(0, false);
                    }
                }
            }
            catch (Exception)
            {
                return(-1);
            }

            return(1);
        }
        private void ExportAnimationGroups(GLTF gltf, BabylonScene babylonScene)
        {
            // Retreive and parse animation group data
            AnimationGroupList animationList = InitAnimationGroups();

            gltf.AnimationsList.Clear();
            gltf.AnimationsList.Capacity = Math.Max(gltf.AnimationsList.Capacity, animationList.Count);

            if (animationList.Count <= 0)
            {
                RaiseMessage("GLTFExporter.Animation | No AnimationGroups: exporting all animations together.", 1);
                GLTFAnimation gltfAnimation = new GLTFAnimation();
                gltfAnimation.name = "All Animations";

                int minFrame = Loader.Core.AnimRange.Start / Loader.Global.TicksPerFrame;
                int maxFrame = Loader.Core.AnimRange.End / Loader.Global.TicksPerFrame;

                foreach (var pair in nodeToGltfNodeMap)
                {
                    ExportNodeAnimation(gltfAnimation, minFrame, maxFrame, gltf, pair.Key, pair.Value, babylonScene);
                }
                foreach (var pair in boneToGltfNodeMap)
                {
                    ExportBoneAnimation(gltfAnimation, minFrame, maxFrame, gltf, pair.Key, pair.Value);
                }

                if (gltfAnimation.ChannelList.Count > 0)
                {
                    gltf.AnimationsList.Add(gltfAnimation);
                }
                else
                {
                    RaiseMessage("GLTFExporter.Animation | No animation data for this animation, it is ignored.", 2);
                }
            }
            else
            {
                foreach (AnimationGroup animGroup in animationList)
                {
                    RaiseMessage("GLTFExporter.Animation | " + animGroup.Name, 1);

                    GLTFAnimation gltfAnimation = new GLTFAnimation();
                    gltfAnimation.name = animGroup.Name;

                    int startFrame = animGroup.FrameStart;
                    int endFrame   = animGroup.FrameEnd;

                    foreach (uint nodeHandle in animGroup.NodeHandles)
                    {
                        // todo: make something a little more efficient..
                        IINode maxNode = Loader.Core.RootNode.FindChildNode(nodeHandle);

                        // node could have been deleted, silently ignore it
                        if (maxNode == null)
                        {
                            continue;
                        }

                        string      id          = maxNode.GetGuid().ToString();
                        BabylonNode babylonNode = babylonNodes.Find(node => node.id.Equals(id));

                        if (babylonNode != null && nodeToGltfNodeMap.TryGetValue(babylonNode, out GLTFNode gltfNode))
                        {
                            ExportNodeAnimation(gltfAnimation, startFrame, endFrame, gltf, babylonNode, gltfNode, babylonScene);
                        }

                        // export all bones that match this id
                        foreach (KeyValuePair <BabylonBone, GLTFNode> pair in boneToGltfNodeMap)
                        {
                            if (pair.Key.id.Equals(id))
                            {
                                ExportBoneAnimation(gltfAnimation, startFrame, endFrame, gltf, pair.Key, pair.Value);
                            }
                        }
                    }

                    if (gltfAnimation.ChannelList.Count > 0)
                    {
                        gltf.AnimationsList.Add(gltfAnimation);
                    }
                    else
                    {
                        RaiseMessage("No data exported for this animation, it is ignored.", 2);
                    }
                }
            }
        }
Пример #38
0
        public void Export(ExportParameters exportParameters)
        {
            var watch = new Stopwatch();

            watch.Start();

            this.exportParameters = exportParameters;
            IINode exportNode = null;

            if (exportParameters is MaxExportParameters)
            {
                MaxExportParameters maxExporterParameters = (exportParameters as MaxExportParameters);
                exportNode = maxExporterParameters.exportNode;
                if (maxExporterParameters.flattenScene)
                {
                    FlattenHierarchy(exportNode);
                }
                if (maxExporterParameters.mergeContainersAndXRef)
                {
                    ExportClosedContainers();
                    Tools.MergeAllXrefRecords();
                }
            }

            Tools.InitializeGuidNodesMap();

            string fileExportString = exportNode != null? $"{exportNode.NodeName} | {exportParameters.outputPath}": exportParameters.outputPath;

            RaiseMessage($"Exportation started: {fileExportString}", Color.Blue);

#if DEBUG
            var containersXrefMergeTime = watch.ElapsedMilliseconds / 1000.0;
            RaiseMessage(string.Format("Containers and Xref  merged in {0:0.00}s", containersXrefMergeTime), Color.Blue);
#endif

            this.scaleFactor = Tools.GetScaleFactorToMeters();

            var scaleFactorFloat = 1.0f;
            // Check input text is valid
            float scaleFactor = exportParameters.scaleFactor;

            long quality = exportParameters.txtQuality;
            try
            {
                if (quality < 0 || quality > 100)
                {
                    throw new Exception();
                }
            }
            catch
            {
                RaiseError("Quality is not a valid number. It should be an integer between 0 and 100.");
                RaiseError("This parameter sets the quality of jpg compression.");
                return;
            }



            var gameConversionManger = Loader.Global.ConversionManager;
            gameConversionManger.CoordSystem = Autodesk.Max.IGameConversionManager.CoordSystem.D3d;

            var gameScene = Loader.Global.IGameInterface;
            if (exportNode == null || exportNode.IsRootNode)
            {
                gameScene.InitialiseIGame(false);
            }
            else
            {
                gameScene.InitialiseIGame(exportNode, true);
            }

            gameScene.SetStaticFrame(0);

            MaxSceneFileName = gameScene.SceneFileName;

            IsCancelled = false;


            ReportProgressChanged(0);

            string tempOutputDirectory  = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
            string outputDirectory      = Path.GetDirectoryName(exportParameters.outputPath);
            string folderOuputDirectory = exportParameters.textureFolder;
            string outputFileName       = Path.GetFileName(exportParameters.outputPath);

            // Check directory exists
            if (!Directory.Exists(outputDirectory))
            {
                RaiseError("Exportation stopped: Output folder does not exist");
                ReportProgressChanged(100);
                return;
            }
            Directory.CreateDirectory(tempOutputDirectory);

            var outputBabylonDirectory = tempOutputDirectory;

            // Force output file extension to be babylon
            outputFileName = Path.ChangeExtension(outputFileName, "babylon");

            var babylonScene = new BabylonScene(outputBabylonDirectory);

            var rawScene = Loader.Core.RootNode;



            string outputFormat = exportParameters.outputFormat;
            isBabylonExported = outputFormat == "babylon" || outputFormat == "binary babylon";
            isGltfExported    = outputFormat == "gltf" || outputFormat == "glb";

            // Get scene parameters
            optimizeAnimations = !Loader.Core.RootNode.GetBoolProperty("babylonjs_donotoptimizeanimations");
            exportNonAnimated  = Loader.Core.RootNode.GetBoolProperty("babylonjs_animgroup_exportnonanimated");

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

                callerForm?.BringToFront();
            }

            // Producer
            babylonScene.producer = new BabylonProducer
            {
                name = "3dsmax",
#if MAX2020
                version = "2020",
#elif MAX2019
                version = "2019",
#elif MAX2018
                version = "2018",
#elif MAX2017
                version = "2017",
#else
                version = Loader.Core.ProductVersion.ToString(),
#endif
                exporter_version = exporterVersion,
                file             = outputFileName
            };

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

            babylonScene.TimelineStartFrame      = Loader.Core.AnimRange.Start / Loader.Global.TicksPerFrame;
            babylonScene.TimelineEndFrame        = Loader.Core.AnimRange.End / Loader.Global.TicksPerFrame;
            babylonScene.TimelineFramesPerSecond = MaxSceneTicksPerSecond / Loader.Global.TicksPerFrame;

            babylonScene.gravity             = rawScene.GetVector3Property("babylonjs_gravity");
            ExportQuaternionsInsteadOfEulers = rawScene.GetBoolProperty("babylonjs_exportquaternions", 1);
            if (string.IsNullOrEmpty(exportParameters.pbrEnvironment) && Loader.Core.UseEnvironmentMap && Loader.Core.EnvironmentMap != null)
            {
                // Environment texture
                var environmentMap = Loader.Core.EnvironmentMap;
                // Copy image file to output if necessary
                var babylonTexture = ExportEnvironmnentTexture(environmentMap, babylonScene);
                if (babylonTexture != null)
                {
                    babylonScene.environmentTexture = babylonTexture.name;

                    // Skybox
                    babylonScene.createDefaultSkybox = rawScene.GetBoolProperty("babylonjs_createDefaultSkybox");
                    babylonScene.skyboxBlurLevel     = rawScene.GetFloatProperty("babylonjs_skyboxBlurLevel");
                }
            }
            else if (!string.IsNullOrEmpty(exportParameters.pbrEnvironment))
            {
                babylonScene.createDefaultSkybox = rawScene.GetBoolProperty("babylonjs_createDefaultSkybox");
                babylonScene.skyboxBlurLevel     = rawScene.GetFloatProperty("babylonjs_skyboxBlurLevel");
            }

            // Instantiate custom material exporters
            materialExporters = new Dictionary <ClassIDWrapper, IMaxMaterialExporter>();
            foreach (Type type in Tools.GetAllLoadableTypes())
            {
                if (type.IsAbstract || type.IsInterface || !typeof(IMaxMaterialExporter).IsAssignableFrom(type))
                {
                    continue;
                }

                IMaxMaterialExporter exporter = Activator.CreateInstance(type) as IMaxMaterialExporter;

                if (exporter == null)
                {
                    RaiseWarning("Creating exporter instance failed: " + type.Name, 1);
                }

                materialExporters.Add(exporter.MaterialClassID, exporter);
            }

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

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

            // Root nodes
            RaiseMessage("Exporting nodes");
            HashSet <IIGameNode> maxRootNodes = getRootNodes(gameScene);
            var progressionStep = 80.0f / maxRootNodes.Count;
            var progression     = 10.0f;
            ReportProgressChanged((int)progression);
            referencedMaterials.Clear();

            // Reseting is optionnal. It makes each morph target manager export starts from id = 0.
            BabylonMorphTargetManager.Reset();
            foreach (var maxRootNode in maxRootNodes)
            {
                BabylonNode node = exportNodeRec(maxRootNode, babylonScene, gameScene);

                // if we're exporting from a specific node, reset the pivot to {0,0,0}
                if (node != null && exportNode != null && !exportNode.IsRootNode)
                {
                    SetNodePosition(ref node, ref babylonScene, new float[] { 0, 0, 0 });
                }

                progression += progressionStep;
                ReportProgressChanged((int)progression);
                CheckCancelled();
            }
            ;
            RaiseMessage(string.Format("Total meshes: {0}", babylonScene.MeshesList.Count), Color.Gray, 1);


            // In 3DS Max the default camera look down (in the -z direction for the 3DS Max reference (+y for babylon))
            // In Babylon the default camera look to the horizon (in the +z direction for the babylon reference)
            // In glTF the default camera look to the horizon (in the +Z direction for glTF reference)
            RaiseMessage("Update camera rotation and position", 1);
            for (int index = 0; index < babylonScene.CamerasList.Count; index++)
            {
                BabylonCamera camera = babylonScene.CamerasList[index];
                FixCamera(ref camera, ref babylonScene);
            }

            // Light for glTF
            if (isGltfExported)
            {
                RaiseMessage("Update light rotation for glTF export", 1);
                for (int index = 0; index < babylonScene.LightsList.Count; index++)
                {
                    BabylonNode light = babylonScene.LightsList[index];
                    FixNodeRotation(ref light, ref babylonScene, -Math.PI / 2);
                }
            }

            // Main camera
            BabylonCamera babylonMainCamera   = null;
            ICameraObject maxMainCameraObject = null;
            if (babylonMainCamera == null && babylonScene.CamerasList.Count > 0)
            {
                // Set first camera as main one
                babylonMainCamera           = babylonScene.CamerasList[0];
                babylonScene.activeCameraID = babylonMainCamera.id;
                RaiseMessage("Active camera set to " + babylonMainCamera.name, Color.Green, 1, true);

                // Retreive camera node with same GUID
                var maxCameraNodesAsTab = gameScene.GetIGameNodeByType(Autodesk.Max.IGameObject.ObjectTypes.Camera);
                var maxCameraNodes      = TabToList(maxCameraNodesAsTab);
                var maxMainCameraNode   = maxCameraNodes.Find(_camera => _camera.MaxNode.GetGuid().ToString() == babylonMainCamera.id);
                maxMainCameraObject = (maxMainCameraNode.MaxNode.ObjectRef as ICameraObject);
            }

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

            // Default light
            bool addDefaultLight = rawScene.GetBoolProperty("babylonjs_addDefaultLight", 1);
            if (!exportParameters.pbrNoLight && addDefaultLight && 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 lights: {0}", babylonScene.LightsList.Count), Color.Gray, 1);
            }

            if (scaleFactorFloat != 1.0f)
            {
                RaiseMessage("A root node is added for scaling", 1);

                // Create root node for scaling
                BabylonMesh rootNode = new BabylonMesh {
                    name = "root", id = Guid.NewGuid().ToString()
                };
                rootNode.isDummy = true;
                float rootNodeScale = scaleFactorFloat;
                rootNode.scaling = new float[3] {
                    rootNodeScale, rootNodeScale, rootNodeScale
                };

                if (ExportQuaternionsInsteadOfEulers)
                {
                    rootNode.rotationQuaternion = new float[] { 0, 0, 0, 1 };
                }
                else
                {
                    rootNode.rotation = new float[] { 0, 0, 0 };
                }

                // Update all top nodes
                var babylonNodes = new List <BabylonNode>();
                babylonNodes.AddRange(babylonScene.MeshesList);
                babylonNodes.AddRange(babylonScene.CamerasList);
                babylonNodes.AddRange(babylonScene.LightsList);
                foreach (BabylonNode babylonNode in babylonNodes)
                {
                    if (babylonNode.parentId == null)
                    {
                        babylonNode.parentId = rootNode.id;
                    }
                }

                // Store root node
                babylonScene.MeshesList.Add(rootNode);
            }

            // Materials
            if (exportParameters.exportMaterials)
            {
                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);
            }
            else
            {
                RaiseMessage("Skipping material export.");
            }

            // 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 (babylonMainCamera != null)
                    {
                        babylonScene.fogStart = maxMainCameraObject.GetEnvRange(0, 0, Tools.Forever);
                        babylonScene.fogEnd   = maxMainCameraObject.GetEnvRange(0, 1, Tools.Forever);
                    }
                }
            }

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

#if DEBUG
            var nodesExportTime = watch.ElapsedMilliseconds / 1000.0 - containersXrefMergeTime;
            RaiseMessage(string.Format("Noded exported in {0:0.00}s", nodesExportTime), Color.Blue);
#endif

            // ----------------------------
            // ----- Animation groups -----
            // ----------------------------
            RaiseMessage("Export animation groups");
            // add animation groups to the scene
            babylonScene.animationGroups = ExportAnimationGroups(babylonScene);
#if DEBUG
            var animationGroupExportTime = watch.ElapsedMilliseconds / 1000.0 - nodesExportTime;
            RaiseMessage(string.Format("Animation groups exported in {0:0.00}s", animationGroupExportTime), Color.Blue);
#endif

            if (isBabylonExported)
            {
                // if we are exporting to .Babylon then remove then remove animations from nodes if there are animation groups.
                if (babylonScene.animationGroups.Count > 0)
                {
                    foreach (BabylonNode node in babylonScene.MeshesList)
                    {
                        node.animations = null;
                    }
                    foreach (BabylonNode node in babylonScene.LightsList)
                    {
                        node.animations = null;
                    }
                    foreach (BabylonNode node in babylonScene.CamerasList)
                    {
                        node.animations = null;
                    }
                    foreach (BabylonSkeleton skel in babylonScene.SkeletonsList)
                    {
                        foreach (BabylonBone bone in skel.bones)
                        {
                            bone.animation = null;
                        }
                    }
                }

                // setup a default skybox for the scene for .Babylon export.
                var sourcePath = exportParameters.pbrEnvironment;
                if (!string.IsNullOrEmpty(sourcePath))
                {
                    var fileName = Path.GetFileName(sourcePath);

                    // Allow only dds file format
                    if (!fileName.EndsWith(".dds"))
                    {
                        RaiseWarning("Failed to export defauenvironment texture: only .dds format is supported.");
                    }
                    else
                    {
                        RaiseMessage($"texture id = Max_Babylon_Default_Environment");
                        babylonScene.environmentTexture = fileName;

                        if (exportParameters.writeTextures)
                        {
                            try
                            {
                                var destPath = Path.Combine(babylonScene.OutputPath, fileName);
                                if (File.Exists(sourcePath) && sourcePath != destPath)
                                {
                                    File.Copy(sourcePath, destPath, true);
                                }
                            }
                            catch
                            {
                                // silently fails
                                RaiseMessage($"Fail to export the default env texture", 3);
                            }
                        }
                    }
                }
            }

            // Output
            babylonScene.Prepare(false, false);
            if (isBabylonExported)
            {
                RaiseMessage("Saving to output file");

                var outputFile = Path.Combine(outputBabylonDirectory, outputFileName);

                var jsonSerializer = JsonSerializer.Create(new JsonSerializerSettings());
                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());

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

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

            ReportProgressChanged(100);

            // Export glTF
            if (isGltfExported)
            {
                bool generateBinary = outputFormat == "glb";

                GLTFExporter gltfExporter = new GLTFExporter();
                exportParameters.customGLTFMaterialExporter = new MaxGLTFMaterialExporter(exportParameters, gltfExporter, this);
                gltfExporter.ExportGltf(this.exportParameters, babylonScene, tempOutputDirectory, outputFileName, generateBinary, this);
            }
            // Move files to output directory
            var filePaths = Directory.GetFiles(tempOutputDirectory);
            if (outputFormat == "binary babylon")
            {
                var tempBinaryOutputDirectory = Path.Combine(tempOutputDirectory, "Binary");
                var binaryFilePaths           = Directory.GetFiles(tempBinaryOutputDirectory);
                foreach (var filePath in binaryFilePaths)
                {
                    if (filePath.EndsWith(".binary.babylon"))
                    {
                        var file         = Path.GetFileName(filePath);
                        var tempFilePath = Path.Combine(tempBinaryOutputDirectory, file);
                        var outputFile   = Path.Combine(outputDirectory, file);

                        IUTF8Str maxNotification = GlobalInterface.Instance.UTF8Str.Create(outputFile);
                        Loader.Global.BroadcastNotification(SystemNotificationCode.PreExport, maxNotification);
                        moveFileToOutputDirectory(tempFilePath, outputFile, exportParameters);
                        Loader.Global.BroadcastNotification(SystemNotificationCode.PostExport, maxNotification);
                    }
                    else if (filePath.EndsWith(".babylonbinarymeshdata"))
                    {
                        var file         = Path.GetFileName(filePath);
                        var tempFilePath = Path.Combine(tempBinaryOutputDirectory, file);
                        var outputFile   = Path.Combine(outputDirectory, file);

                        IUTF8Str maxNotification = GlobalInterface.Instance.UTF8Str.Create(outputFile);
                        Loader.Global.BroadcastNotification(SystemNotificationCode.PreExport, maxNotification);
                        moveFileToOutputDirectory(tempFilePath, outputFile, exportParameters);
                        Loader.Global.BroadcastNotification(SystemNotificationCode.PostExport, maxNotification);
                    }
                }
            }
            if (outputFormat == "glb")
            {
                foreach (var file_path in filePaths)
                {
                    if (Path.GetExtension(file_path) == ".glb")
                    {
                        var file         = Path.GetFileName(file_path);
                        var tempFilePath = Path.Combine(tempOutputDirectory, file);
                        var outputFile   = Path.Combine(outputDirectory, file);


                        IUTF8Str maxNotification = GlobalInterface.Instance.UTF8Str.Create(outputFile);
                        Loader.Global.BroadcastNotification(SystemNotificationCode.PreExport, maxNotification);
                        moveFileToOutputDirectory(tempFilePath, outputFile, exportParameters);
                        Loader.Global.BroadcastNotification(SystemNotificationCode.PostExport, maxNotification);

                        break;
                    }
                }
            }
            else
            {
                foreach (var filePath in filePaths)
                {
                    var    file         = Path.GetFileName(filePath);
                    string ext          = Path.GetExtension(file);
                    var    tempFilePath = Path.Combine(tempOutputDirectory, file);
                    var    outputPath   = Path.Combine(outputDirectory, file);
                    if (!string.IsNullOrWhiteSpace(exportParameters.textureFolder) && TextureUtilities.ExtensionIsValidGLTFTexture(ext))
                    {
                        outputPath = Path.Combine(exportParameters.textureFolder, file);
                    }

                    IUTF8Str maxNotification = GlobalInterface.Instance.UTF8Str.Create(outputPath);
                    Loader.Global.BroadcastNotification(SystemNotificationCode.PreExport, maxNotification);
                    moveFileToOutputDirectory(tempFilePath, outputPath, exportParameters);
                    Loader.Global.BroadcastNotification(SystemNotificationCode.PostExport, maxNotification);
                }
            }
            Directory.Delete(tempOutputDirectory, true);
            watch.Stop();

            RaiseMessage(string.Format("Exportation done in {0:0.00}s: {1}", watch.ElapsedMilliseconds / 1000.0, fileExportString), Color.Blue);
            IUTF8Str max_notification = Autodesk.Max.GlobalInterface.Instance.UTF8Str.Create("BabylonExportComplete");
            Loader.Global.BroadcastNotification(SystemNotificationCode.PostExport, max_notification);
        }
        private IList <BabylonAnimationGroup> ExportAnimationGroups(BabylonScene babylonScene)
        {
            IList <BabylonAnimationGroup> animationGroups = new List <BabylonAnimationGroup>();

            // Retrieve and parse animation group data
            AnimationGroupList animationList = AnimationGroupList.InitAnimationGroups(this);

            foreach (AnimationGroup animGroup in animationList)
            {
                RaiseMessage("Exporter.animationGroups | " + animGroup.Name, 1);

                BabylonAnimationGroup animationGroup = new BabylonAnimationGroup
                {
                    name = animGroup.Name,
                    from = animGroup.FrameStart,
                    to   = animGroup.FrameEnd,
                    targetedAnimations = new List <BabylonTargetedAnimation>()
                };

                // add animations of each nodes contained in the animGroup
                foreach (Guid guid in animGroup.NodeGuids)
                {
                    IINode maxNode = Tools.GetINodeByGuid(guid);

                    // node could have been deleted, silently ignore it
                    if (maxNode == null)
                    {
                        continue;
                    }


                    // Helpers can be exported as dummies and as bones
                    string nodeId = maxNode.GetGuid().ToString();
                    string boneId = isGltfExported?maxNode.GetGuid().ToString(): maxNode.GetGuid().ToString() + "-bone";   // the suffix "-bone" is added in babylon export format to assure the uniqueness of IDs


                    // Node
                    BabylonNode node = null;
                    babylonScene.NodeMap.TryGetValue(nodeId, out node);
                    if (node != null)
                    {
                        if (node.animations != null && node.animations.Length != 0)
                        {
                            IList <BabylonAnimation> animations = GetSubAnimations(node, animationGroup.from, animationGroup.to);
                            foreach (BabylonAnimation animation in animations)
                            {
                                BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation
                                {
                                    animation = animation,
                                    targetId  = nodeId
                                };

                                animationGroup.targetedAnimations.Add(targetedAnimation);
                            }
                        }
                        else if (exportNonAnimated)
                        {
                            BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation
                            {
                                animation = CreatePositionAnimation(animationGroup.from, animationGroup.to, node.position),
                                targetId  = node.id
                            };

                            animationGroup.targetedAnimations.Add(targetedAnimation);
                        }
                    }

                    // bone
                    BabylonBone bone  = null;
                    int         index = 0;
                    while (index < babylonScene.SkeletonsList.Count && bone == null)
                    {
                        BabylonSkeleton skel = babylonScene.SkeletonsList[index];
                        bone = skel.bones.FirstOrDefault(b => b.id == boneId);
                        index++;
                    }

                    if (bone != null)
                    {
                        if (bone.animation != null)
                        {
                            IList <BabylonAnimation> animations = GetSubAnimations(bone, animationGroup.from, animationGroup.to);
                            foreach (BabylonAnimation animation in animations)
                            {
                                BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation
                                {
                                    animation = animation,
                                    targetId  = boneId
                                };

                                animationGroup.targetedAnimations.Add(targetedAnimation);
                            }
                        }
                        else if (exportNonAnimated)
                        {
                            BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation
                            {
                                animation = CreateMatrixAnimation(animationGroup.from, animationGroup.to, bone.matrix),
                                targetId  = bone.id
                            };

                            animationGroup.targetedAnimations.Add(targetedAnimation);
                        }
                    }
                }

                if (animationGroup.targetedAnimations.Count > 0)
                {
                    animationGroups.Add(animationGroup);
                }
            }

            return(animationGroups);
        }
Пример #40
0
        private void addSelectedButton_Click(object sender, EventArgs e)
        {
            if (currentInfo == null)
            {
                return;
            }

            if (currentAnimationParseType == AnimationParseType.Nodes)
            {
                MaxNodeTree.BeginUpdate();
                for (int i = 0; i < Loader.Core.SelNodeCount; ++i)
                {
                    IINode node = Loader.Core.GetSelNode(i);

                    //added in flightsim to add lod node "x0_name" and all other lod relative
                    // x1_name,x2_name etc
                    //todo expost addnode to maxscript and call this outside
                    if (node.Name.StartsWith("x"))
                    {
                        string lod_name   = node.Name.Substring(3);
                        string lod_prefix = node.Name.Replace(lod_name, "");
                        if (lod_prefix.ToCharArray()[0] == 'x' && lod_prefix.ToCharArray()[2] == '_')
                        {
                            for (int j = 0; j < 7; j++)
                            {
                                string relativeLodName = "x" + j + "_" + lod_name;
                                IINode relativeLodNode = Loader.Core.GetINodeByName(relativeLodName);
                                if (relativeLodNode != null)
                                {
                                    MaxNodeTree.QueueAddNode(relativeLodNode);
                                }
                            }
                        }
                        else
                        {
                            MaxNodeTree.QueueAddNode(node);
                        }
                    }
                    else
                    {
                        MaxNodeTree.QueueAddNode(node);
                    }
                }

                MaxNodeTree.EndUpdate();
            }


            if (currentAnimationParseType == AnimationParseType.Materials)
            {
                if (Loader.Core.SelNodeCount < 1)
                {
                    MessageBox.Show("You need to select at least one Node");
                    return;
                }
                for (int i = 0; i < Loader.Core.SelNodeCount; ++i)
                {
                    IINode node     = Loader.Core.GetSelNode(i);
                    IMtl   material = node.GetAnimatableMaterial();
                    if (material != null)
                    {
                        maxMaterialView.AddMaterialFromSelection(material);
                    }
                }
            }
        }
Пример #41
0
 public void DeleteFromData(IINode dataNode = null)
 {
     dataNode = dataNode ?? Loader.Core.RootNode;
     dataNode.DeleteProperty(GetPropertyName());
     IsDirty = true;
 }
Пример #42
0
        public static void PrepareTextBox(TextBox textBox, IINode node, string propertyName, string defaultValue = "")
        {
            var state = node.GetStringProperty(propertyName, defaultValue);

            textBox.Text = state;
        }
Пример #43
0
        private static void ResolveMultipleInheritedContainer(IIContainerObject container)
        {
            string helperPropBuffer = string.Empty;

            container.BabylonContainerHelper().GetUserPropBuffer(ref helperPropBuffer);

            List <IINode> containerHierarchy = new List <IINode>()
            {
                container.ContainerNode
            };

            containerHierarchy.AddRange(container.ContainerNode.ContainerNodeTree(false));

            int containerID = 1;

            container.ContainerNode.GetUserPropInt("babylonjs_ContainerID", ref containerID);

            //the first istance of the multiples containers, the one without _ID_*
            //mContainer ->referenceBrotherContainer
            //mContainer_ID_2
            int idIndex = container.ContainerNode.Name.IndexOf("_ID_");

            if (idIndex < 0)
            {
                return;
            }
            string refBrotherName            = container.ContainerNode.Name.Substring(0, idIndex);
            IINode refBrotherContainerObject = Loader.Core.GetINodeByName(refBrotherName);

            //if there is no brother, there is nothing to resolve
            if (refBrotherContainerObject == null)
            {
                return;
            }


            //manage multiple containers inherithed from the same source
            foreach (IINode n in containerHierarchy)
            {
                if (n.IsBabylonContainerHelper())
                {
                    continue;
                }

                //change the guid of the node
                //replace the guid in the babylon helper
                string oldGuid = n.GetStringProperty("babylonjs_GUID", Guid.NewGuid().ToString());
                n.DeleteProperty("babylonjs_GUID");
                Guid newGuid = n.GetGuid();
                helperPropBuffer = helperPropBuffer.Replace(oldGuid, newGuid.ToString());

                if (containerID > 1 && !n.Name.EndsWith("_ID_" + containerID))
                {
                    string originalName = n.Name;
                    n.Name = $"{n.Name}_ID_{containerID}";
                    IINode source = refBrotherContainerObject.FindChildNode(originalName);
                    IMtl   mat    = source.Mtl;
                    if (mat != null)
                    {
                        n.Mtl = mat;
                    }
                }
            }

            //replace animationList guid to have distinct list of AnimationGroup for each container
            string animationListStr = string.Empty;

            container.BabylonContainerHelper().GetUserPropString(s_AnimationListPropertyName, ref animationListStr);
            if (!string.IsNullOrEmpty(animationListStr))
            {
                string[] animationGroupGuid = animationListStr.Split(AnimationGroup.s_PropertySeparator);
                foreach (string guidStr in animationGroupGuid)
                {
                    Guid newAnimGroupGuid = Guid.NewGuid();
                    helperPropBuffer = helperPropBuffer.Replace(guidStr, newAnimGroupGuid.ToString());
                }

                container.BabylonContainerHelper().SetUserPropBuffer(helperPropBuffer);

                //add ID of container to animationGroup name to identify animation in viewer
                container.BabylonContainerHelper().GetUserPropString(s_AnimationListPropertyName, ref animationListStr);
                string[] newAnimationGroupGuid = animationListStr.Split(AnimationGroup.s_PropertySeparator);

                if (containerID > 1)
                {
                    foreach (string guidStr in newAnimationGroupGuid)
                    {
                        string propertiesString = string.Empty;
                        if (!container.BabylonContainerHelper().GetUserPropString(guidStr, ref propertiesString))
                        {
                            return;
                        }

                        string[] properties = propertiesString.Split(AnimationGroup.s_PropertySeparator);
                        if (properties.Length < 4)
                        {
                            throw new Exception("Invalid number of properties, can't deserialize.");
                        }

                        string name = properties[0];
                        if (!string.IsNullOrEmpty(name) && !name.EndsWith("_ID_" + containerID))
                        {
                            propertiesString = propertiesString.Replace(name, name + "_ID_" + containerID);
                            container.BabylonContainerHelper().SetUserPropString(guidStr, propertiesString);
                        }
                    }
                }
            }
        }
Пример #44
0
 public static void PrepareComboBox(ComboBox comboBox, IINode node, string propertyName, string defaultValue)
 {
     comboBox.SelectedItem = node.GetStringProperty(propertyName, defaultValue);
 }
Пример #45
0
        public static void UpdateVector3Control(Vector3Control vector3Control, IINode node, string propertyName)
        {
            string name = propertyName + "_x";
            node.SetUserPropFloat(ref name, vector3Control.X);

            name = propertyName + "_y";
            node.SetUserPropFloat(ref name, vector3Control.Y);

            name = propertyName + "_z";
            node.SetUserPropFloat(ref name, vector3Control.Z);
        }
Пример #46
0
 public static void UpdateTextBox(TextBox textBox, IINode node, string propertyName)
 {
     node.SetUserPropString(propertyName, textBox.Text);
 }
Пример #47
0
        public static bool PrepareCheckBox(CheckBox checkBox, IINode node, string propertyName, int defaultState = 0)
        {
            var state = node.GetBoolProperty(propertyName, defaultState);

            if (checkBox.CheckState == CheckState.Indeterminate)
            {
                checkBox.CheckState = state ? CheckState.Checked : CheckState.Unchecked;
            }
            else
            {
                if (checkBox.ThreeState)
                {
                    if (!state && checkBox.CheckState == CheckState.Checked ||
                        state && checkBox.CheckState == CheckState.Unchecked)
                    {
                        checkBox.CheckState = CheckState.Indeterminate;
                        return true;
                    }
                }
                else
                {
                    checkBox.CheckState = state ? CheckState.Checked : CheckState.Unchecked;
                    return true;
                }
            }

            return false;
        }
Пример #48
0
 public static void PrepareVector3Control(Vector3Control vector3Control, IINode node, string propertyName, float defaultX = 0, float defaultY = 0, float defaultZ = 0)
 {
     vector3Control.X = node.GetFloatProperty(propertyName + "_x", defaultX);
     vector3Control.Y = node.GetFloatProperty(propertyName + "_y", defaultY);
     vector3Control.Z = node.GetFloatProperty(propertyName + "_z", defaultZ);
 }
Пример #49
0
 public static void PrepareComboBox(ComboBox comboBox, IINode node, string propertyName, string defaultValue)
 {
     comboBox.SelectedItem = node.GetStringProperty(propertyName, defaultValue);
 }
Пример #50
0
        public static void UpdateComboBox(ComboBox comboBox, IINode node, string propertyName)
        {
            var value = comboBox.SelectedItem.ToString();

            node.SetUserPropString(propertyName, value);
        }
Пример #51
0
 public static void PrepareVector3Control(Vector3Control vector3Control, IINode node, string propertyName, float defaultX = 0, float defaultY = 0, float defaultZ = 0)
 {
     vector3Control.X = node.GetFloatProperty(propertyName + "_x", defaultX);
     vector3Control.Y = node.GetFloatProperty(propertyName + "_y", defaultY);
     vector3Control.Z = node.GetFloatProperty(propertyName + "_z", defaultZ);
 }
Пример #52
0
 public static IEnumerable <IINode> NodesListBySuperClasses(this IINode rootNode, SClass_ID[] sids)
 {
     return(from n in rootNode.NodeTree() where n.ObjectRef != null && sids.Any(sid => n.EvalWorldState(0, false).Obj.SuperClassID == sid) select n);
 }
Пример #53
0
        public static void UpdateComboBox(ComboBox comboBox, IINode node, string propertyName)
        {
            var value = comboBox.SelectedItem.ToString();
#if MAX2015 || MAX2016
            node.SetUserPropString(propertyName, value);
#else
            node.SetUserPropString(ref propertyName, ref value);
#endif
        }
Пример #54
0
 public static bool HasParent(this IINode node)
 {
     return(node.ParentNode != null && !node.ParentNode.IsRootNode);
 }
Пример #55
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);
        }
Пример #56
0
        public static void SetStringProperty(this IINode node, string propertyName, string defaultState)
        {
            string state = defaultState;

            node.SetUserPropString(propertyName, state);
        }
Пример #57
0
 public VisualNodeInfo(IINode maxNode, bool isDummy = true, EState state = EState.Added)
 {
     MaxNode = maxNode;
     State   = state;
     IsDummy = isDummy;
 }
Пример #58
0
 /// <summary>
 /// helper for the notifiy dependands on node
 /// if you change anything on a node the node have to notify all dependents
 /// this is similar to events in c#
 /// </summary>
 /// <param name="node"></param>
 /// <param name="interval"></param>
 /// <param name="part"></param>
 /// <param name="message"></param>
 public static void NotifyDependents(this IINode node, IInterval interval, int part, RefMessage message)
 {
     node.NotifyDependents(interval, new UIntPtr((uint)part), message, Globals.NOTIFY_ALL, true, null);
 }
Пример #59
0
        private void IsMeshFlattenable(IINode node, AnimationGroupList animationGroupList, ref List <IINode> flattenableNodes)
        {
            //a node can't be flatten if:
            //- is not a mesh
            //- is marked as not flattenable
            //- is hidden
            //- is part of animation group
            //- is skinned
            //- is linked to animated node

            if (node.IsMarkedAsNotFlattenable())
            {
                return;
            }

            if (node.IsNodeHidden(false) && !exportParameters.exportHiddenObjects)
            {
                return;
            }

            if (node.IsRootNode)
            {
                for (int i = 0; i < node.NumChildren; i++)
                {
                    IINode n = node.GetChildNode(i);
                    IsMeshFlattenable(n, animationGroupList, ref flattenableNodes);
                }
                return;
            }

            if (node.GetTriObjectFromNode() == null)
            {
                for (int i = 0; i < node.NumChildren; i++)
                {
                    IINode n = node.GetChildNode(i);
                    IsMeshFlattenable(n, animationGroupList, ref flattenableNodes);
                }
                return;
            }

            if (node.IsSkinned())
            {
                string message = $"{node.Name} can't be flatten, because is skinned";
                RaiseMessage(message, 0);
                for (int i = 0; i < node.NumChildren; i++)
                {
                    IINode n = node.GetChildNode(i);
                    IsMeshFlattenable(n, animationGroupList, ref flattenableNodes);
                }
                return;
            }

            if (node.IsNodeTreeAnimated())
            {
                string message = $"{node.Name} can't be flatten, his hierachy contains animated node";
                RaiseMessage(message, 0);
                for (int i = 0; i < node.NumChildren; i++)
                {
                    IINode n = node.GetChildNode(i);
                    IsMeshFlattenable(n, animationGroupList, ref flattenableNodes);
                }
                return;
            }

            if (node.IsInAnimationGroups(animationGroupList))
            {
                string message = $"{node.Name} can't be flatten, because is part of an AnimationGroup";
                RaiseMessage(message, 0);
                for (int i = 0; i < node.NumChildren; i++)
                {
                    IINode n = node.GetChildNode(i);
                    IsMeshFlattenable(n, animationGroupList, ref flattenableNodes);
                }
                return;
            }

            flattenableNodes.Add(node);
        }
Пример #60
0
        public object ExportGLTFExtension <T>(T babylonObject, ExportParameters parameters, ref GLTF gltf, ILoggingProvider logger)
        {
            var babylonMesh = babylonObject as BabylonMesh;

            if (babylonMesh != null)
            {
                GLTFExtensionAsoboGizmo   gltfExtensionAsoboGizmo = new GLTFExtensionAsoboGizmo();
                List <GLTFExtensionGizmo> collisions = new List <GLTFExtensionGizmo>();
                gltfExtensionAsoboGizmo.gizmos = collisions;

                Guid guid = Guid.Empty;
                Guid.TryParse(babylonMesh.id, out guid);
                IINode maxNode = Tools.GetINodeByGuid(guid);
                foreach (IINode node in maxNode.DirectChildren())
                {
                    IObject            obj   = node.ObjectRef;
                    List <AsoboTag>    tags  = new List <AsoboTag>();
                    GLTFExtensionGizmo gizmo = new GLTFExtensionGizmo();;
                    if (new MaterialUtilities.ClassIDWrapper(obj.ClassID).Equals(BoxColliderClassID))
                    {
                        GLTFExtensionAsoboBoxParams boxParams = new GLTFExtensionAsoboBoxParams();
                        float height = FlightSimExtensionUtility.GetGizmoParameterFloat(node, "BoxGizmo", "height");
                        float width  = FlightSimExtensionUtility.GetGizmoParameterFloat(node, "BoxGizmo", "width");
                        float length = FlightSimExtensionUtility.GetGizmoParameterFloat(node, "BoxGizmo", "length");
                        gizmo.Translation = FlightSimExtensionUtility.GetTranslation(node, maxNode);
                        float[] rotation = FlightSimExtensionUtility.GetRotation(node, maxNode);
                        if (!FlightSimExtensionUtility.IsDefaultRotation(rotation))
                        {
                            gizmo.Rotation = rotation;
                        }

                        boxParams.width  = width;
                        boxParams.height = height;
                        boxParams.length = length;

                        gizmo.Params = boxParams;
                        gizmo.Type   = "box";

                        bool isRoad      = FlightSimExtensionUtility.GetGizmoParameterBoolean(node, "BoxCollider", "IsRoad", IsSubClass: false);
                        bool isCollision = FlightSimExtensionUtility.GetGizmoParameterBoolean(node, "BoxCollider", "IsCollision", IsSubClass: false);

                        if (isCollision)
                        {
                            tags.Add(AsoboTag.Collision);
                        }
                        if (isRoad)
                        {
                            tags.Add(AsoboTag.Road);
                        }

                        ParseTags(ref gizmo, ref gltf, ref tags);
                        collisions.Add(gizmo);
                    }
                    else if (new MaterialUtilities.ClassIDWrapper(obj.ClassID).Equals(CylinderColliderClassID))
                    {
                        GLTFExtensionAsoboCylinderParams cylinderParams = new GLTFExtensionAsoboCylinderParams();
                        float radius = FlightSimExtensionUtility.GetGizmoParameterFloat(node, "CylGizmo", "radius");
                        float height = FlightSimExtensionUtility.GetGizmoParameterFloat(node, "CylGizmo", "height");
                        gizmo.Translation = FlightSimExtensionUtility.GetTranslation(node, maxNode);
                        float[] rotation = FlightSimExtensionUtility.GetRotation(node, maxNode);
                        if (!FlightSimExtensionUtility.IsDefaultRotation(rotation))
                        {
                            gizmo.Rotation = rotation;
                        }
                        cylinderParams.height = height;
                        cylinderParams.radius = radius;
                        gizmo.Params          = cylinderParams;
                        gizmo.Type            = "cylinder";

                        bool isRoad      = FlightSimExtensionUtility.GetGizmoParameterBoolean(node, "CylCollider", "IsRoad", IsSubClass: false);
                        bool isCollision = FlightSimExtensionUtility.GetGizmoParameterBoolean(node, "CylCollider", "IsCollision", IsSubClass: false);

                        if (isCollision)
                        {
                            tags.Add(AsoboTag.Collision);
                        }
                        if (isRoad)
                        {
                            tags.Add(AsoboTag.Road);
                        }

                        ParseTags(ref gizmo, ref gltf, ref tags);
                        collisions.Add(gizmo);
                    }
                    else if (new MaterialUtilities.ClassIDWrapper(obj.ClassID).Equals(SphereColliderClassID))
                    {
                        GLTFExtensionAsoboSphereParams sphereParams = new GLTFExtensionAsoboSphereParams();
                        float radius = FlightSimExtensionUtility.GetGizmoParameterFloat(node, "SphereGizmo", "radius");
                        gizmo.Translation   = FlightSimExtensionUtility.GetTranslation(node, maxNode);
                        sphereParams.radius = radius;
                        gizmo.Type          = "sphere";
                        gizmo.Params        = sphereParams;

                        bool isRoad      = FlightSimExtensionUtility.GetGizmoParameterBoolean(node, "SphereCollider", "IsRoad", IsSubClass: false);
                        bool isCollision = FlightSimExtensionUtility.GetGizmoParameterBoolean(node, "SphereCollider", "IsCollision", IsSubClass: false);

                        if (isCollision)
                        {
                            tags.Add(AsoboTag.Collision);
                        }
                        if (isRoad)
                        {
                            tags.Add(AsoboTag.Road);
                        }

                        ParseTags(ref gizmo, ref gltf, ref tags);
                        collisions.Add(gizmo);
                    }
                }
                if (collisions.Count > 0)
                {
                    return(gltfExtensionAsoboGizmo);
                }
            }
            return(null);
        }