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; }
/// <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); }
/// <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); }
private void FillTree(IINode node) { this.AddNode(node, this.Tree.Nodes); for (int i = 0; i < node.NumberOfChildren; i++) { this.FillTree(node.GetChildNode(i)); } }
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; }
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]); }
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; } } }
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; }
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; } }
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()); } }
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); }
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; }
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; }
public static void PrepareTextBox(TextBox textBox, IINode node, string propertyName, string defaultValue = "") { var state = node.GetStringProperty(propertyName, defaultValue); textBox.Text = state; }
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); }
public override void Do() { IINodeTab nodeTab = this.nodes.ToIINodeTab(); this.containerNode = MaxInterfaces.ContainerManager.CreateContainer(nodeTab); this.containerNode.SetAFlag(AnimatableFlags.Held); }
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; }
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); }
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; }
public void QueueRemoveNode(IINode node) { QueueRemoveNode(node.Handle); }
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); }
public static bool HasParent(this IINode node) { return(node.ParentNode != null && node.ParentNode.ObjectRef != null); }
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); }
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); }
public static Guid GetGuid(this IINode node) { return(GetGuid(Animatable.CreateWrapper <Node>(node))); }
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); }
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 } }
private void CreateFacesFromNode(IINode node) { }
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); } } } }
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); }
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); } } } }
public void DeleteFromData(IINode dataNode = null) { dataNode = dataNode ?? Loader.Core.RootNode; dataNode.DeleteProperty(GetPropertyName()); IsDirty = true; }
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); } } } } }
public static void PrepareComboBox(ComboBox comboBox, IINode node, string propertyName, string defaultValue) { comboBox.SelectedItem = node.GetStringProperty(propertyName, defaultValue); }
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); }
public static void UpdateTextBox(TextBox textBox, IINode node, string propertyName) { node.SetUserPropString(propertyName, textBox.Text); }
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; }
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); }
public static void UpdateComboBox(ComboBox comboBox, IINode node, string propertyName) { var value = comboBox.SelectedItem.ToString(); node.SetUserPropString(propertyName, value); }
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); }
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 }
public static bool HasParent(this IINode node) { return(node.ParentNode != null && !node.ParentNode.IsRootNode); }
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); }
public static void SetStringProperty(this IINode node, string propertyName, string defaultState) { string state = defaultState; node.SetUserPropString(propertyName, state); }
public VisualNodeInfo(IINode maxNode, bool isDummy = true, EState state = EState.Added) { MaxNode = maxNode; State = state; IsDummy = isDummy; }
/// <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); }
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); }
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); }