private BabylonShadowGenerator ExportShadowGenerator(IINode lightNode, BabylonScene babylonScene) { var maxLight = (lightNode.ObjectRef as ILightObject); var babylonShadowGenerator = new BabylonShadowGenerator(); RaiseMessage("Exporting shadow map", 2); babylonShadowGenerator.lightId = lightNode.GetGuid().ToString(); babylonShadowGenerator.mapSize = maxLight.GetMapSize(0, Tools.Forever); babylonShadowGenerator.bias = lightNode.GetFloatProperty("babylonjs_shadows_bias", 0.00005f); babylonShadowGenerator.forceBackFacesOnly = lightNode.GetBoolProperty("babylonjs_forcebackfaces"); var shadowsType = lightNode.GetStringProperty("babylonjs_shadows_type", "Blurred Variance"); switch (shadowsType) { case "Hard shadows": break; case "Poisson Sampling": babylonShadowGenerator.usePoissonSampling = true; break; case "Variance": babylonShadowGenerator.useVarianceShadowMap = true; break; case"Blurred Variance": babylonShadowGenerator.useBlurVarianceShadowMap = true; babylonShadowGenerator.blurScale = lightNode.GetFloatProperty("babylonjs_shadows_blurScale", 2); babylonShadowGenerator.blurBoxOffset = lightNode.GetFloatProperty("babylonjs_shadows_blurBoxOffset", 1); break; } var list = new List<string>(); var inclusion = maxLight.ExclList.TestFlag(1); //NT_INCLUDE var checkExclusionList = maxLight.ExclList.TestFlag(4); //NT_AFFECT_SHADOWCAST foreach (var meshNode in Loader.Core.RootNode.NodesListBySuperClass(SClass_ID.Geomobject)) { #if MAX2017 if (meshNode.CastShadows) #else if (meshNode.CastShadows == 1) #endif { var inList = maxLight.ExclList.FindNode(meshNode) != -1; if (!checkExclusionList || (inList && inclusion) || (!inList && !inclusion)) { list.Add(meshNode.GetGuid().ToString()); } } } babylonShadowGenerator.renderList = list.ToArray(); babylonScene.ShadowGeneratorsList.Add(babylonShadowGenerator); return babylonShadowGenerator; }
private void OnNodeAdded(IntPtr param0, IntPtr param1) { try { INotifyInfo obj = Loader.Global.NotifyInfo.Marshal(param1); IINode n = (IINode)obj.CallParam; //todo replace this with something like isXREFNODE //to have a distinction between added xref node and max node string guid = n.GetStringProperty("babylonjs_GUID", string.Empty); if (string.IsNullOrEmpty(guid)) { n.GetGuid(); // force to assigne a new guid if not exist yet for this node } IIContainerObject contaner = Loader.Global.ContainerManagerInterface.IsContainerNode(n); if (contaner != null) { // a generic operation on a container is done (open/inherit) contaner.ResolveContainer(); } } catch { // Fails silently } }
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); }
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; }
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 (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); }
public static List <Guid> ToGuids(this IList <uint> handles) { List <Guid> guids = new List <Guid>(); foreach (uint handle in handles) { IINode node = Loader.Core.GetINodeByHandle(handle); Guid guid = node.GetGuid(); guids.Add(guid); } return(guids); }
private int ParseNewProperties(string guidPropPart) { int numFailed = 0; string[] guidProperties = guidPropPart.Split(s_GUIDTypeSeparator); string[] nodes = new string[0]; string[] materials = new string[0]; if (!string.IsNullOrWhiteSpace(guidProperties[0])) { nodes = guidProperties[0].Split(s_PropertySeparator); } if (!string.IsNullOrWhiteSpace(guidProperties[1])) { materials = guidProperties[1].Split(s_PropertySeparator); } int numNodeGUIDs = nodes.Length; int numMatGUIDs = materials.Length; for (int i = 0; i < numNodeGUIDs; ++i) { Guid guid; if (!Guid.TryParse(nodes[i], out guid)) { uint id; if (!uint.TryParse(nodes[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); } for (int i = 0; i < numMatGUIDs; ++i) { Guid guid; if (Guid.TryParse(materials[i], out guid)) { materialsGuids.Add(guid); } } return(numFailed); }
private void OnNodeDeleted(IntPtr objPtr, INotifyInfo infoPtr) { try { IINode n = (IINode)infoPtr.CallParam; Tools.guids.Remove(n.GetGuid()); } catch { // Fails silently } }
private void OnNodeDeleted(IntPtr objPtr, IntPtr param1) { try { INotifyInfo obj = Loader.Global.NotifyInfo.Marshal(param1); IINode n = (IINode)obj.CallParam; Tools.guids.Remove(n.GetGuid()); } catch { // Fails silently } }
public void RemoveNodeFromAnimationGroup(AnimationGroup info, uint nodeHandle) { if (info == null) return; IINode node = Loader.Core.GetINodeByHandle(nodeHandle); if (node == null) { return; } List<Guid> newGuids = info.NodeGuids.ToList(); newGuids.Remove(node.GetGuid()); info.NodeGuids = newGuids; info.SaveToData(); }
public void HighlightAnimationGroupOfSelection() { AnimationListBox.ClearSelected(); IINode node = Loader.Core.GetSelNode(0); if (node != null) { for (int i = 0; i < animationGroups.Count; i++) { if (animationGroups[i].NodeGuids.Contains(node.GetGuid())) { AnimationListBox.SelectedItem = animationGroups[i]; } } } }
private void OnNodeAdded(IntPtr objPtr, INotifyInfo infoPtr) { try { IINode n = (IINode)infoPtr.CallParam; n.GetGuid(); // force to assigne a new guid if not exist yet for this node IIContainerObject contaner = Loader.Global.ContainerManagerInterface.IsContainerNode(n); if (contaner != null) { // a generic operation on a container is done (open/inherit) contaner.ResolveContainer(); } } catch { // Fails silently } }
public void AutoAssignLodInAnimationGroup() { AnimationGroupList animationGroupList = new AnimationGroupList(); animationGroupList.LoadFromData(); var nodes = Loader.Core.RootNode.NodeTree(); List <IINode> nodeToAdd = new List <IINode>(); foreach (AnimationGroup anim in animationGroupList) { nodeToAdd.Clear(); foreach (Guid guid in anim.NodeGuids) { IINode n = Tools.GetINodeByGuid(guid); if (n == null) { continue; } if (!Regex.IsMatch(n.Name, "(?i)x[0-9]_")) { continue; } string noLodName = n.Name.Substring(3); foreach (IINode node in nodes) { if (Regex.IsMatch(node.Name, $"(?i)x[0-9]_{noLodName}$")) { nodeToAdd.Add(node); } } } foreach (IINode n in nodeToAdd) { List <Guid> newGuids = anim.NodeGuids.ToList(); newGuids.Add(n.GetGuid()); anim.NodeGuids = newGuids; } anim.SaveToData(); } }
private void OnNodeAdded(IntPtr param0, IntPtr param1) { try { INotifyInfo obj = Loader.Global.NotifyInfo.Marshal(param1); IINode n = (IINode)obj.CallParam; n.GetGuid(); // force to assigne a new guid if not exist yet for this node IIContainerObject contaner = Loader.Global.ContainerManagerInterface.IsContainerNode(n); if (contaner != null) { // a generic operation on a container is done (open/inherit) Tools.guids = new Dictionary <Guid, IAnimatable>(); } } catch { // Fails silently } }
private int ParseOldProperties(string guidPropPart) { IsOldType = true; //force it to be saved in the new format string[] properties = guidPropPart.Split(s_PropertySeparator); int numFailed = 0; int numNodeIDs = properties.Length; if (nodeGuids.Capacity < numNodeIDs) { nodeGuids.Capacity = numNodeIDs; } for (int i = 0; i < numNodeIDs; ++i) { Guid guid; if (!Guid.TryParse(properties[i], out guid)) { uint id; if (!uint.TryParse(properties[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); } return(numFailed); }
private void ExportAnimationGroups(GLTF gltf, BabylonScene babylonScene) { AnimationGroupList animationList = new AnimationGroupList(); animationList.LoadFromData(); gltf.AnimationsList.Clear(); gltf.AnimationsList.Capacity = Math.Max(gltf.AnimationsList.Capacity, animationList.Count); foreach (AnimationGroup animGroup in animationList) { GLTFAnimation gltfAnimation = new GLTFAnimation(); gltfAnimation.name = animGroup.Name; foreach (uint nodeHandle in animGroup.NodeHandles) { // todo: make something a little more efficient.. IINode maxNode = Loader.Core.RootNode.FindChildNode(nodeHandle); 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, animGroup.FrameStart, animGroup.FrameEnd, 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, animGroup.FrameStart, animGroup.FrameEnd, gltf, pair.Key, pair.Value); } } } gltf.AnimationsList.Add(gltfAnimation); } }
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); }
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); } } } }
private void confirmButton_Click(object sender, EventArgs e) { if (currentInfo == null) { return; } AnimationGroup confirmedInfo = currentInfo; string newName = nameTextBox.Text; 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); bool changed = newName != confirmedInfo.Name || newFrameStart != confirmedInfo.FrameStart || newFrameEnd != confirmedInfo.FrameEnd || nodesChanged; if (!changed) { return; } confirmedInfo.Name = newName; confirmedInfo.FrameStart = newFrameStart; confirmedInfo.FrameEnd = newFrameEnd; 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); } } } ResetChangedTextBoxColors(); MaxNodeTree.SelectedNode = null; InfoChanged?.Invoke(confirmedInfo); ConfirmPressed?.Invoke(confirmedInfo); }
private void ExportLight(IINode lightNode, BabylonScene babylonScene) { if (lightNode.GetBoolProperty("babylonjs_noexport")) { return; } var maxLight = (lightNode.ObjectRef as ILightObject); var babylonLight = new BabylonLight(); RaiseMessage(lightNode.Name, 1); babylonLight.name = lightNode.Name; babylonLight.id = lightNode.GetGuid().ToString(); // Type var lightState = Loader.Global.LightState.Create(); maxLight.EvalLightState(0, Tools.Forever, lightState); var directionScale = -1; switch (lightState.Type) { case LightType.OmniLgt: babylonLight.type = 0; break; case LightType.SpotLgt: babylonLight.type = 2; babylonLight.angle = (float)(maxLight.GetFallsize(0, Tools.Forever) * Math.PI / 180.0f); babylonLight.exponent = 1; break; case LightType.DirectLgt: babylonLight.type = 1; break; case LightType.AmbientLgt: babylonLight.type = 3; babylonLight.groundColor = new float[] { 0, 0, 0 }; directionScale = 1; break; } // Shadows if (maxLight.ShadowMethod == 1) { if (lightState.Type == LightType.DirectLgt) { ExportShadowGenerator(lightNode, babylonScene); } else { RaiseWarning("Shadows maps are only supported for directional lights", 2); } } // Position var wm = lightNode.GetWorldMatrix(0, false); var position = wm.Trans; babylonLight.position = position.ToArraySwitched(); // Direction var target = lightNode.Target; if (target != null) { var targetWm = target.GetObjTMBeforeWSM(0, Tools.Forever); var targetPosition = targetWm.Trans; var direction = targetPosition.Subtract(position); babylonLight.direction = direction.ToArraySwitched(); } else { var dir = wm.GetRow(2).MultiplyBy(directionScale); babylonLight.direction = dir.ToArraySwitched(); } // Exclusion var maxScene = Loader.Core.RootNode; var inclusion = maxLight.ExclList.TestFlag(1); //NT_INCLUDE var checkExclusionList = maxLight.ExclList.TestFlag(2); //NT_AFFECT_ILLUM if (checkExclusionList) { var excllist = new List<string>(); var incllist = new List<string>(); foreach (var meshNode in maxScene.NodesListBySuperClass(SClass_ID.Geomobject)) { if (meshNode.CastShadows == 1) { var inList = maxLight.ExclList.FindNode(meshNode) != -1; if (inList) { if (inclusion) { incllist.Add(meshNode.GetGuid().ToString()); } else { excllist.Add(meshNode.GetGuid().ToString()); } } } } babylonLight.includedOnlyMeshesIds = incllist.ToArray(); babylonLight.excludedMeshesIds = excllist.ToArray(); } // Other fields babylonLight.intensity = maxLight.GetIntensity(0, Tools.Forever); babylonLight.diffuse = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 }; babylonLight.specular = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 }; if (maxLight.UseAtten) { babylonLight.range = maxLight.GetAtten(0, 1, Tools.Forever); } // Animations var animations = new List<BabylonAnimation>(); if (!ExportVector3Controller(lightNode.TMController.PositionController, "position", animations)) { ExportVector3Animation("position", animations, key => { var worldMatrix = lightNode.GetWorldMatrix(key, lightNode.HasParent()); return worldMatrix.Trans.ToArraySwitched(); }); } ExportVector3Animation("direction", animations, key => { var targetNode = lightNode.Target; if (targetNode != null) { var targetWm = target.GetObjTMBeforeWSM(0, Tools.Forever); var targetPosition = targetWm.Trans; var direction = targetPosition.Subtract(position); return direction.ToArraySwitched(); } var dir = wm.GetRow(2).MultiplyBy(directionScale); return dir.ToArraySwitched(); }); ExportFloatAnimation("intensity", animations, key => new[] { maxLight.GetIntensity(key, Tools.Forever) }); babylonLight.animations = animations.ToArray(); if (lightNode.GetBoolProperty("babylonjs_autoanimate")) { babylonLight.autoAnimate = true; babylonLight.autoAnimateFrom = (int)lightNode.GetFloatProperty("babylonjs_autoanimate_from"); babylonLight.autoAnimateTo = (int)lightNode.GetFloatProperty("babylonjs_autoanimate_to"); babylonLight.autoAnimateLoop = lightNode.GetBoolProperty("babylonjs_autoanimateloop"); } babylonScene.LightsList.Add(babylonLight); }
private void ExportLight(IINode lightNode, BabylonScene babylonScene) { if (lightNode.GetBoolProperty("babylonjs_noexport")) { return; } var maxLight = (lightNode.ObjectRef as ILightObject); var babylonLight = new BabylonLight(); RaiseMessage(lightNode.Name, 1); babylonLight.name = lightNode.Name; babylonLight.id = lightNode.GetGuid().ToString(); // Type var lightState = Loader.Global.LightState.Create(); maxLight.EvalLightState(0, Tools.Forever, lightState); var directionScale = -1; switch (lightState.Type) { case LightType.OmniLgt: babylonLight.type = 0; break; case LightType.SpotLgt: babylonLight.type = 2; babylonLight.angle = (float)(maxLight.GetFallsize(0, Tools.Forever) * Math.PI / 180.0f); babylonLight.exponent = 1; break; case LightType.DirectLgt: babylonLight.type = 1; break; case LightType.AmbientLgt: babylonLight.type = 3; babylonLight.groundColor = new float[] { 0, 0, 0 }; directionScale = 1; break; } // Shadows if (maxLight.ShadowMethod == 1) { if (lightState.Type == LightType.DirectLgt) { ExportShadowGenerator(lightNode, babylonScene); } else { RaiseWarning("Shadows maps are only supported for directional lights", 2); } } // Position var wm = lightNode.GetWorldMatrix(0, false); var position = wm.Trans; babylonLight.position = position.ToArraySwitched(); // Direction var target = lightNode.Target; if (target != null) { var targetWm = target.GetObjTMBeforeWSM(0, Tools.Forever); var targetPosition = targetWm.Trans; var direction = targetPosition.Subtract(position); babylonLight.direction = direction.ToArraySwitched(); } else { var dir = wm.GetRow(2).MultiplyBy(directionScale); babylonLight.direction = dir.ToArraySwitched(); } // Exclusion var maxScene = Loader.Core.RootNode; var inclusion = maxLight.ExclList.TestFlag(1); //NT_INCLUDE var checkExclusionList = maxLight.ExclList.TestFlag(2); //NT_AFFECT_ILLUM if (checkExclusionList) { var excllist = new List <string>(); var incllist = new List <string>(); foreach (var meshNode in maxScene.NodesListBySuperClass(SClass_ID.Geomobject)) { if (meshNode.CastShadows == 1) { var inList = maxLight.ExclList.FindNode(meshNode) != -1; if (inList) { if (inclusion) { incllist.Add(meshNode.GetGuid().ToString()); } else { excllist.Add(meshNode.GetGuid().ToString()); } } } } babylonLight.includedOnlyMeshesIds = incllist.ToArray(); babylonLight.excludedMeshesIds = excllist.ToArray(); } // Other fields babylonLight.intensity = maxLight.GetIntensity(0, Tools.Forever); babylonLight.diffuse = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 }; babylonLight.specular = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 }; if (maxLight.UseAtten) { babylonLight.range = maxLight.GetAtten(0, 1, Tools.Forever); } // Animations var animations = new List <BabylonAnimation>(); if (!ExportVector3Controller(lightNode.TMController.PositionController, "position", animations)) { ExportVector3Animation("position", animations, key => { var worldMatrix = lightNode.GetWorldMatrix(key, lightNode.HasParent()); return(worldMatrix.Trans.ToArraySwitched()); }); } ExportVector3Animation("direction", animations, key => { var targetNode = lightNode.Target; if (targetNode != null) { var targetWm = target.GetObjTMBeforeWSM(0, Tools.Forever); var targetPosition = targetWm.Trans; var direction = targetPosition.Subtract(position); return(direction.ToArraySwitched()); } var dir = wm.GetRow(2).MultiplyBy(directionScale); return(dir.ToArraySwitched()); }); ExportFloatAnimation("intensity", animations, key => new[] { maxLight.GetIntensity(key, Tools.Forever) }); babylonLight.animations = animations.ToArray(); if (lightNode.GetBoolProperty("babylonjs_autoanimate")) { babylonLight.autoAnimate = true; babylonLight.autoAnimateFrom = (int)lightNode.GetFloatProperty("babylonjs_autoanimate_from"); babylonLight.autoAnimateTo = (int)lightNode.GetFloatProperty("babylonjs_autoanimate_to"); babylonLight.autoAnimateLoop = lightNode.GetBoolProperty("babylonjs_autoanimateloop"); } babylonScene.LightsList.Add(babylonLight); }
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); }
private IList <BabylonAnimationGroup> ExportAnimationGroups(BabylonScene babylonScene) { IList <BabylonAnimationGroup> animationGroups = new List <BabylonAnimationGroup>(); // Retrieve and parse animation group data AnimationGroupList animationList = AnimationGroupList.InitAnimationGroups(logger); foreach (AnimationGroup animGroup in animationList) { logger?.RaiseMessage("Exporter.animationGroups | " + animGroup.Name, 1); BabylonAnimationGroup animationGroup = new BabylonAnimationGroup { name = animGroup.Name, from = animGroup.FrameStart, to = animGroup.FrameEnd, keepNonAnimated = animGroup.KeepNonAnimated, 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; } if (exportParameters.exportAsSubmodel && !maxNode.Selected) { 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); if (!animGroup.KeepStaticAnimation) { RemoveStaticAnimations(ref animations); } foreach (BabylonAnimation animation in animations) { BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation { animation = animation, targetId = nodeId }; 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); } } } } // add animations of each nodes contained in the animGroup foreach (Guid guid in animGroup.MaterialGuids) { IMtl maxMtl = Tools.GetIMtlByGuid(guid); // mat could have been deleted, silently ignore it if (maxMtl == null) { continue; } string matId = maxMtl.GetGuid().ToString(); // Material BabylonMaterial material = null; material = babylonScene.MaterialsList.FirstOrDefault(x => x.id == matId); if (material != null) { if (material.animations != null && material.animations.Length != 0) { IList <BabylonAnimation> animations = GetSubAnimations(material, animationGroup.from, animationGroup.to); foreach (BabylonAnimation animation in animations) { BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation { animation = animation, targetId = matId }; animationGroup.targetedAnimations.Add(targetedAnimation); } } } } if (animationGroup.targetedAnimations.Count > 0) { animationGroups.Add(animationGroup); } } return(animationGroups); }
private void ExportMesh(IINode meshNode, BabylonScene babylonScene) { if (meshNode.GetBoolProperty("babylonjs_noexport")) { return; } if (!ExportHiddenObjects && meshNode.IsHidden(NodeHideFlags.None, false)) { return; } var babylonMesh = new BabylonMesh(); int vx1, vx2, vx3; babylonMesh.name = meshNode.Name; babylonMesh.id = meshNode.GetGuid().ToString(); if (meshNode.HasParent()) { babylonMesh.parentId = meshNode.ParentNode.GetGuid().ToString(); } // Misc. babylonMesh.isVisible = meshNode.Renderable == 1; babylonMesh.pickable = meshNode.GetBoolProperty("babylonjs_checkpickable"); babylonMesh.receiveShadows = meshNode.RcvShadows == 1; babylonMesh.showBoundingBox = meshNode.GetBoolProperty("babylonjs_showboundingbox"); babylonMesh.showSubMeshesBoundingBox = meshNode.GetBoolProperty("babylonjs_showsubmeshesboundingbox"); // Collisions babylonMesh.checkCollisions = meshNode.GetBoolProperty("babylonjs_checkcollisions"); // Skin var skin = GetSkinModifier(meshNode); if (skin != null) { babylonMesh.skeletonId = skins.IndexOf(skin); bonesCount = skin.NumBones; } // Position / rotation / scaling var wm = meshNode.GetWorldMatrix(0, meshNode.HasParent()); babylonMesh.position = wm.Trans.ToArraySwitched(); var parts = Loader.Global.AffineParts.Create(); Loader.Global.DecompAffine(wm, parts); if (exportQuaternionsInsteadOfEulers) { babylonMesh.rotationQuaternion = parts.Q.ToArray(); } else { var rotate = new float[3]; IntPtr xPtr = Marshal.AllocHGlobal(sizeof(float)); IntPtr yPtr = Marshal.AllocHGlobal(sizeof(float)); IntPtr zPtr = Marshal.AllocHGlobal(sizeof(float)); parts.Q.GetEuler(xPtr, yPtr, zPtr); Marshal.Copy(xPtr, rotate, 0, 1); Marshal.Copy(yPtr, rotate, 1, 1); Marshal.Copy(zPtr, rotate, 2, 1); var temp = rotate[1]; rotate[0] = -rotate[0] * parts.F; rotate[1] = -rotate[2] * parts.F; rotate[2] = -temp * parts.F; babylonMesh.rotation = rotate; } babylonMesh.scaling = parts.K.ToArraySwitched(); if (wm.Parity) { vx1 = 2; vx2 = 1; vx3 = 0; } else { vx1 = 0; vx2 = 1; vx3 = 2; } // Pivot var pivotMatrix = Tools.Identity; pivotMatrix.PreTranslate(meshNode.ObjOffsetPos); Loader.Global.PreRotateMatrix(pivotMatrix, meshNode.ObjOffsetRot); Loader.Global.ApplyScaling(pivotMatrix, meshNode.ObjOffsetScale); babylonMesh.pivotMatrix = pivotMatrix.ToArray(); // Mesh var objectState = meshNode.EvalWorldState(0, false); var triObject = objectState.Obj.GetMesh(); var mesh = triObject != null ? triObject.Mesh : null; RaiseMessage(meshNode.Name, 1); if (mesh != null) { mesh.BuildNormals(); if (mesh.NumFaces < 1) { RaiseError(string.Format("Mesh {0} has no face", babylonMesh.name), 2); } if (mesh.NumVerts < 3) { RaiseError(string.Format("Mesh {0} has not enough vertices", babylonMesh.name), 2); } if (mesh.NumVerts >= 65536) { RaiseError(string.Format("Mesh {0} has too many vertices (more than 65535)", babylonMesh.name), 2); } // Material var mtl = meshNode.Mtl; var multiMatsCount = 1; if (mtl != null) { babylonMesh.materialId = mtl.GetGuid().ToString(); if (!referencedMaterials.Contains(mtl)) { referencedMaterials.Add(mtl); } multiMatsCount = Math.Max(mtl.NumSubMtls, 1); } babylonMesh.visibility = meshNode.GetVisibility(0, Tools.Forever); var vertices = new List<GlobalVertex>(); var indices = new List<int>(); var matIDs = new List<int>(); var hasUV = mesh.NumTVerts > 0; var hasUV2 = mesh.GetNumMapVerts(2) > 0; var optimizeVertices = meshNode.GetBoolProperty("babylonjs_optimizevertices"); // Skin IISkinContextData skinContext = null; if (skin != null) { skinContext = skin.GetContextInterface(meshNode); } // Compute normals VNormal[] vnorms = Tools.ComputeNormals(mesh, optimizeVertices); List<GlobalVertex>[] verticesAlreadyExported = null; if (optimizeVertices) { verticesAlreadyExported = new List<GlobalVertex>[mesh.NumVerts]; } for (var face = 0; face < mesh.NumFaces; face++) { indices.Add(CreateGlobalVertex(mesh, face, vx1, vertices, hasUV, hasUV2, vnorms, verticesAlreadyExported, skinContext)); indices.Add(CreateGlobalVertex(mesh, face, vx2, vertices, hasUV, hasUV2, vnorms, verticesAlreadyExported, skinContext)); indices.Add(CreateGlobalVertex(mesh, face, vx3, vertices, hasUV, hasUV2, vnorms, verticesAlreadyExported, skinContext)); matIDs.Add(mesh.Faces[face].MatID % multiMatsCount); CheckCancelled(); } if (vertices.Count >= 65536) { RaiseError(string.Format("Mesh {0} has too many vertices: {1} (limit is 65535)", babylonMesh.name, vertices.Count), 2); if (!optimizeVertices) { RaiseError("You can try to optimize your object using [Try to optimize vertices] option", 2); } } RaiseMessage(string.Format("{0} vertices, {1} faces", vertices.Count, indices.Count / 3), 2); // Buffers babylonMesh.positions = vertices.SelectMany(v => v.Position.ToArraySwitched()).ToArray(); babylonMesh.normals = vertices.SelectMany(v => v.Normal.ToArraySwitched()).ToArray(); if (hasUV) { babylonMesh.uvs = vertices.SelectMany(v => v.UV.ToArray()).ToArray(); } if (hasUV2) { babylonMesh.uvs2 = vertices.SelectMany(v => v.UV2.ToArray()).ToArray(); } if (skin != null) { babylonMesh.matricesWeights = vertices.SelectMany(v => v.Weights.ToArray()).ToArray(); babylonMesh.matricesIndices = vertices.Select(v => v.BonesIndices).ToArray(); } // Submeshes var sortedIndices = new List<int>(); var subMeshes = new List<BabylonSubMesh>(); var indexStart = 0; for (var index = 0; index < multiMatsCount; index++) { var subMesh = new BabylonSubMesh(); var indexCount = 0; var minVertexIndex = int.MaxValue; var maxVertexIndex = int.MinValue; subMesh.indexStart = indexStart; subMesh.materialIndex = index; for (var face = 0; face < matIDs.Count; face++) { if (matIDs[face] == index) { var a = indices[3 * face]; var b = indices[3 * face + 1]; var c = indices[3 * face + 2]; sortedIndices.Add(a); sortedIndices.Add(b); sortedIndices.Add(c); indexCount += 3; if (a < minVertexIndex) { minVertexIndex = a; } if (b < minVertexIndex) { minVertexIndex = b; } if (c < minVertexIndex) { minVertexIndex = c; } if (a > maxVertexIndex) { maxVertexIndex = a; } if (b > maxVertexIndex) { maxVertexIndex = b; } if (c > maxVertexIndex) { maxVertexIndex = c; } } } if (indexCount != 0) { subMesh.indexCount = indexCount; subMesh.verticesStart = minVertexIndex; subMesh.verticesCount = maxVertexIndex - minVertexIndex + 1; indexStart += indexCount; subMeshes.Add(subMesh); } CheckCancelled(); } babylonMesh.subMeshes = subMeshes.ToArray(); // Buffers - Indices babylonMesh.indices = sortedIndices.ToArray(); triObject.Dispose(); } // Animations var animations = new List<BabylonAnimation>(); if (!ExportVector3Controller(meshNode.TMController.PositionController, "position", animations)) { ExportVector3Animation("position", animations, key => { var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent()); return worldMatrix.Trans.ToArraySwitched(); }); } if (!ExportQuaternionController(meshNode.TMController.RotationController, "rotationQuaternion", animations)) { ExportQuaternionAnimation("rotationQuaternion", animations, key => { var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent()); var affineParts = Loader.Global.AffineParts.Create(); Loader.Global.DecompAffine(worldMatrix, affineParts); return affineParts.Q.ToArray(); }); } if (!ExportVector3Controller(meshNode.TMController.ScaleController, "scaling", animations)) { ExportVector3Animation("scaling", animations, key => { var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent()); var affineParts = Loader.Global.AffineParts.Create(); Loader.Global.DecompAffine(worldMatrix, affineParts); return affineParts.K.ToArraySwitched(); }); } if (!ExportFloatController(meshNode.VisController, "visibility", animations)) { ExportFloatAnimation("visibility", animations, key => new[] { meshNode.GetVisibility(key, Tools.Forever) }); } babylonMesh.animations = animations.ToArray(); if (meshNode.GetBoolProperty("babylonjs_autoanimate", 1)) { babylonMesh.autoAnimate = true; babylonMesh.autoAnimateFrom = (int)meshNode.GetFloatProperty("babylonjs_autoanimate_from"); babylonMesh.autoAnimateTo = (int)meshNode.GetFloatProperty("babylonjs_autoanimate_to", 100); babylonMesh.autoAnimateLoop = meshNode.GetBoolProperty("babylonjs_autoanimateloop", 1); } babylonScene.MeshesList.Add(babylonMesh); }
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); }
private BabylonNode ExportMesh(IIGameScene scene, IIGameNode meshNode, BabylonScene babylonScene) { if (IsMeshExportable(meshNode) == false) { return(null); } logger?.RaiseMessage(meshNode.Name, 1); if (!exportParameters.keepInstances) { return(ExportMasterMesh(scene, meshNode, babylonScene)); } else { // Instances #if MAX2020 || MAX2021 || MAX2022 var tabs = Loader.Global.INodeTab.Create(); #else var tabs = Loader.Global.NodeTab.Create(); #endif Loader.Global.IInstanceMgr.InstanceMgr.GetInstances(meshNode.MaxNode, tabs); if (tabs.Count > 1) { IINode Master = TabToList <IINode>(tabs)[tabs.Count - 1]; List <IINode> Instances = TabToList <IINode>(tabs).FindAll(x => x.Handle != Master.Handle); foreach (IINode instanceNode in tabs.ToIEnumerable()) { //this make sure every instance node is indexed in guid dictionary Tools.GetGuid(instanceNode); } BabylonMesh babylonMasterMesh = babylonScene.MeshesList.Find(mesh => mesh.id == Master.GetGuid().ToString()); if (babylonMasterMesh == null) { return(ExportMasterMesh(scene, meshNode, babylonScene)); } else { return(ExportInstanceMesh(scene, meshNode, babylonScene, babylonMasterMesh)); } } return(ExportMasterMesh(scene, meshNode, babylonScene)); } }
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; }
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); }
private IList <BabylonAnimationGroup> ExportAnimationGroups(BabylonScene babylonScene) { IList <BabylonAnimationGroup> animationGroups = new List <BabylonAnimationGroup>(); // Retrieve and parse animation group data AnimationGroupList animationList = InitAnimationGroups(); 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 (uint nodeHandle in animGroup.NodeHandles) { IINode maxNode = Loader.Core.RootNode.FindChildNode(nodeHandle); // 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 = maxNode.GetGuid().ToString() + "-bone"; // the suffix "-bone" is added in babylon export format to assure the uniqueness of IDs // Node BabylonNode node = babylonScene.MeshesList.FirstOrDefault(m => m.id == nodeId); if (node == null) { node = babylonScene.CamerasList.FirstOrDefault(c => c.id == nodeId); } if (node == null) { node = babylonScene.LightsList.FirstOrDefault(l => l.id == nodeId); } 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 ExportMesh(IINode meshNode, BabylonScene babylonScene) { if (meshNode.IsInstance()) { return; } if (meshNode.GetBoolProperty("babylonjs_noexport")) { return; } if (!ExportHiddenObjects && meshNode.IsHidden(NodeHideFlags.None, false)) { return; } var babylonMesh = new BabylonMesh(); int vx1, vx2, vx3; babylonMesh.name = meshNode.Name; babylonMesh.id = meshNode.GetGuid().ToString(); if (meshNode.HasParent()) { babylonMesh.parentId = meshNode.ParentNode.GetGuid().ToString(); } // Misc. babylonMesh.isVisible = meshNode.Renderable == 1; babylonMesh.pickable = meshNode.GetBoolProperty("babylonjs_checkpickable"); babylonMesh.receiveShadows = meshNode.RcvShadows == 1; babylonMesh.showBoundingBox = meshNode.GetBoolProperty("babylonjs_showboundingbox"); babylonMesh.showSubMeshesBoundingBox = meshNode.GetBoolProperty("babylonjs_showsubmeshesboundingbox"); // Collisions babylonMesh.checkCollisions = meshNode.GetBoolProperty("babylonjs_checkcollisions"); // Skin var skin = GetSkinModifier(meshNode); if (skin != null) { babylonMesh.skeletonId = skins.IndexOf(skin); bonesCount = skin.NumBones; } // Position / rotation / scaling var wm = Tools.ExtractCoordinates(meshNode, babylonMesh, exportQuaternionsInsteadOfEulers); if (wm.Parity) { vx1 = 2; vx2 = 1; vx3 = 0; } else { vx1 = 0; vx2 = 1; vx3 = 2; } // Pivot var pivotMatrix = Tools.Identity; pivotMatrix.PreTranslate(meshNode.ObjOffsetPos); Loader.Global.PreRotateMatrix(pivotMatrix, meshNode.ObjOffsetRot); Loader.Global.ApplyScaling(pivotMatrix, meshNode.ObjOffsetScale); babylonMesh.pivotMatrix = pivotMatrix.ToArray(); // Mesh var objectState = meshNode.EvalWorldState(0, false); var triObject = objectState.Obj.GetMesh(); var mesh = triObject != null ? triObject.Mesh : null; RaiseMessage(meshNode.Name, 1); if (mesh != null) { mesh.BuildNormals(); if (mesh.NumFaces < 1) { RaiseError(string.Format("Mesh {0} has no face", babylonMesh.name), 2); } if (mesh.NumVerts < 3) { RaiseError(string.Format("Mesh {0} has not enough vertices", babylonMesh.name), 2); } if (mesh.NumVerts >= 65536) { RaiseError(string.Format("Mesh {0} has too many vertices (more than 65535)", babylonMesh.name), 2); } // Material var mtl = meshNode.Mtl; var multiMatsCount = 1; if (mtl != null) { babylonMesh.materialId = mtl.GetGuid().ToString(); if (!referencedMaterials.Contains(mtl)) { referencedMaterials.Add(mtl); } multiMatsCount = Math.Max(mtl.NumSubMtls, 1); } babylonMesh.visibility = meshNode.GetVisibility(0, Tools.Forever); var vertices = new List <GlobalVertex>(); var indices = new List <int>(); var matIDs = new List <int>(); var hasUV = mesh.NumTVerts > 0; var hasUV2 = mesh.GetNumMapVerts(2) > 0; var optimizeVertices = meshNode.GetBoolProperty("babylonjs_optimizevertices"); // Skin IISkinContextData skinContext = null; if (skin != null) { skinContext = skin.GetContextInterface(meshNode); } // Compute normals VNormal[] vnorms = Tools.ComputeNormals(mesh, optimizeVertices); List <GlobalVertex>[] verticesAlreadyExported = null; if (optimizeVertices) { verticesAlreadyExported = new List <GlobalVertex> [mesh.NumVerts]; } for (var face = 0; face < mesh.NumFaces; face++) { indices.Add(CreateGlobalVertex(mesh, face, vx1, vertices, hasUV, hasUV2, vnorms, verticesAlreadyExported, skinContext)); indices.Add(CreateGlobalVertex(mesh, face, vx2, vertices, hasUV, hasUV2, vnorms, verticesAlreadyExported, skinContext)); indices.Add(CreateGlobalVertex(mesh, face, vx3, vertices, hasUV, hasUV2, vnorms, verticesAlreadyExported, skinContext)); matIDs.Add(mesh.Faces[face].MatID % multiMatsCount); CheckCancelled(); } if (vertices.Count >= 65536) { RaiseError(string.Format("Mesh {0} has too many vertices: {1} (limit is 65535)", babylonMesh.name, vertices.Count), 2); if (!optimizeVertices) { RaiseError("You can try to optimize your object using [Try to optimize vertices] option", 2); } } RaiseMessage(string.Format("{0} vertices, {1} faces", vertices.Count, indices.Count / 3), 2); // Buffers babylonMesh.positions = vertices.SelectMany(v => v.Position.ToArraySwitched()).ToArray(); babylonMesh.normals = vertices.SelectMany(v => v.Normal.ToArraySwitched()).ToArray(); if (hasUV) { babylonMesh.uvs = vertices.SelectMany(v => v.UV.ToArray()).ToArray(); } if (hasUV2) { babylonMesh.uvs2 = vertices.SelectMany(v => v.UV2.ToArray()).ToArray(); } if (skin != null) { babylonMesh.matricesWeights = vertices.SelectMany(v => v.Weights.ToArray()).ToArray(); babylonMesh.matricesIndices = vertices.Select(v => v.BonesIndices).ToArray(); } // Submeshes var sortedIndices = new List <int>(); var subMeshes = new List <BabylonSubMesh>(); var indexStart = 0; for (var index = 0; index < multiMatsCount; index++) { var subMesh = new BabylonSubMesh(); var indexCount = 0; var minVertexIndex = int.MaxValue; var maxVertexIndex = int.MinValue; subMesh.indexStart = indexStart; subMesh.materialIndex = index; for (var face = 0; face < matIDs.Count; face++) { if (matIDs[face] == index) { var a = indices[3 * face]; var b = indices[3 * face + 1]; var c = indices[3 * face + 2]; sortedIndices.Add(a); sortedIndices.Add(b); sortedIndices.Add(c); indexCount += 3; if (a < minVertexIndex) { minVertexIndex = a; } if (b < minVertexIndex) { minVertexIndex = b; } if (c < minVertexIndex) { minVertexIndex = c; } if (a > maxVertexIndex) { maxVertexIndex = a; } if (b > maxVertexIndex) { maxVertexIndex = b; } if (c > maxVertexIndex) { maxVertexIndex = c; } } } if (indexCount != 0) { subMesh.indexCount = indexCount; subMesh.verticesStart = minVertexIndex; subMesh.verticesCount = maxVertexIndex - minVertexIndex + 1; indexStart += indexCount; subMeshes.Add(subMesh); } CheckCancelled(); } babylonMesh.subMeshes = subMeshes.ToArray(); // Buffers - Indices babylonMesh.indices = sortedIndices.ToArray(); triObject.Dispose(); } // Instances var tabs = Loader.Global.NodeTab.Create(); Loader.Global.IInstanceMgr.InstanceMgr.GetInstances(meshNode, tabs); var instances = new List <BabylonAbstractMesh>(); for (var index = 0; index < tabs.Count; index++) { var indexer = new IntPtr(index); var tab = tabs[indexer]; Marshal.FreeHGlobal(indexer); if (meshNode.GetGuid() == tab.GetGuid()) { continue; } tab.MarkAsInstance(); var instance = new BabylonAbstractMesh { name = tab.Name }; Tools.ExtractCoordinates(tab, instance, exportQuaternionsInsteadOfEulers); var instanceAnimations = new List <BabylonAnimation>(); GenerateCoordinatesAnimations(tab, instanceAnimations); instance.animations = instanceAnimations.ToArray(); instances.Add(instance); } babylonMesh.instances = instances.ToArray(); // Animations var animations = new List <BabylonAnimation>(); GenerateCoordinatesAnimations(meshNode, animations); if (!ExportFloatController(meshNode.VisController, "visibility", animations)) { ExportFloatAnimation("visibility", animations, key => new[] { meshNode.GetVisibility(key, Tools.Forever) }); } babylonMesh.animations = animations.ToArray(); if (meshNode.GetBoolProperty("babylonjs_autoanimate", 1)) { babylonMesh.autoAnimate = true; babylonMesh.autoAnimateFrom = (int)meshNode.GetFloatProperty("babylonjs_autoanimate_from"); babylonMesh.autoAnimateTo = (int)meshNode.GetFloatProperty("babylonjs_autoanimate_to", 100); babylonMesh.autoAnimateLoop = meshNode.GetBoolProperty("babylonjs_autoanimateloop", 1); } babylonScene.MeshesList.Add(babylonMesh); }