public static bool HasRuntimeAccess(IMtl mat) { if (mat.IsMultiMtl) { for (int i = 0; i < mat.NumSubMtls; i++) { IMtl childMat = mat.GetSubMtl(i); if (childMat != null) { if (class_ID.Equals(childMat.ClassID)) { int p = Tools.GetMaterialProperty(childMat, "uniqueInContainer"); if (Convert.ToBoolean(p)) { return(true); } } } } } else if (class_ID.Equals(mat.ClassID)) { int p = Tools.GetMaterialProperty(mat, "uniqueInContainer"); if (Convert.ToBoolean(p)) { return(true); } } return(false); }
private IIGameMaterial GetBakedMaterialFromShellMaterial(IIGameMaterial materialNode) { if (isShellMaterial(materialNode)) { // Shell Material Parameters // Original Material not exported => only for the offline rendering in 3DS Max // Baked Material => used for the export IMtl bakedMtl = materialNode.IPropertyContainer.GetProperty(1).MaxParamBlock2.GetMtl(3, 0, 0); if (bakedMtl != null) { Guid guid = bakedMtl.GetGuid(); for (int indexSubMaterial = 0; indexSubMaterial < materialNode.SubMaterialCount; indexSubMaterial++) { IIGameMaterial subMaterialNode = materialNode.GetSubMaterial(indexSubMaterial); if (guid.Equals(subMaterialNode.MaxMaterial.GetGuid())) { return(subMaterialNode); } } } } return(null); }
/// <summary> /// Retrieve current selected material in slate material editor /// </summary> /// <returns></returns> public static IMtl GetSelectedMaterial() { string mxs = "viewNode = sme.GetView (sme.activeView)"; mxs += "\r\n" + "smeSelMats = #()"; mxs += "\r\n" + "if (trackViewNodes[#sme][(sme.activeView)] != undefined) then("; mxs += "\r\n" + "for n = 1 to trackViewNodes[#sme][(sme.activeView)].numSubs do ("; mxs += "\r\n" + "m = trackViewNodes[#sme][(sme.activeView)][n].reference"; mxs += "\r\n" + "b = viewNode.GetNodeByRef m"; mxs += "\r\n" + "if b.selected do append smeSelMats m)"; mxs += "\r\n" + "smeSelMats[1])"; IFPValue mxsRetVal = Loader.Global.FPValue.Create(); ScriptsUtilities.ExecuteMAXScriptScript(mxs, true, mxsRetVal); IMtl result = null; try { result = mxsRetVal.Mtl; } catch (Exception e) { //do nothing ,just retun a null material } return(result); }
/// <summary> /// fix the material ids /// sometimes inside a node more material ids are set on faces /// than materials are actually used /// </summary> /// <param name="nodeView"></param> private static void FixMaterialIDs(NodeView nodeView) { // get the used material from the node int iNumMaterials = 0; IMtl nodeMaterial = nodeView.Node.Mtl; // first check if a material is on the node // check as well if its a multimaterial if (nodeMaterial != null) { iNumMaterials = nodeMaterial.NumSubMtls > 0 ? nodeMaterial.NumSubMtls : 1; } // cycle through all face and check the MatID IFace[] arrFaces = nodeView.Mesh.Faces.ToArray(); for (int i = 0; i < arrFaces.Length; i++) { if (arrFaces[i].MatID < iNumMaterials) { continue; } arrFaces[i].MatID = iNumMaterials > 0 ? (ushort)(arrFaces[i].MatID % iNumMaterials) : (ushort)0; } // very important. call this to notify max that this node has changed // this is similar to events in c# nodeView.Node.NotifyDependents(Globals.FOREVER, Globals.PART_ALL, RefMessage.NodeMaterialChanged); nodeView.Node.NotifyDependents(Globals.FOREVER, Globals.PART_ALL, RefMessage.Change); }
/// <summary> /// fix the material ids /// sometimes inside a node more material ids are set on faces /// than materials are actually used /// </summary> /// <param name="nodeData"></param> private static async Task CheckMatIds(sNodeData nodeData) { await Task.Run(() => { IMesh mesh = nodeData.ViewNode.Mesh; // get the used material from the node int iNumMaterials = 0; IMtl nodeMaterial = nodeData.ViewNode.Node.Mtl; // first check if a material is on the node // check as well if its a multimaterial if (nodeMaterial != null) { iNumMaterials = nodeMaterial.NumSubMtls > 0 ? nodeMaterial.NumSubMtls : 1; } // cycle through all face and check the MatID IFace[] arrFaces = mesh.Faces.ToArray(); for (int i = 0; i < arrFaces.Length; i++) { if (arrFaces[i].MatID > iNumMaterials) { nodeData.ViewNode.WrongMatIDCount++; } } }); }
public bool GetGltfMaterial(BabylonMaterial babylonMaterial, GLTF gltf, ILoggingProvider logger, out GLTFMaterial gltfMaterial) { gltfMaterial = null; IIGameMaterial gameMtl = babylonMaterial.maxGameMaterial; if (gameMtl == null || gameMtl.MaxMaterial == null) { return(false); } IMtl maxMtl = gameMtl.MaxMaterial; IMaxMaterialExporter materialExporter; if (materialExporters.TryGetValue(new ClassIDWrapper(maxMtl.ClassID), out materialExporter) && materialExporter is IMaxGLTFMaterialExporter) { gltfMaterial = ((IMaxGLTFMaterialExporter)materialExporter).ExportGLTFMaterial(this.exportParameters, gltf, gameMtl, (string sourcePath, string textureName) => { return(this.TryWriteImage(gltf, sourcePath, textureName, exportParameters, logger)); }, (string message, Color color) => { logger.RaiseMessage(message, color, 2); }, (string message) => { logger.RaiseWarning(message, 2); }, (string message) => { logger.RaiseError(message, 2); }); if (gltfMaterial == null) { string message = string.Format("Custom glTF material exporter failed to export | Exporter: '{0}' | Material Name: '{1}' | Material Class: '{2}'", materialExporter.GetType().ToString(), gameMtl.MaterialName, gameMtl.ClassName); logger.RaiseWarning(message, 2); return(false); } return(true); } return(false); }
private ListViewItem FillMaterialItem(IMtl material, Guid guid) { if (previousMaterialMap.ContainsKey(guid)) { return(null); } ListViewItem item = new ListViewItem(); item.Text = material.Name; Items.Add(item); return(item); }
MaterialInformation GetMaterialProperties(IMtl material, MessageMaterialRequest request) { if (material == null) { return null; } if (request.m_materialIndex < 0) { return GetMaterialProperties(material); } return GetMaterialProperties(material.GetSubMtl(request.m_materialIndex)); }
public void FillMaterialsView(IList <Guid> infoMaterialGuids) { Items.Clear(); foreach (var dicKeyValue in Tools.guids) { if (infoMaterialGuids.Contains(dicKeyValue.Key)) { IMtl animMat = dicKeyValue.Value as IMtl; AddMaterial(animMat); } } currentMaterialMap = previousMaterialMap.ToDictionary(entry => entry.Key, entry => (ListViewItem)entry.Value.Clone());; }
private IIGameMaterial GetRenderMaterialFromDirectXShader(IIGameMaterial materialNode) { IIGameMaterial renderMaterial = null; if (isDirectXShaderMaterial(materialNode)) { var gameScene = Loader.Global.IGameInterface; IMtl renderMtl = materialNode.IPropertyContainer.GetProperty(35).MaxParamBlock2.GetMtl(4, 0, 0); if (renderMtl != null) { renderMaterial = gameScene.GetIGameMaterial(renderMtl); } } return(renderMaterial); }
public static bool IsMaterialAssignedInScene(IMtl mtl) { for (int i = 0; i < Loader.Core.SceneMtls.Count; i++) { IMtl sceneMtl = null; #if MAX2015 || MAX2016 sceneMtl = (IMtl)Loader.Core.SceneMtls[new IntPtr(i)]; #else sceneMtl = (IMtl)Loader.Core.SceneMtls[i]; #endif if (sceneMtl != null && mtl.GetNativeHandle() == sceneMtl.GetNativeHandle()) { return(true); } } return(false); }
public void AddMaterial(IMtl material) { if (material == null) { return; } if (!FlightSimMaterialUtilities.IsFlightSimMaterial(material)) { return; } Guid matGuid = material.GetGuid(); ListViewItem item = FillMaterialItem(material, matGuid); if (item != null) { previousMaterialMap.Add(matGuid, item); } }
public void RemoveMaterialFromSelection(IMtl material) { if (material == null) { return; } if (!FlightSimMaterialUtilities.IsFlightSimMaterial(material)) { return; } Guid matGuid = material.GetGuid(); ListViewItem itemToRemove; if (previousMaterialMap.TryGetValue(matGuid, out itemToRemove)) { itemToRemove.BackColor = Color.Red; currentMaterialMap.Remove(matGuid); } }
public static bool HasFlightSimMaterials(IMtl mat) { if (mat.IsMultiMtl) { for (int i = 0; i < mat.NumSubMtls; i++) { IMtl childMat = mat.GetSubMtl(i); if (childMat != null && class_ID.Equals(childMat.ClassID)) { return(true); } } } else if (mat != null && class_ID.Equals(mat.ClassID)) { return(true); } return(false); }
public static IMtl GetAnimatableMaterial(this IINode node) { IMtl material = node.Mtl; if (material == null) { MessageBox.Show("No Material found for the selected node"); return(null); } if (material.IsMultiMtl) { MessageBox.Show("MultiMaterial animation is not supported, use a non-MultiMaterial material"); return(null); } if (!FlightSimMaterialUtilities.IsFlightSimMaterial(material)) { MessageBox.Show("Material animation is supported only for FlightSimMaterial"); return(null); } return(material); }
MaterialInformation GetMaterialProperties(IMtl material) { if (material == null) { return null; } MaterialInformation m = new MaterialInformation(); m.m_className = material.ClassName; m.m_materialName = material.Name; m.m_handle = _gi.Animatable.GetHandleByAnim(material).ToUInt64(); var prps = EnumerateProperties(material).ToList(); foreach (var p in EnumerateProperties(material)) { m.MaterialProperties.Add(new MaterialProperty(p.m_parameterName, p.m_internalName, p.GetValue())); } return m; }
public void AddMaterialFromSelection(IMtl material) { if (material == null) { return; } if (!MaterialUtilities.IsMaterialAssignedInScene(material)) { return; } if (!FlightSimMaterialUtilities.IsFlightSimMaterial(material)) { return; } Guid matGuid = material.GetGuid(); ListViewItem item = FillMaterialItem(material, matGuid); if (item != null) { currentMaterialMap.Add(matGuid, item); item.BackColor = Color.Green; } }
private IIGameMaterial GetRenderMaterialFromDirectXShader(IIGameMaterial materialNode) { IIGameMaterial renderMaterial = null; if (isDirectXShaderMaterial(materialNode)) { var gameScene = Loader.Global.IGameInterface; IIGameProperty property = materialNode.IPropertyContainer.GetProperty(35); if (property != null) { IMtl renderMtl = materialNode.IPropertyContainer.GetProperty(35).MaxParamBlock2.GetMtl(4, 0, 0); if (renderMtl != null) { renderMaterial = gameScene.GetIGameMaterial(renderMtl); } } else { RaiseWarning($"DirectX material property for {materialNode.MaterialName} is null...", 2); } } return(renderMaterial); }
private void removeNodeButton_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); MaxNodeTree.QueueRemoveNode(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.RemoveMaterialFromSelection(material); } } } }
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); } } } } }
internal Material(IMtl x) : base(x) { }
public MaterialObjectsWrapper(IMtl material) { this.Material = material; }
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 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); } } } }
private void getMaterials(ref int geoIndex) { if (ReadUInt32() != (uint)secIDs.MATERIAL_LIST) { datIndex -= 4; return; } //get number of materials datIndex += 20; int matCount = ReadInt32(); //skip trash FFFF data (one for each material) datIndex += matCount * 4; mtlList[geoIndex] = (IMultiMtl)ip.CreateInstance(SClass_ID.Material, global.Class_ID.Create((uint)BuiltInClassIDA.MULTI_CLASS_ID, 0)); mtlList[geoIndex].SetNumSubMtls(matCount); //read material data for (int i = 0; i < matCount; ++i) { IMtl leMat = (IMtl)ip.CreateInstance(SClass_ID.Material, global.Class_ID.Create((uint)custClassIDs.GTAMAT_A, (uint)custClassIDs.GTAMAT_B)); //skip material header, struct header and integer datIndex += 28; //read color leMat.GetParamBlock(0).SetValue(3, 0, global.Color.Create(data[datIndex] / 255.0f, data[datIndex + 1] / 255.0f, data[datIndex + 2] / 255.0f), 0); leMat.GetParamBlock(0).SetValue(6, 0, (int)data[datIndex + 3], 0); //increment and skip unknown datIndex += 8; uint numTextures = ReadUInt32(); //ambient, diffuse and specular? leMat.GetParamBlock(0).SetValue(0, 0, ReadSingle(), 0); leMat.GetParamBlock(0).SetValue(1, 0, ReadSingle(), 0); leMat.GetParamBlock(0).SetValue(2, 0, ReadSingle(), 0); mtlList[geoIndex].SetSubMtl(i, leMat); //read textures for (int ind = 0; ind < numTextures; ++ind) { //skip texture and struct header datIndex += 24; int filtAddr = datIndex; datIndex += 4; //skip three bytes (used later)+1 unknown. //read diffuse texture name datIndex += 4; //skip header int size = ReadInt32(); datIndex += 4; //skip RW version IBitmapTex diffTex = (IBitmapTex)ip.CreateInstance(SClass_ID.Texmap, global.Class_ID.Create((uint)BuiltInClassIDA.BMTEX_CLASS_ID, 0)); diffTex.Name = ReadString(ref size); //read alpha texture name datIndex += 4; //skip header size = ReadInt32(); datIndex += 4; //skip RW version IBitmapTex alphaTex = (IBitmapTex)ip.CreateInstance(SClass_ID.Texmap, global.Class_ID.Create((uint)BuiltInClassIDA.BMTEX_CLASS_ID, 0)); alphaTex.Name = ReadString(ref size); //set tiling and mirror data from filter flags switch (data[filtAddr]) { case 1: diffTex.FilterType = 2; //FILTER_NADA alphaTex.FilterType = 2; break; case 2: diffTex.FilterType = 1; //FILTER_SAT alphaTex.FilterType = 1; //FILTER_SAT break; default: diffTex.FilterType = 0; //FILTER_PYR alphaTex.FilterType = 0; //FILTER_PYR break; } diffTex.UVGen.SetFlag(1 << 2, ~(data[filtAddr + 1] | 0xfffffffe)); diffTex.UVGen.SetFlag(1 << 0, ~(data[filtAddr + 1] | 0xfffffffd)); diffTex.UVGen.SetFlag(1 << 3, ~(data[filtAddr + 1] | 0xffffffef)); diffTex.UVGen.SetFlag(1 << 1, ~(data[filtAddr + 1] | 0xffffffdf)); alphaTex.UVGen.SetFlag(1 << 2, ~(data[filtAddr + 1] | 0xfffffffe)); alphaTex.UVGen.SetFlag(1 << 0, ~(data[filtAddr + 1] | 0xfffffffd)); alphaTex.UVGen.SetFlag(1 << 3, ~(data[filtAddr + 1] | 0xffffffef)); alphaTex.UVGen.SetFlag(1 << 1, ~(data[filtAddr + 1] | 0xffffffdf)); leMat.GetParamBlock(0).SetValue(4, 0, diffTex, 0); leMat.GetParamBlock(0).SetValue(7, 0, alphaTex, 0); leMat.GetParamBlock(0).SetValue(8, 0, 0, 0); //skip extension if (ReadUInt32() == (uint)secIDs.EXTENSION) { int temp = ReadInt32(); datIndex += temp + 4; } else { datIndex -= 4; } } //read material effects if (ReadUInt32() == (uint)secIDs.EXTENSION) { datIndex += 8; //skip section size and RW version //check for material effects, reflection and specular material for (int ind = 0; ind < 3; ++ind) { switch (ReadUInt32()) { case (uint)secIDs.MATERIAL_EFFECTS_PLG: { datIndex += 16; //skip section size, RW version and starting ints (both 2) leMat.GetParamBlock(0).SetValue(9, 0, 100.0f * ReadSingle(), 0); //reflection leMat.GetParamBlock(0).SetValue(11, 0, 1, 0); datIndex += 8; //skip unknown (= 0), skip texture ON/OFF switch 0/1 if (ReadUInt32() == (uint)secIDs.TEXTURE) { //skip texture and struct header datIndex += 20; int filtAddr = datIndex; datIndex += 4; //skip 3 filtering bytes + unkown //read diffuse texture name datIndex += 4; //skip header int size = ReadInt32(); datIndex += 4; //skip RW version IBitmapTex diffTex = (IBitmapTex)ip.CreateInstance(SClass_ID.Texmap, global.Class_ID.Create((uint)BuiltInClassIDA.BMTEX_CLASS_ID, 0)); diffTex.Name = ReadString(ref size); //skip alpha texture if (ReadUInt32() == 0x02) { int temp = ReadInt32(); datIndex += temp + 4; } else { datIndex -= 4; } //set tiling and mirror data from filter flags switch (data[filtAddr]) { case 1: diffTex.FilterType = 2; //FILTER_NADA break; case 2: diffTex.FilterType = 1; //FILTER_SAT break; default: diffTex.FilterType = 0; //FILTER_PYR break; } diffTex.UVGen.SetFlag(1 << 2, ~(data[filtAddr + 1] | 0xfffffffe)); diffTex.UVGen.SetFlag(1 << 0, ~(data[filtAddr + 1] | 0xfffffffd)); diffTex.UVGen.SetFlag(1 << 3, ~(data[filtAddr + 1] | 0xffffffef)); diffTex.UVGen.SetFlag(1 << 1, ~(data[filtAddr + 1] | 0xffffffdf)); leMat.GetParamBlock(0).SetValue(10, 0, diffTex, 0); datIndex += 16; //for some reason zero size extension contains data 00 00 00 00 } } break; case (uint)secIDs.REFLECTION_MATERIAL: { datIndex += 8; leMat.GetParamBlock(0).SetValue(12, 0, global.Color.Create(ReadSingle(), ReadSingle(), ReadSingle()), 0); leMat.GetParamBlock(0).SetValue(15, 0, 255.0f * ReadSingle(), 0); leMat.GetParamBlock(0).SetValue(17, 0, ReadSingle(), 0); datIndex += 4; //skip unknown } break; case (uint)secIDs.SPECULAR_MATERIAL: { int secSize = ReadInt32() - 4; //section size-4 because the float read in ReadSingle() takes up 4 bytes datIndex += 4; leMat.GetParamBlock(0).SetValue(16, 0, 255.0f * ReadSingle(), 0); IBitmapTex diffTex = (IBitmapTex)ip.CreateInstance(SClass_ID.Texmap, global.Class_ID.Create((uint)BuiltInClassIDA.BMTEX_CLASS_ID, 0)); diffTex.Name = ReadString(ref secSize); //-4 because the float read in ReadSingle() takes up 4 bytes //MessageBox.Show(diffTex.Name); //MessageBox.Show(datIndex.ToString()); leMat.GetParamBlock(0).SetValue(13, 0, diffTex, 0); } break; default: datIndex -= 4; break; } } } else { datIndex -= 4; } } // skip extension if (ReadUInt32() == (uint)secIDs.EXTENSION) { int temp = ReadInt32(); datIndex += temp + 4; } else { datIndex -= 4; } }
/// <summary> /// Initializes a new instance of the MaterialWrapper class. /// </summary> /// <param name="material">The IMtl object to wrap.</param> public MaterialWrapper(IMtl material) { Throw.IfNull(material, "material"); this.Material = material; }
private void ExportMaterial(IMtl materialNode, BabylonScene babylonScene) { var name = materialNode.Name; var id = materialNode.GetGuid().ToString(); RaiseMessage(name, 1); if (materialNode.NumSubMtls > 0) { var babylonMultimaterial = new BabylonMultiMaterial { name = name, id = id }; var guids = new List <string>(); for (var index = 0; index < materialNode.NumSubMtls; index++) { var subMat = materialNode.GetSubMtl(index); if (subMat != null) { guids.Add(subMat.GetGuid().ToString()); if (!referencedMaterials.Contains(subMat)) { referencedMaterials.Add(subMat); ExportMaterial(subMat, babylonScene); } } else { guids.Add(Guid.Empty.ToString()); } } babylonMultimaterial.materials = guids.ToArray(); babylonScene.MultiMaterialsList.Add(babylonMultimaterial); return; } var babylonMaterial = new BabylonMaterial { name = name, id = id, ambient = materialNode.GetAmbient(0, false).ToArray(), diffuse = materialNode.GetDiffuse(0, false).ToArray(), specular = materialNode.GetSpecular(0, false).Scale(materialNode.GetShinStr(0, false)), specularPower = materialNode.GetShininess(0, false) * 256, emissive = materialNode.GetSelfIllumColorOn(0, false) ? materialNode.GetSelfIllumColor(0, false).ToArray() : materialNode.GetDiffuse(0, false).Scale(materialNode.GetSelfIllum(0, false)), alpha = 1.0f - materialNode.GetXParency(0, false) }; var stdMat = materialNode.GetParamBlock(0).Owner as IStdMat2; if (stdMat != null) { babylonMaterial.backFaceCulling = !stdMat.TwoSided; babylonMaterial.wireframe = stdMat.Wire; // Textures BabylonFresnelParameters fresnelParameters; babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, out fresnelParameters, babylonScene); // Ambient babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, out fresnelParameters, babylonScene); // Diffuse if (fresnelParameters != null) { babylonMaterial.diffuseFresnelParameters = fresnelParameters; } babylonMaterial.specularTexture = ExportTexture(stdMat, 2, out fresnelParameters, babylonScene); // Specular babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, out fresnelParameters, babylonScene); // Emissive if (fresnelParameters != null) { babylonMaterial.emissiveFresnelParameters = fresnelParameters; if (babylonMaterial.emissive[0] == 0 && babylonMaterial.emissive[1] == 0 && babylonMaterial.emissive[2] == 0) { babylonMaterial.emissive = new float[] { 1, 1, 1 }; } } babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, out fresnelParameters, babylonScene, false, true); // Opacity if (fresnelParameters != null) { babylonMaterial.opacityFresnelParameters = fresnelParameters; } babylonMaterial.bumpTexture = ExportTexture(stdMat, 8, out fresnelParameters, babylonScene); // Bump babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, out fresnelParameters, babylonScene, true); // Reflection if (fresnelParameters != null) { if (babylonMaterial.reflectionTexture == null) { RaiseWarning("Fallout cannot be used with reflection channel without a texture", 2); } else { babylonMaterial.reflectionFresnelParameters = fresnelParameters; } } // Constraints if (babylonMaterial.diffuseTexture != null) { babylonMaterial.diffuse = new [] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new float[] { 0, 0, 0 }; } if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null && babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name && babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB) { // This is a alpha testing purpose babylonMaterial.opacityTexture = null; babylonMaterial.diffuseTexture.hasAlpha = true; RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", 2); RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", 2); } } babylonScene.MaterialsList.Add(babylonMaterial); }
public static bool IsFlightSimMaterial(IMtl mat) { return(mat != null && class_ID.Equals(mat.ClassID)); }
private void ExportMaterial(IMtl materialNode, BabylonScene babylonScene) { var name = materialNode.Name; var id = materialNode.GetGuid().ToString(); RaiseMessage(name, 1); if (materialNode.NumSubMtls > 0) { var babylonMultimaterial = new BabylonMultiMaterial(); babylonMultimaterial.name = name; babylonMultimaterial.id = id; var guids = new List<string>(); for (var index = 0; index < materialNode.NumSubMtls; index++) { var subMat = materialNode.GetSubMtl(index); if (subMat != null) { guids.Add(subMat.GetGuid().ToString()); if (!referencedMaterials.Contains(subMat)) { referencedMaterials.Add(subMat); ExportMaterial(subMat, babylonScene); } } else { guids.Add(Guid.Empty.ToString()); } } babylonMultimaterial.materials = guids.ToArray(); babylonScene.MultiMaterialsList.Add(babylonMultimaterial); return; } var babylonMaterial = new BabylonMaterial(); babylonMaterial.name = name; babylonMaterial.id = id; babylonMaterial.ambient = materialNode.GetAmbient(0, false).ToArray(); babylonMaterial.diffuse = materialNode.GetDiffuse(0, false).ToArray(); babylonMaterial.specular = materialNode.GetSpecular(0, false).Scale(materialNode.GetShinStr(0, false)); babylonMaterial.specularPower = materialNode.GetShininess(0, false) * 256; babylonMaterial.emissive = materialNode.GetSelfIllumColorOn(0, false) ? materialNode.GetSelfIllumColor(0, false).ToArray() : materialNode.GetDiffuse(0, false).Scale(materialNode.GetSelfIllum(0, false)); babylonMaterial.alpha = 1.0f - materialNode.GetXParency(0, false); var stdMat = materialNode.GetParamBlock(0).Owner as IStdMat2; if (stdMat != null) { babylonMaterial.backFaceCulling = !stdMat.TwoSided; babylonMaterial.wireframe = stdMat.Wire; // Textures babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, babylonScene); // Ambient babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, babylonScene); // Diffuse babylonMaterial.specularTexture = ExportTexture(stdMat, 2, babylonScene); // Specular babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, babylonScene); // Emissive babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, babylonScene, false, true); // Opacity babylonMaterial.bumpTexture = ExportTexture(stdMat, 8, babylonScene); // Bump babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, babylonScene, true); // Reflection // Constraints if (babylonMaterial.diffuseTexture != null) { babylonMaterial.diffuse = new [] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new float[]{0, 0, 0}; } if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null && babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name && babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB) { // This is a alpha testing purpose babylonMaterial.opacityTexture = null; babylonMaterial.diffuseTexture.hasAlpha = true; RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", 2); RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", 2); } } babylonScene.MaterialsList.Add(babylonMaterial); }
private void ExportMaterial(BabylonMaterial babylonMaterial, GLTF gltf) { var name = babylonMaterial.name; var id = babylonMaterial.id; RaiseMessage("GLTFExporter.Material | Export material named: " + name, 1); GLTFMaterial gltfMaterial = null; IIGameMaterial gameMtl = babylonMaterial.maxGameMaterial; IMtl maxMtl = gameMtl.MaxMaterial; IMaterialExporter materialExporter; if (materialExporters.TryGetValue(new ClassIDWrapper(maxMtl.ClassID), out materialExporter) && materialExporter is IGLTFMaterialExporter) { gltfMaterial = ((IGLTFMaterialExporter)materialExporter).ExportGLTFMaterial(this, gltf, gameMtl, (string sourcePath, string textureName) => { return TryWriteImage(gltf, sourcePath, textureName); }, (string message, Color color) => { RaiseMessage(message, color, 2); }, (string message) => { RaiseWarning(message, 2); }, (string message) => { RaiseError(message, 2); }); if (gltfMaterial == null) { string message = string.Format("Custom glTF material exporter failed to export | Exporter: '{0}' | Material Name: '{1}' | Material Class: '{2}'", materialExporter.GetType().ToString(), gameMtl.MaterialName, gameMtl.ClassName); RaiseWarning(message, 2); } else { gltfMaterial.index = gltf.MaterialsList.Count; gltf.MaterialsList.Add(gltfMaterial); } } else if (babylonMaterial.GetType() == typeof(BabylonStandardMaterial)) { var babylonStandardMaterial = babylonMaterial as BabylonStandardMaterial; // --- prints --- #region prints RaiseVerbose("GLTFExporter.Material | babylonMaterial data", 2); RaiseVerbose("GLTFExporter.Material | babylonMaterial.alpha=" + babylonMaterial.alpha, 3); RaiseVerbose("GLTFExporter.Material | babylonMaterial.alphaMode=" + babylonMaterial.alphaMode, 3); RaiseVerbose("GLTFExporter.Material | babylonMaterial.backFaceCulling=" + babylonMaterial.backFaceCulling, 3); RaiseVerbose("GLTFExporter.Material | babylonMaterial.wireframe=" + babylonMaterial.wireframe, 3); // Ambient for (int i = 0; i < babylonStandardMaterial.ambient.Length; i++) { RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.ambient[" + i + "]=" + babylonStandardMaterial.ambient[i], 3); } // Diffuse RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuse.Length=" + babylonStandardMaterial.diffuse.Length, 3); for (int i = 0; i < babylonStandardMaterial.diffuse.Length; i++) { RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuse[" + i + "]=" + babylonStandardMaterial.diffuse[i], 3); } if (babylonStandardMaterial.diffuseTexture == null) { RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuseTexture=null", 3); } else { RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuseTexture.name=" + babylonStandardMaterial.diffuseTexture.name, 3); } // Normal / bump if (babylonStandardMaterial.bumpTexture == null) { RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.bumpTexture=null", 3); } else { RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.bumpTexture.name=" + babylonStandardMaterial.bumpTexture.name, 3); } // Opacity if (babylonStandardMaterial.opacityTexture == null) { RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.opacityTexture=null", 3); } else { RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.opacityTexture.name=" + babylonStandardMaterial.opacityTexture.name, 3); } // Specular for (int i = 0; i < babylonStandardMaterial.specular.Length; i++) { RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specular[" + i + "]=" + babylonStandardMaterial.specular[i], 3); } RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specularPower=" + babylonStandardMaterial.specularPower, 3); if (babylonStandardMaterial.specularTexture == null) { RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specularTexture=null", 3); } else { RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specularTexture.name=" + babylonStandardMaterial.specularTexture.name, 3); } // Occlusion if (babylonStandardMaterial.ambientTexture == null) { RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.ambientTexture=null", 3); } else { RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.ambientTexture.name=" + babylonStandardMaterial.ambientTexture.name, 3); } // Emissive for (int i = 0; i < babylonStandardMaterial.emissive.Length; i++) { RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.emissive[" + i + "]=" + babylonStandardMaterial.emissive[i], 3); } if (babylonStandardMaterial.emissiveTexture == null) { RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.emissiveTexture=null", 3); } else { RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.emissiveTexture.name=" + babylonStandardMaterial.emissiveTexture.name, 3); } #endregion // -------------------------------- // --------- gltfMaterial --------- // -------------------------------- RaiseMessage("GLTFExporter.Material | create gltfMaterial", 2); gltfMaterial = new GLTFMaterial { name = name }; gltfMaterial.id = babylonMaterial.id; gltfMaterial.index = gltf.MaterialsList.Count; gltf.MaterialsList.Add(gltfMaterial); // Alpha string alphaMode; float? alphaCutoff; getAlphaMode(babylonStandardMaterial, out alphaMode, out alphaCutoff); gltfMaterial.alphaMode = alphaMode; gltfMaterial.alphaCutoff = alphaCutoff; // DoubleSided gltfMaterial.doubleSided = !babylonMaterial.backFaceCulling; // Normal gltfMaterial.normalTexture = ExportTexture(babylonStandardMaterial.bumpTexture, gltf); // Occulison gltfMaterial.occlusionTexture = ExportTexture(babylonStandardMaterial.ambientTexture, gltf); // Emissive gltfMaterial.emissiveFactor = babylonStandardMaterial.emissive; // linkEmissiveWithDiffuse attribute doesn't have an equivalent in gltf format // When true, the emissive texture needs to be manually multiplied with diffuse texture // Otherwise, the emissive texture is assumed to be already pre-multiplied if (babylonStandardMaterial.linkEmissiveWithDiffuse) { // Even when no emissive texture is provided, the self illumination value needs to be multiplied to the diffuse texture in order to get the pre-multiplied emissive (texture) if (babylonStandardMaterial.emissiveTexture != null || babylonStandardMaterial.selfIllum > 0) { // Default emissive is the raw value of the self illumination // It is not the babylon emissive value which is already pre-multiplied with diffuse color float[] defaultEmissive = new float[] { 1, 1, 1 }.Multiply(babylonStandardMaterial.selfIllum); gltfMaterial.emissiveTexture = ExportEmissiveTexture(babylonStandardMaterial, gltf, defaultEmissive, babylonStandardMaterial.diffuse); } } else { gltfMaterial.emissiveTexture = ExportTexture(babylonStandardMaterial.emissiveTexture, gltf); } // Constraints if (gltfMaterial.emissiveTexture != null) { gltfMaterial.emissiveFactor = new[] { 1.0f, 1.0f, 1.0f }; } // -------------------------------- // --- gltfPbrMetallicRoughness --- // -------------------------------- RaiseMessage("GLTFExporter.Material | create gltfPbrMetallicRoughness", 2); var gltfPbrMetallicRoughness = new GLTFPBRMetallicRoughness(); gltfMaterial.pbrMetallicRoughness = gltfPbrMetallicRoughness; // --- Global --- // Eye Ball correction to limit overall brightness from std to PBR. // This only impacts the factors. var correctedDiffuse = new BabylonColor3(babylonStandardMaterial.diffuse).scale(0.5f); SpecularGlossiness _specularGlossiness = new SpecularGlossiness { diffuse = correctedDiffuse, opacity = babylonMaterial.alpha, specular = new BabylonColor3(babylonStandardMaterial.specular), glossiness = babylonStandardMaterial.specularPower / 256 }; MetallicRoughness _metallicRoughness = ConvertToMetallicRoughness(_specularGlossiness, true); // Base color gltfPbrMetallicRoughness.baseColorFactor = new float[4] { _metallicRoughness.baseColor.r, _metallicRoughness.baseColor.g, _metallicRoughness.baseColor.b, _metallicRoughness.opacity }; // Metallic roughness gltfPbrMetallicRoughness.metallicFactor = _metallicRoughness.metallic; gltfPbrMetallicRoughness.roughnessFactor = _metallicRoughness.roughness; // --- Textures --- var babylonTexture = babylonStandardMaterial.diffuseTexture != null ? babylonStandardMaterial.diffuseTexture : babylonStandardMaterial.specularTexture != null ? babylonStandardMaterial.specularTexture : babylonStandardMaterial.opacityTexture != null ? babylonStandardMaterial.opacityTexture : null; if (babylonTexture != null) { //Check if the texture already exist var _key = SetStandText(babylonStandardMaterial); bool isAlphaInTexture = (isTextureOk(babylonStandardMaterial.diffuseTexture) && babylonStandardMaterial.diffuseTexture.hasAlpha) || isTextureOk(babylonStandardMaterial.opacityTexture); Bitmap baseColorBitmap = null; Bitmap metallicRoughnessBitmap = null; GLTFTextureInfo textureInfoBC = new GLTFTextureInfo(); GLTFTextureInfo textureInfoMR = new GLTFTextureInfo(); if (exportParameters.writeTextures) { // Diffuse Bitmap diffuseBitmap = null; if (babylonStandardMaterial.diffuseTexture != null) { diffuseBitmap = LoadTexture(babylonStandardMaterial.diffuseTexture.originalPath); } // Specular Bitmap specularBitmap = null; if (babylonStandardMaterial.specularTexture != null) { if (babylonStandardMaterial.specularTexture.bitmap != null) { // Specular color map has been computed by the exporter specularBitmap = babylonStandardMaterial.specularTexture.bitmap; } else { // Specular color map is straight input specularBitmap = LoadTexture(babylonStandardMaterial.specularTexture.originalPath); } } // Opacity / Alpha / Transparency Bitmap opacityBitmap = null; if ((babylonStandardMaterial.diffuseTexture == null || babylonStandardMaterial.diffuseTexture.hasAlpha == false) && babylonStandardMaterial.opacityTexture != null) { opacityBitmap = LoadTexture(babylonStandardMaterial.opacityTexture.originalPath); } if (diffuseBitmap != null || specularBitmap != null || opacityBitmap != null) { // Retreive dimensions int width = 0; int height = 0; var haveSameDimensions = _getMinimalBitmapDimensions(out width, out height, diffuseBitmap, specularBitmap, opacityBitmap); if (!haveSameDimensions) { RaiseError("Diffuse, specular and opacity maps should have same dimensions", 2); } // Create baseColor+alpha and metallic+roughness maps baseColorBitmap = new Bitmap(width, height); metallicRoughnessBitmap = new Bitmap(width, height); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { SpecularGlossiness specularGlossinessTexture = new SpecularGlossiness { diffuse = diffuseBitmap != null ? new BabylonColor3(diffuseBitmap.GetPixel(x, y)) : _specularGlossiness.diffuse, opacity = diffuseBitmap != null && babylonStandardMaterial.diffuseTexture.hasAlpha ? diffuseBitmap.GetPixel(x, y).A / 255.0f : opacityBitmap != null && babylonStandardMaterial.opacityTexture.getAlphaFromRGB ? opacityBitmap.GetPixel(x, y).R / 255.0f : opacityBitmap != null && babylonStandardMaterial.opacityTexture.getAlphaFromRGB == false ? opacityBitmap.GetPixel(x, y).A / 255.0f : _specularGlossiness.opacity, specular = specularBitmap != null ? new BabylonColor3(specularBitmap.GetPixel(x, y)) : _specularGlossiness.specular, glossiness = babylonStandardMaterial.useGlossinessFromSpecularMapAlpha && specularBitmap != null ? specularBitmap.GetPixel(x, y).A / 255.0f : _specularGlossiness.glossiness }; var displayPrints = x == width / 2 && y == height / 2; MetallicRoughness metallicRoughnessTexture = ConvertToMetallicRoughness(specularGlossinessTexture, displayPrints); Color colorBase = Color.FromArgb( (int)(metallicRoughnessTexture.opacity * 255), (int)(metallicRoughnessTexture.baseColor.r * 255), (int)(metallicRoughnessTexture.baseColor.g * 255), (int)(metallicRoughnessTexture.baseColor.b * 255) ); baseColorBitmap.SetPixel(x, y, colorBase); // The metalness values are sampled from the B channel. // The roughness values are sampled from the G channel. // These values are linear. If other channels are present (R or A), they are ignored for metallic-roughness calculations. Color colorMetallicRoughness = Color.FromArgb( 0, (int)(metallicRoughnessTexture.roughness * 255), (int)(metallicRoughnessTexture.metallic * 255) ); metallicRoughnessBitmap.SetPixel(x, y, colorMetallicRoughness); } } } } //export textures textureInfoBC = ExportBitmapTexture(gltf, babylonTexture, baseColorBitmap, babylonTexture.name); gltfPbrMetallicRoughness.baseColorTexture = textureInfoBC; // If no specular map is defined, the metallic and roughness values are be driven by the global parameters if (babylonStandardMaterial.specularTexture != null) { textureInfoMR = ExportBitmapTexture(gltf, babylonTexture, metallicRoughnessBitmap, babylonMaterial.name + "_metallicRoughness" + ".jpg"); gltfPbrMetallicRoughness.metallicRoughnessTexture = textureInfoMR; } //register the texture AddStandText(_key, textureInfoBC, textureInfoMR); } } else if (babylonMaterial.GetType() == typeof(BabylonPBRMetallicRoughnessMaterial)) { var babylonPBRMetallicRoughnessMaterial = babylonMaterial as BabylonPBRMetallicRoughnessMaterial; // --- prints --- #region prints RaiseVerbose("GLTFExporter.Material | babylonMaterial data", 2); RaiseVerbose("GLTFExporter.Material | babylonMaterial.alpha=" + babylonMaterial.alpha, 3); RaiseVerbose("GLTFExporter.Material | babylonMaterial.alphaMode=" + babylonMaterial.alphaMode, 3); RaiseVerbose("GLTFExporter.Material | babylonMaterial.backFaceCulling=" + babylonMaterial.backFaceCulling, 3); RaiseVerbose("GLTFExporter.Material | babylonMaterial.wireframe=" + babylonMaterial.wireframe, 3); // Global RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.maxSimultaneousLights=" + babylonPBRMetallicRoughnessMaterial.maxSimultaneousLights, 3); RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.disableLighting=" + babylonPBRMetallicRoughnessMaterial.disableLighting, 3); RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.alphaCutOff=" + babylonPBRMetallicRoughnessMaterial.alphaCutOff, 3); RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.transparencyMode=" + babylonPBRMetallicRoughnessMaterial.transparencyMode, 3); RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.doubleSided=" + babylonPBRMetallicRoughnessMaterial.doubleSided, 3); // Base color RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.baseColor.Length=" + babylonPBRMetallicRoughnessMaterial.baseColor.Length, 3); for (int i = 0; i < babylonPBRMetallicRoughnessMaterial.baseColor.Length; i++) { RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.baseColor[" + i + "]=" + babylonPBRMetallicRoughnessMaterial.baseColor[i], 3); } if (babylonPBRMetallicRoughnessMaterial.baseTexture == null) { RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.baseTexture=null", 3); } // Metallic+roughness RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.metallic=" + babylonPBRMetallicRoughnessMaterial.metallic, 3); RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.roughness=" + babylonPBRMetallicRoughnessMaterial.roughness, 3); if (babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture == null) { RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture=null", 3); } // Normal / bump if (babylonPBRMetallicRoughnessMaterial.normalTexture == null) { RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.normalTexture=null", 3); } RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.invertNormalMapX=" + babylonPBRMetallicRoughnessMaterial.invertNormalMapX, 3); RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.invertNormalMapY=" + babylonPBRMetallicRoughnessMaterial.invertNormalMapY, 3); // Emissive for (int i = 0; i < babylonPBRMetallicRoughnessMaterial.emissive.Length; i++) { RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.emissiveColor[" + i + "]=" + babylonPBRMetallicRoughnessMaterial.emissive[i], 3); } if (babylonPBRMetallicRoughnessMaterial.emissiveTexture == null) { RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.emissiveTexture=null", 3); } // Ambient occlusion RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.occlusionStrength=" + babylonPBRMetallicRoughnessMaterial.occlusionStrength, 3); if (babylonPBRMetallicRoughnessMaterial.occlusionTexture == null) { RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.occlusionTexture=null", 3); } #endregion // -------------------------------- // --------- gltfMaterial --------- // -------------------------------- RaiseMessage("GLTFExporter.Material | create gltfMaterial", 2); gltfMaterial = new GLTFMaterial { name = name }; gltfMaterial.id = babylonMaterial.id; gltfMaterial.index = gltf.MaterialsList.Count; gltf.MaterialsList.Add(gltfMaterial); // Alpha string alphaMode; float? alphaCutoff; getAlphaMode(babylonPBRMetallicRoughnessMaterial, out alphaMode, out alphaCutoff); gltfMaterial.alphaMode = alphaMode; gltfMaterial.alphaCutoff = alphaCutoff; // DoubleSided gltfMaterial.doubleSided = babylonPBRMetallicRoughnessMaterial.doubleSided; // Normal gltfMaterial.normalTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.normalTexture, gltf); // Occlusion if (babylonPBRMetallicRoughnessMaterial.occlusionTexture != null) { if (babylonPBRMetallicRoughnessMaterial.occlusionTexture.bitmap != null) { // ORM texture has been merged manually by the exporter // Occlusion is defined as well as metallic and/or roughness RaiseVerbose("Occlusion is defined as well as metallic and/or roughness", 2); gltfMaterial.occlusionTexture = ExportBitmapTexture(gltf, babylonPBRMetallicRoughnessMaterial.occlusionTexture); } else { // ORM texture was already merged or only occlusion is defined RaiseVerbose("ORM texture was already merged or only occlusion is defined", 2); gltfMaterial.occlusionTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.occlusionTexture, gltf); } } // Emissive gltfMaterial.emissiveFactor = babylonPBRMetallicRoughnessMaterial.emissive; gltfMaterial.emissiveTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.emissiveTexture, gltf); // -------------------------------- // --- gltfPbrMetallicRoughness --- // -------------------------------- RaiseMessage("GLTFExporter.Material | create gltfPbrMetallicRoughness", 2); var gltfPbrMetallicRoughness = new GLTFPBRMetallicRoughness(); gltfMaterial.pbrMetallicRoughness = gltfPbrMetallicRoughness; // --- Global --- // Base color gltfPbrMetallicRoughness.baseColorFactor = new float[4] { babylonPBRMetallicRoughnessMaterial.baseColor[0], babylonPBRMetallicRoughnessMaterial.baseColor[1], babylonPBRMetallicRoughnessMaterial.baseColor[2], babylonPBRMetallicRoughnessMaterial.alpha }; if (babylonPBRMetallicRoughnessMaterial.baseTexture != null) { if (babylonPBRMetallicRoughnessMaterial.baseTexture.bitmap != null) { gltfPbrMetallicRoughness.baseColorTexture = ExportBitmapTexture(gltf, babylonPBRMetallicRoughnessMaterial.baseTexture); } else { gltfPbrMetallicRoughness.baseColorTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.baseTexture, gltf); } } // Metallic roughness gltfPbrMetallicRoughness.metallicFactor = babylonPBRMetallicRoughnessMaterial.metallic; gltfPbrMetallicRoughness.roughnessFactor = babylonPBRMetallicRoughnessMaterial.roughness; if (babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture != null) { if (babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture == babylonPBRMetallicRoughnessMaterial.occlusionTexture) { // Occlusion is defined as well as metallic and/or roughness // Use same texture RaiseVerbose("Occlusion is defined as well as metallic and/or roughness", 2); gltfPbrMetallicRoughness.metallicRoughnessTexture = gltfMaterial.occlusionTexture; } else { // Occlusion is not defined, only metallic and/or roughness RaiseVerbose("Occlusion is not defined, only metallic and/or roughness", 2); if (babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture.bitmap != null) { // Metallic & roughness texture has been merged manually by the exporter // Write bitmap file RaiseVerbose("Metallic & roughness texture has been merged manually by the exporter", 2); gltfPbrMetallicRoughness.metallicRoughnessTexture = ExportBitmapTexture(gltf, babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture); } else { // Metallic & roughness texture was already merged // Copy file RaiseVerbose("Metallic & roughness texture was already merged", 2); gltfPbrMetallicRoughness.metallicRoughnessTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture, gltf); } } } } else { RaiseWarning("GLTFExporter.Material | Unsupported material type: " + babylonMaterial.GetType() + " | Max MaterialClass: " + babylonMaterial.maxGameMaterial.ClassName, 2); } if (gltfMaterial != null && babylonMaterial.isUnlit) { // Add Unlit extension if (!exportParameters.enableKHRMaterialsUnlit) { RaiseWarning("GLTFExporter.Material | KHR_materials_unlit has not been enabled for export!", 2); } else { if (gltfMaterial.extensions == null) { gltfMaterial.extensions = new GLTFExtensions(); } if (gltf.extensionsUsed == null) { gltf.extensionsUsed = new System.Collections.Generic.List<string>(); } if (!gltf.extensionsUsed.Contains("KHR_materials_unlit")) { gltf.extensionsUsed.Add("KHR_materials_unlit"); } gltfMaterial.extensions["KHR_materials_unlit"] = new object(); } } }
public static IINode FlattenHierarchy(this IINode node) { IILayer nodeLayer = LayerUtilities.GetNodeLayer(node); if (nodeLayer != null) { Loader.Core.LayerManager.SetCurrentLayer(nodeLayer.Name); } List <IINode> children = node.NodeTree().ToList(); List <IINode> nonMeshChildren = children.Where(x => !x.IsMesh()).ToList(); List <IINode> meshChildren = children.Where(x => x.IsMesh()).ToList(); IClass_ID cid = Loader.Global.Class_ID.Create((uint)BuiltInClassIDA.SPHERE_CLASS_ID, 0); object obj = Loader.Core.CreateInstance(SClass_ID.Geomobject, cid as IClass_ID); IINode result = Loader.Core.CreateObjectNode((IObject)obj); result.Name = node.Name; result.SetNodeTM(Loader.Core.Time, node.GetNodeTM(Loader.Core.Time, Forever)); node.ParentNode.AttachChild(result, true); string convertToEditablePoly = $"ConvertTo (maxOps.getNodeByHandle {result.Handle}) Editable_Poly"; ScriptsUtilities.ExecuteMaxScriptCommand(convertToEditablePoly); IPolyObject polyObject = result.GetPolyObjectFromNode(); IEPoly nodeEPoly = (IEPoly)polyObject.GetInterface(Loader.EditablePoly); List <IMtl> newMultiMat = new List <IMtl>(); foreach (IINode n in meshChildren) { ITriObject triObject = n.GetTriObjectFromNode(); IMesh mesh = triObject.Mesh; if (n.Mtl.IsMultiMtl) { Dictionary <IMtl, List <IFace> > matIDtoFacesMap = new Dictionary <IMtl, List <IFace> >(); ////List<int> matIDsInUse = new List<int>(); foreach (IFace face in mesh.Faces) { int faceMatID = face.MatID; IMtl mat = n.Mtl.GetSubMtl(faceMatID); if (!matIDtoFacesMap.ContainsKey(mat)) { List <IFace> facesOfMat = new List <IFace>(); matIDtoFacesMap.Add(mat, facesOfMat); } matIDtoFacesMap[mat].Add(face); } foreach (KeyValuePair <IMtl, List <IFace> > matToFaceKeyValue in matIDtoFacesMap) { IMtl faceMat = matToFaceKeyValue.Key; //get the material from the list of the multimaterial if (!newMultiMat.Contains(faceMat)) { newMultiMat.Add(faceMat); } ushort newId = (ushort)(newMultiMat.IndexOf(faceMat)); foreach (IFace face in matToFaceKeyValue.Value) { face.MatID = newId; } } } else { //IMtl currentMat = n.Mtl; //int matID = newMultiMat.IndexOf(currentMat); //if (matID == -1) //{ // newMultiMat.Add(currentMat); // ushort newId = (ushort)newMultiMat.Count; // for (int fID = 0; fID < mesh.NumFaces; fID++) // { // mesh.SetFaceMtlIndex(fID, (ushort)newId); // } //} //else //{ // for (int fID = 0; fID < mesh.NumFaces; fID++) // { // mesh.SetFaceMtlIndex(fID, (ushort)matID); // } //} } triObject.Mesh = mesh; n.ObjectRef = triObject; //bool undo = false; //nodeEPoly.EpfnAttach(n, ref undo,result, Loader.Core.Time); } IClass_ID matCid = Loader.Global.Class_ID.Create((uint)BuiltInClassIDA.MULTI_MATERIAL_CLASS_ID, 0); IMtl finalMat = (IMtl)Loader.Core.CreateInstance(SClass_ID.Material, matCid); for (int i = 0; i < newMultiMat.Count; i++) { finalMat.SetSubMtl(i, newMultiMat[i]); } finalMat.Name = "final mat"; result.Mtl = finalMat; foreach (IINode n in nonMeshChildren) { result.AttachChild(n, true); } Loader.Core.DeleteNode(node, false, false); return(result); }
public void LoadFromData(string propertyName, IINode dataNode, Dictionary <string, string> rootNodePropDictionary = null) { if (!Guid.TryParse(propertyName, out serializedId)) { throw new Exception("Invalid ID, can't deserialize."); } string propertiesString = string.Empty; if (rootNodePropDictionary == null) { if (!dataNode.GetUserPropString(propertyName, ref propertiesString)) { return; } } else { if (!rootNodePropDictionary.TryGetValue(propertyName, out propertiesString)) { return; } } int numFailed = 0; try // Try using the new way, if it's not working use the old way. { SerializableAnimationGroup serialAnimGroup = new SerializableAnimationGroup(propertiesString); serialAnimGroup.FillSerializedData(this); } catch { int indexOfguidPart = propertiesString .Select((c, i) => new { c, i }) .Where(x => x.c == s_PropertySeparator) .Skip(2) .FirstOrDefault().i; string[] baseProperties = propertiesString.Substring(0, indexOfguidPart)?.Split(s_PropertySeparator); string guidPart = propertiesString.Substring(indexOfguidPart + 1); if (baseProperties.Length != 3) { 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 = baseProperties[0]; if (!int.TryParse(baseProperties[1], out ticksStart)) { throw new Exception("Failed to parse FrameStart property."); } if (!int.TryParse(baseProperties[2], out ticksEnd)) { throw new Exception("Failed to parse FrameEnd property."); } if (string.IsNullOrEmpty(guidPart) || guidPart == s_GUIDTypeSeparator.ToString()) { return; } if (!guidPart.Contains(s_GUIDTypeSeparator)) { // to grant retro-compatiblity numFailed = ParseOldProperties(guidPart); } else { //new format with nodes and node materials guid numFailed = ParseNewProperties(guidPart); } } 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); } } AnimationGroupMaterials = new List <AnimationGroupMaterial>(); foreach (Guid materialGUID in materialsGuids) { IMtl mat = Tools.GetIMtlByGuid(materialGUID); if (mat != null) { string name = mat.Name; AnimationGroupMaterial matData = new AnimationGroupMaterial(materialGUID, name); AnimationGroupMaterials.Add(matData); } } 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); List <Guid> nodeGuids = new List <Guid>(); List <Guid> materialsGuids = new List <Guid>(); foreach (AnimationGroup animData in animationGroupsData) { nodeGuids.Clear(); 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)); } } if (animData.AnimationGroupMaterials != null) { string missingMaterials = ""; foreach (AnimationGroupMaterial matData in animData.AnimationGroupMaterials) { //check here if something changed between export\import // a material 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 IMtl mtl = Tools.GetIMtlByGuid(matData.Guid); if (mtl == null) { //material is missing missingMaterials += matData.Name + "\n"; continue; } materialsGuids.Add(mtl.GetGuid()); } if (!string.IsNullOrEmpty(missingMaterials)) { //skip restoration of evaluated animation group materialsGuids = new List <Guid>(); MessageBox.Show(string.Format("{0} does not exist,{1} import skipped", missingMaterials, animData.Name)); } } animData.NodeGuids = nodeGuids; animData.MaterialGuids = materialsGuids; string nodes = string.Join(AnimationGroup.s_PropertySeparator.ToString(), animData.NodeGuids); string materials = string.Join(AnimationGroup.s_PropertySeparator.ToString(), animData.MaterialGuids); string guids = string.Join(AnimationGroup.s_GUIDTypeSeparator.ToString(), nodes, materials); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendFormat(AnimationGroup.s_PropertyFormat, animData.Name, animData.TicksStart, animData.TicksEnd, guids); Loader.Core.RootNode.SetStringProperty(animData.SerializedId.ToString(), stringBuilder.ToString()); 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); }