static void DumpMultiMaterial(NovaMultiMaterial multiMaterial, BabylonScene babylonScene) { var babylonMultiMaterial = new BabylonMultiMaterial(); babylonScene.MultiMaterialsList.Add(babylonMultiMaterial); babylonMultiMaterial.name = multiMaterial.Name; babylonMultiMaterial.id = multiMaterial.ID.ToString(); babylonMultiMaterial.materials = multiMaterial.Materials.Select(material => (material != null ? material.ID.ToString() : "")).ToArray(); }
private void ExportMultiMaterial(string uuidMultiMaterial, List <MFnDependencyNode> materials, BabylonScene babylonScene, bool fullPBR) { var babylonMultimaterial = new BabylonMultiMaterial { id = uuidMultiMaterial }; // Name string nameConcatenated = ""; bool isFirstTime = true; List <MFnDependencyNode> materialsSorted = new List <MFnDependencyNode>(materials); materialsSorted.Sort(new MFnDependencyNodeComparer()); foreach (MFnDependencyNode material in materialsSorted) { if (!isFirstTime) { nameConcatenated += "_"; } isFirstTime = false; nameConcatenated += material.name; } babylonMultimaterial.name = nameConcatenated; // Materials var uuids = new List <string>(); foreach (MFnDependencyNode subMat in materials) { string uuidSubMat = subMat.uuid().asString(); uuids.Add(uuidSubMat); if (!referencedMaterials.Contains(subMat, new MFnDependencyNodeEqualityComparer())) { // Export sub material referencedMaterials.Add(subMat); ExportMaterial(subMat, babylonScene, fullPBR); } } babylonMultimaterial.materials = uuids.ToArray(); babylonScene.MultiMaterialsList.Add(babylonMultimaterial); }
private void ExportMaterial(IIGameMaterial materialNode, BabylonScene babylonScene) { var name = materialNode.MaterialName; var id = materialNode.MaxMaterial.GetGuid().ToString(); RaiseMessage(name, 1); // --- prints --- #region prints { RaiseVerbose("materialNode.MaterialClass=" + materialNode.MaterialClass, 2); RaiseVerbose("materialNode.NumberOfTextureMaps=" + materialNode.NumberOfTextureMaps, 2); var propertyContainer = materialNode.IPropertyContainer; RaiseVerbose("propertyContainer=" + propertyContainer, 2); if (propertyContainer != null) { RaiseVerbose("propertyContainer.NumberOfProperties=" + propertyContainer.NumberOfProperties, 3); for (int i = 0; i < propertyContainer.NumberOfProperties; i++) { var prop = propertyContainer.GetProperty(i); if (prop != null) { RaiseVerbose("propertyContainer.GetProperty(" + i + ")=" + prop.Name, 3); switch (prop.GetType_) { case PropType.StringProp: string propertyString = ""; RaiseVerbose("prop.GetPropertyValue(ref propertyString, 0)=" + prop.GetPropertyValue(ref propertyString, 0), 4); RaiseVerbose("propertyString=" + propertyString, 4); break; case PropType.IntProp: int propertyInt = 0; RaiseVerbose("prop.GetPropertyValue(ref propertyInt, 0)=" + prop.GetPropertyValue(ref propertyInt, 0), 4); RaiseVerbose("propertyInt=" + propertyInt, 4); break; case PropType.FloatProp: float propertyFloat = 0; RaiseVerbose("prop.GetPropertyValue(ref propertyFloat, 0)=" + prop.GetPropertyValue(ref propertyFloat, 0, true), 4); RaiseVerbose("propertyFloat=" + propertyFloat, 4); RaiseVerbose("prop.GetPropertyValue(ref propertyFloat, 0)=" + prop.GetPropertyValue(ref propertyFloat, 0, false), 4); RaiseVerbose("propertyFloat=" + propertyFloat, 4); break; case PropType.Point3Prop: IPoint3 propertyPoint3 = Loader.Global.Point3.Create(0, 0, 0); RaiseVerbose("prop.GetPropertyValue(ref propertyPoint3, 0)=" + prop.GetPropertyValue(propertyPoint3, 0), 4); RaiseVerbose("propertyPoint3=" + Point3ToString(propertyPoint3), 4); break; case PropType.Point4Prop: IPoint4 propertyPoint4 = Loader.Global.Point4.Create(0, 0, 0, 0); RaiseVerbose("prop.GetPropertyValue(ref propertyPoint4, 0)=" + prop.GetPropertyValue(propertyPoint4, 0), 4); RaiseVerbose("propertyPoint4=" + Point4ToString(propertyPoint4), 4); break; case PropType.UnknownProp: default: RaiseVerbose("Unknown property type", 4); break; } } else { RaiseVerbose("propertyContainer.GetProperty(" + i + ") IS NULL", 3); } } } } #endregion if (materialNode.SubMaterialCount > 0) { var babylonMultimaterial = new BabylonMultiMaterial { name = name, id = id }; var guids = new List <string>(); for (var index = 0; index < materialNode.SubMaterialCount; index++) { var subMat = materialNode.GetSubMaterial(index); if (subMat != null) { guids.Add(subMat.MaxMaterial.GetGuid().ToString()); if (!referencedMaterials.Contains(subMat)) { referencedMaterials.Add(subMat); ExportMaterial(subMat, babylonScene); } } else { guids.Add(Guid.Empty.ToString()); } } babylonMultimaterial.materials = guids.ToArray(); babylonScene.MultiMaterialsList.Add(babylonMultimaterial); return; } var stdMat = materialNode.MaxMaterial.GetParamBlock(0).Owner as IStdMat2; if (stdMat != null) { var isSelfIllumColor = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false); var babylonMaterial = new BabylonStandardMaterial { name = name, id = id, ambient = materialNode.MaxMaterial.GetAmbient(0, false).ToArray(), diffuse = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(), specular = materialNode.MaxMaterial.GetSpecular(0, false).Scale(materialNode.MaxMaterial.GetShinStr(0, false)), specularPower = materialNode.MaxMaterial.GetShininess(0, false) * 256, emissive = isSelfIllumColor ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray() : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)), // compute the pre-multiplied emissive color alpha = 1.0f - materialNode.MaxMaterial.GetXParency(0, false) }; // If Self-Illumination color checkbox is checked // Then self-illumination is assumed to be pre-multiplied // Otherwise self-illumination needs to be multiplied with diffuse // linkEmissiveWithDiffuse attribute tells the Babylon engine to perform such multiplication babylonMaterial.linkEmissiveWithDiffuse = !isSelfIllumColor; // useEmissiveAsIllumination attribute tells the Babylon engine to use pre-multiplied emissive as illumination babylonMaterial.useEmissiveAsIllumination = isSelfIllumColor; // Store the emissive value (before multiplication) for gltf babylonMaterial.selfIllum = materialNode.MaxMaterial.GetSelfIllum(0, false); babylonMaterial.backFaceCulling = !stdMat.TwoSided; babylonMaterial.wireframe = stdMat.Wire; // Textures BabylonFresnelParameters fresnelParameters; babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, out fresnelParameters, babylonScene); // Ambient babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, out fresnelParameters, babylonScene); // Diffuse if (fresnelParameters != null) { babylonMaterial.diffuseFresnelParameters = fresnelParameters; } babylonMaterial.specularTexture = ExportTexture(stdMat, 2, out fresnelParameters, babylonScene); // Specular babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, out fresnelParameters, babylonScene); // Emissive if (fresnelParameters != null) { babylonMaterial.emissiveFresnelParameters = fresnelParameters; if (babylonMaterial.emissive[0] == 0 && babylonMaterial.emissive[1] == 0 && babylonMaterial.emissive[2] == 0 && babylonMaterial.emissiveTexture == null) { babylonMaterial.emissive = new float[] { 1, 1, 1 }; } } babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, out fresnelParameters, babylonScene, false, true); // Opacity if (fresnelParameters != null) { babylonMaterial.opacityFresnelParameters = fresnelParameters; if (babylonMaterial.alpha == 1 && babylonMaterial.opacityTexture == null) { babylonMaterial.alpha = 0; } } babylonMaterial.bumpTexture = ExportTexture(stdMat, 8, out fresnelParameters, babylonScene); // Bump babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, out fresnelParameters, babylonScene, true); // Reflection if (fresnelParameters != null) { if (babylonMaterial.reflectionTexture == null) { RaiseWarning("Fallout cannot be used with reflection channel without a texture", 2); } else { babylonMaterial.reflectionFresnelParameters = fresnelParameters; } } // Constraints if (babylonMaterial.diffuseTexture != null) { babylonMaterial.diffuse = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new float[] { 0, 0, 0 }; } if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null && babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name && babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB) { // This is a alpha testing purpose babylonMaterial.opacityTexture = null; babylonMaterial.diffuseTexture.hasAlpha = true; RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", 2); RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", 2); } babylonScene.MaterialsList.Add(babylonMaterial); } // TODO - Find another way to detect if material is physical else if (materialNode.MaterialClass.ToLower() == "physical material" || // English materialNode.MaterialClass.ToLower() == "physisches material" || // German // TODO - check if translation is ok materialNode.MaterialClass.ToLower() == "matériau physique") // French { var propertyContainer = materialNode.IPropertyContainer; var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial { name = name, id = id }; // --- Global --- // Alpha //var alphaFromXParency = 1.0f - materialNode.MaxMaterial.GetXParency(0, false); var alphaFromPropertyContainer = 1.0f - propertyContainer.GetFloatProperty(17); //RaiseMessage("alphaFromXParency=" + alphaFromXParency, 2); //RaiseMessage("alphaFromPropertyContainer=" + alphaFromPropertyContainer, 2); babylonMaterial.alpha = alphaFromPropertyContainer; babylonMaterial.baseColor = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(); babylonMaterial.metallic = propertyContainer.GetFloatProperty(6); babylonMaterial.roughness = propertyContainer.GetFloatProperty(4); var invertRoughness = propertyContainer.GetBoolProperty(5); if (invertRoughness) { // Inverse roughness babylonMaterial.roughness = 1 - babylonMaterial.roughness; } // Self illumination is computed from emission color, luminance, temperature and weight babylonMaterial.emissive = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false) ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray() : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)); // --- Textures --- babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(materialNode, babylonMaterial.baseColor, babylonMaterial.alpha, babylonScene, name); babylonMaterial.metallicRoughnessTexture = ExportMetallicRoughnessTexture(materialNode, babylonMaterial.metallic, babylonMaterial.roughness, babylonScene, name, invertRoughness); var normalMapAmount = propertyContainer.GetFloatProperty(91); babylonMaterial.normalTexture = ExportPBRTexture(materialNode, 30, babylonScene, normalMapAmount); babylonMaterial.emissiveTexture = ExportPBRTexture(materialNode, 17, babylonScene); // Use diffuse roughness map as ambient occlusion babylonMaterial.occlusionTexture = ExportPBRTexture(materialNode, 6, babylonScene); // Constraints if (babylonMaterial.baseTexture != null) { babylonMaterial.baseColor = new[] { 1.0f, 1.0f, 1.0f }; babylonMaterial.alpha = 1.0f; } if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.metallicRoughnessTexture != null) { babylonMaterial.metallic = 1.0f; babylonMaterial.roughness = 1.0f; } babylonScene.MaterialsList.Add(babylonMaterial); } else { RaiseWarning("Unsupported material type: " + materialNode.MaterialClass, 2); } }
private void ConvertUnityMeshToBabylon(Mesh mesh, Transform transform, GameObject gameObject, float progress) { BabylonMesh babylonMesh = new BabylonMesh(); var renderer = gameObject.GetComponent <Renderer>(); ExporterWindow.ReportProgress(progress, "Exporting mesh: " + gameObject.name); babylonMesh.name = gameObject.name; babylonMesh.id = GetID(transform.gameObject); if (renderer != null) { babylonMesh.receiveShadows = renderer.receiveShadows; } babylonMesh.parentId = GetParentID(transform); babylonMesh.position = transform.localPosition.ToFloat(); babylonMesh.rotation = new float[3]; babylonMesh.rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180; babylonMesh.rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180; babylonMesh.rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180; babylonMesh.scaling = transform.localScale.ToFloat(); if (mesh != null) { babylonMesh.positions = new float[mesh.vertexCount * 3]; for (int i = 0; i < mesh.vertices.Length; i++) { babylonMesh.positions[i * 3] = mesh.vertices[i].x; babylonMesh.positions[(i * 3) + 1] = mesh.vertices[i].y; babylonMesh.positions[(i * 3) + 2] = mesh.vertices[i].z; // Computing world extends var worldPosition = transform.TransformPoint(mesh.vertices[i]); if (worldPosition.x > babylonScene.MaxVector.X) { babylonScene.MaxVector.X = worldPosition.x; } if (worldPosition.y > babylonScene.MaxVector.Y) { babylonScene.MaxVector.Y = worldPosition.y; } if (worldPosition.z > babylonScene.MaxVector.Z) { babylonScene.MaxVector.Z = worldPosition.z; } if (worldPosition.x < babylonScene.MinVector.X) { babylonScene.MinVector.X = worldPosition.x; } if (worldPosition.y < babylonScene.MinVector.Y) { babylonScene.MinVector.Y = worldPosition.y; } if (worldPosition.z < babylonScene.MinVector.Z) { babylonScene.MinVector.Z = worldPosition.z; } } babylonMesh.normals = new float[mesh.vertexCount * 3]; for (int i = 0; i < mesh.normals.Length; i++) { babylonMesh.normals[i * 3] = mesh.normals[i].x; babylonMesh.normals[(i * 3) + 1] = mesh.normals[i].y; babylonMesh.normals[(i * 3) + 2] = mesh.normals[i].z; } babylonMesh.uvs = new float[mesh.vertexCount * 2]; for (int i = 0; i < mesh.uv.Length; i++) { babylonMesh.uvs[i * 2] = mesh.uv[i].x; babylonMesh.uvs[(i * 2) + 1] = mesh.uv[i].y; } babylonMesh.uvs2 = new float[mesh.vertexCount * 2]; if (mesh.uv2 != null && mesh.uv2.Length > 0) { for (int i = 0; i < mesh.uv2.Length; i++) { babylonMesh.uvs2[i * 2] = mesh.uv2[i].x; babylonMesh.uvs2[(i * 2) + 1] = mesh.uv2[i].y; } } else { for (int i = 0; i < mesh.uv.Length; i++) { babylonMesh.uvs2[i * 2] = mesh.uv[i].x; babylonMesh.uvs2[(i * 2) + 1] = mesh.uv[i].y; } } babylonMesh.indices = new int[mesh.triangles.Length]; for (int i = 0; i < mesh.triangles.Length; i += 3) { babylonMesh.indices[i] = mesh.triangles[i + 2]; babylonMesh.indices[i + 1] = mesh.triangles[i + 1]; babylonMesh.indices[i + 2] = mesh.triangles[i]; } if (renderer != null && renderer.sharedMaterial != null) { if (mesh.subMeshCount > 1) // Multimaterials { BabylonMultiMaterial bMultiMat; if (!multiMatDictionary.ContainsKey(renderer.sharedMaterial.name)) { bMultiMat = new BabylonMultiMaterial { materials = new string[mesh.subMeshCount], id = Guid.NewGuid().ToString(), name = renderer.sharedMaterial.name }; for (int i = 0; i < renderer.sharedMaterials.Length; i++) { var sharedMaterial = renderer.sharedMaterials[i]; BabylonMaterial babylonMaterial; babylonMaterial = DumpMaterial(sharedMaterial, renderer); bMultiMat.materials[i] = babylonMaterial.id; } if (mesh.subMeshCount > 1) { multiMatDictionary.Add(bMultiMat.name, bMultiMat); } } else { bMultiMat = multiMatDictionary[renderer.sharedMaterial.name]; } babylonMesh.materialId = bMultiMat.id; babylonMesh.subMeshes = new BabylonSubMesh[mesh.subMeshCount]; var offset = 0; for (int materialIndex = 0; materialIndex < mesh.subMeshCount; materialIndex++) { var unityTriangles = mesh.GetTriangles(materialIndex); babylonMesh.subMeshes[materialIndex] = new BabylonSubMesh { verticesStart = 0, verticesCount = mesh.vertexCount, materialIndex = materialIndex, indexStart = offset, indexCount = unityTriangles.Length }; offset += unityTriangles.Length; } } else { babylonMesh.materialId = DumpMaterial(renderer.sharedMaterial, renderer).id; } } babylonScene.MeshesList.Add(babylonMesh); // Animations ExportAnimations(transform, babylonMesh); if (IsRotationQuaternionAnimated(babylonMesh)) { babylonMesh.rotationQuaternion = transform.localRotation.ToFloat(); } // Collisions if (exportationOptions.ExportCollisions) { var collider = gameObject.GetComponent <Collider>(); if (collider != null) { babylonMesh.checkCollisions = true; } } } }
private BabylonMesh ConvertUnityMeshToBabylon(Mesh mesh, Transform transform, GameObject gameObject, float progress, ref UnityMetaData metaData, ref List <BabylonExport.Entities.BabylonParticleSystem> particleSystems, ref List <UnityFlareSystem> lensFlares, ref string componentTags, BabylonMesh collisionMesh = null, Collider collider = null) { BabylonMesh babylonMesh = new BabylonMesh(); metaData.type = "Mesh"; if (!String.IsNullOrEmpty(componentTags)) { babylonMesh.tags = componentTags; } ExporterWindow.ReportProgress(progress, "Exporting mesh: " + gameObject.name); babylonMesh.name = gameObject.name; babylonMesh.id = GetID(transform.gameObject); var renderer = gameObject.GetComponent <Renderer>(); if (renderer != null) { babylonMesh.receiveShadows = renderer.receiveShadows; } babylonMesh.parentId = GetParentID(transform); babylonMesh.position = transform.localPosition.ToFloat(); babylonMesh.rotation = new float[3]; babylonMesh.rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180; babylonMesh.rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180; babylonMesh.rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180; babylonMesh.scaling = transform.localScale.ToFloat(); babylonMesh.checkCollisions = false; // Collision mesh (With detail mesh fallback) string collisionMeshId = null; if (collider != null) { if (collisionMesh != null) { collisionMeshId = collisionMesh.id; collisionMesh.parentId = babylonMesh.id; collisionMesh.visibility = collider.isTrigger ? 0.25f : 0.5f; collisionMesh.checkCollisions = (exportationOptions.ExportCollisions && collider.isTrigger == false); } else { babylonMesh.checkCollisions = exportationOptions.ExportCollisions; } } metaData.properties["collisionMeshId"] = collisionMeshId; if (mesh != null) { Tools.GenerateBabylonMeshData(mesh, babylonMesh, babylonScene, transform); int index = 0; if (mesh.boneWeights.Length == mesh.vertexCount) { babylonMesh.matricesIndices = new int[mesh.vertexCount]; babylonMesh.matricesWeights = new float[mesh.vertexCount * 4]; index = 0; foreach (BoneWeight bw in mesh.boneWeights) { babylonMesh.matricesIndices[index] = (bw.boneIndex3 << 24) | (bw.boneIndex2 << 16) | (bw.boneIndex1 << 8) | bw.boneIndex0; babylonMesh.matricesWeights[index * 4 + 0] = bw.weight0; babylonMesh.matricesWeights[index * 4 + 1] = bw.weight1; babylonMesh.matricesWeights[index * 4 + 2] = bw.weight2; babylonMesh.matricesWeights[index * 4 + 3] = bw.weight3; var totalWeight = bw.weight0 + bw.weight1 + bw.weight2 + bw.weight3; if (Mathf.Abs(totalWeight - 1.0f) > 0.01f) { throw new Exception("Total bone weights is not normalized for: " + mesh); } index++; } } index = 0; if (renderer != null && renderer.sharedMaterial != null) { // Validate Multi Materials if (mesh.subMeshCount > 1) { BabylonMultiMaterial bMultiMat; string multiMatName = ""; for (int i = 0; i < renderer.sharedMaterials.Length; i++) { multiMatName += renderer.sharedMaterials[i].name; } if (!multiMatDictionary.ContainsKey(multiMatName)) { bMultiMat = new BabylonMultiMaterial { materials = new string[mesh.subMeshCount], id = Guid.NewGuid().ToString(), name = multiMatName }; for (int i = 0; i < renderer.sharedMaterials.Length; i++) { var sharedMaterial = renderer.sharedMaterials[i]; BabylonMaterial babylonMaterial; babylonMaterial = DumpMaterial(sharedMaterial, renderer.lightmapIndex, renderer.lightmapScaleOffset); bMultiMat.materials[i] = babylonMaterial.id; } if (mesh.subMeshCount > 1) { multiMatDictionary.Add(bMultiMat.name, bMultiMat); } } else { bMultiMat = multiMatDictionary[multiMatName]; } babylonMesh.materialId = bMultiMat.id; babylonMesh.subMeshes = new BabylonSubMesh[mesh.subMeshCount]; var offset = 0; for (int materialIndex = 0; materialIndex < mesh.subMeshCount; materialIndex++) { var unityTriangles = mesh.GetTriangles(materialIndex); babylonMesh.subMeshes[materialIndex] = new BabylonSubMesh { verticesStart = 0, verticesCount = mesh.vertexCount, materialIndex = materialIndex, indexStart = offset, indexCount = unityTriangles.Length }; offset += unityTriangles.Length; } } else { babylonMesh.materialId = DumpMaterial(renderer.sharedMaterial, renderer.lightmapIndex, renderer.lightmapScaleOffset).id; } } babylonMesh.metadata = metaData; babylonScene.MeshesList.Add(babylonMesh); // Animations ExportAnimations(transform, babylonMesh); if (IsRotationQuaternionAnimated(babylonMesh)) { babylonMesh.rotationQuaternion = transform.localRotation.ToFloat(); } // Lens Flares ParseLensFlares(gameObject, babylonMesh.id, ref lensFlares); // Particles Systems ParseParticleSystems(gameObject, babylonMesh.id, ref particleSystems); // Babylon Physics if (exportationOptions.ExportPhysics) { var physics = gameObject.GetComponent <BabylonPhysicsState>(); if (physics != null) { babylonMesh.physicsMass = physics.mass; babylonMesh.physicsFriction = physics.friction; babylonMesh.physicsRestitution = physics.restitution; babylonMesh.physicsImpostor = (int)physics.imposter; } } } return(babylonMesh); }
private void ExportMaterial(IIGameMaterial materialNode, BabylonScene babylonScene) { var name = materialNode.MaterialName; var id = materialNode.MaxMaterial.GetGuid().ToString(); // Check if the material was already exported. The material id is unique. if (babylonScene.MaterialsList.FirstOrDefault(m => m.id == id) != null) { return; } RaiseMessage(name, 1); // --- prints --- #region prints { RaiseVerbose("materialNode.MaterialClass=" + materialNode.MaterialClass, 2); RaiseVerbose("materialNode.NumberOfTextureMaps=" + materialNode.NumberOfTextureMaps, 2); var propertyContainer = materialNode.IPropertyContainer; RaiseVerbose("propertyContainer=" + propertyContainer, 2); if (propertyContainer != null) { RaiseVerbose("propertyContainer.NumberOfProperties=" + propertyContainer.NumberOfProperties, 3); for (int i = 0; i < propertyContainer.NumberOfProperties; i++) { var prop = propertyContainer.GetProperty(i); if (prop != null) { RaiseVerbose("propertyContainer.GetProperty(" + i + ")=" + prop.Name, 3); switch (prop.GetType_) { case PropType.StringProp: string propertyString = ""; RaiseVerbose("prop.GetPropertyValue(ref propertyString, 0)=" + prop.GetPropertyValue(ref propertyString, 0), 4); RaiseVerbose("propertyString=" + propertyString, 4); break; case PropType.IntProp: int propertyInt = 0; RaiseVerbose("prop.GetPropertyValue(ref propertyInt, 0)=" + prop.GetPropertyValue(ref propertyInt, 0), 4); RaiseVerbose("propertyInt=" + propertyInt, 4); break; case PropType.FloatProp: float propertyFloat = 0; RaiseVerbose("prop.GetPropertyValue(ref propertyFloat, 0, true)=" + prop.GetPropertyValue(ref propertyFloat, 0, true), 4); RaiseVerbose("propertyFloat=" + propertyFloat, 4); RaiseVerbose("prop.GetPropertyValue(ref propertyFloat, 0, false)=" + prop.GetPropertyValue(ref propertyFloat, 0, false), 4); RaiseVerbose("propertyFloat=" + propertyFloat, 4); break; case PropType.Point3Prop: IPoint3 propertyPoint3 = Loader.Global.Point3.Create(0, 0, 0); RaiseVerbose("prop.GetPropertyValue(ref propertyPoint3, 0)=" + prop.GetPropertyValue(propertyPoint3, 0), 4); RaiseVerbose("propertyPoint3=" + Point3ToString(propertyPoint3), 4); break; case PropType.Point4Prop: IPoint4 propertyPoint4 = Loader.Global.Point4.Create(0, 0, 0, 0); RaiseVerbose("prop.GetPropertyValue(ref propertyPoint4, 0)=" + prop.GetPropertyValue(propertyPoint4, 0), 4); RaiseVerbose("propertyPoint4=" + Point4ToString(propertyPoint4), 4); break; case PropType.UnknownProp: default: RaiseVerbose("Unknown property type", 4); break; } } else { RaiseVerbose("propertyContainer.GetProperty(" + i + ") IS NULL", 3); } } } } #endregion if (materialNode.SubMaterialCount > 0) { var babylonMultimaterial = new BabylonMultiMaterial { name = name, id = id }; var guids = new List <string>(); for (var index = 0; index < materialNode.SubMaterialCount; index++) { var subMat = materialNode.GetSubMaterial(index); if (subMat != null) { guids.Add(subMat.MaxMaterial.GetGuid().ToString()); if (!referencedMaterials.Contains(subMat)) { referencedMaterials.Add(subMat); ExportMaterial(subMat, babylonScene); } } else { guids.Add(Guid.Empty.ToString()); } } babylonMultimaterial.materials = guids.ToArray(); babylonScene.MultiMaterialsList.Add(babylonMultimaterial); return; } var unlitProperty = materialNode.IPropertyContainer.QueryProperty("BabylonUnlit"); bool isUnlit = unlitProperty != null?unlitProperty.GetBoolValue() : false; var stdMat = materialNode.MaxMaterial.NumParamBlocks > 0 ? materialNode.MaxMaterial.GetParamBlock(0).Owner as IStdMat2 : null; if (stdMat != null) { var babylonMaterial = new BabylonStandardMaterial { name = name, id = id, isUnlit = isUnlit, diffuse = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(), alpha = 1.0f - materialNode.MaxMaterial.GetXParency(0, false) }; babylonMaterial.backFaceCulling = !stdMat.TwoSided; babylonMaterial.wireframe = stdMat.Wire; var isSelfIllumColor = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false); var maxSpecularColor = materialNode.MaxMaterial.GetSpecular(0, false).ToArray(); if (isUnlit == false) { babylonMaterial.ambient = materialNode.MaxMaterial.GetAmbient(0, false).ToArray(); babylonMaterial.specular = maxSpecularColor.Multiply(materialNode.MaxMaterial.GetShinStr(0, false)); babylonMaterial.specularPower = materialNode.MaxMaterial.GetShininess(0, false) * 256; babylonMaterial.emissive = isSelfIllumColor ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray() : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)); // compute the pre-multiplied emissive color // If Self-Illumination color checkbox is checked // Then self-illumination is assumed to be pre-multiplied // Otherwise self-illumination needs to be multiplied with diffuse // linkEmissiveWithDiffuse attribute tells the Babylon engine to perform such multiplication babylonMaterial.linkEmissiveWithDiffuse = !isSelfIllumColor; // useEmissiveAsIllumination attribute tells the Babylon engine to use pre-multiplied emissive as illumination babylonMaterial.useEmissiveAsIllumination = isSelfIllumColor; // Store the emissive value (before multiplication) for gltf babylonMaterial.selfIllum = materialNode.MaxMaterial.GetSelfIllum(0, false); } // Textures BabylonFresnelParameters fresnelParameters; babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, out fresnelParameters, babylonScene); // Diffuse if (fresnelParameters != null) { babylonMaterial.diffuseFresnelParameters = fresnelParameters; } if ((babylonMaterial.alpha == 1.0f && babylonMaterial.opacityTexture == null) && babylonMaterial.diffuseTexture != null && (babylonMaterial.diffuseTexture.originalPath.EndsWith(".tif") || babylonMaterial.diffuseTexture.originalPath.EndsWith(".tiff")) && babylonMaterial.diffuseTexture.hasAlpha) { RaiseWarning($"Diffuse texture named {babylonMaterial.diffuseTexture.originalPath} is a .tif file and its Alpha Source is 'Image Alpha' by default.", 2); RaiseWarning($"If you don't want material to be in BLEND mode, set diffuse texture Alpha Source to 'None (Opaque)'", 2); } babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, out fresnelParameters, babylonScene, false, true); // Opacity if (fresnelParameters != null) { babylonMaterial.opacityFresnelParameters = fresnelParameters; if (babylonMaterial.alpha == 1 && babylonMaterial.opacityTexture == null) { babylonMaterial.alpha = 0; } } if (isUnlit == false) { babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, out fresnelParameters, babylonScene); // Ambient babylonMaterial.specularTexture = ExportSpecularTexture(materialNode, maxSpecularColor, babylonScene); babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, out fresnelParameters, babylonScene); // Emissive if (fresnelParameters != null) { babylonMaterial.emissiveFresnelParameters = fresnelParameters; if (babylonMaterial.emissive[0] == 0 && babylonMaterial.emissive[1] == 0 && babylonMaterial.emissive[2] == 0 && babylonMaterial.emissiveTexture == null) { babylonMaterial.emissive = new float[] { 1, 1, 1 }; } } babylonMaterial.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); } else if (isPhysicalMaterial(materialNode)) { var propertyContainer = materialNode.IPropertyContainer; var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial { name = name, id = id, isUnlit = isUnlit }; // --- Global --- // Alpha //var alphaFromXParency = 1.0f - materialNode.MaxMaterial.GetXParency(0, false); var alphaFromPropertyContainer = 1.0f - propertyContainer.GetFloatProperty(17); //RaiseMessage("alphaFromXParency=" + alphaFromXParency, 2); //RaiseMessage("alphaFromPropertyContainer=" + alphaFromPropertyContainer, 2); babylonMaterial.alpha = alphaFromPropertyContainer; babylonMaterial.baseColor = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(); var invertRoughness = propertyContainer.GetBoolProperty(5); if (isUnlit == false) { babylonMaterial.metallic = propertyContainer.GetFloatProperty(6); babylonMaterial.roughness = propertyContainer.GetFloatProperty(4); if (invertRoughness) { // Inverse roughness babylonMaterial.roughness = 1 - babylonMaterial.roughness; } // Self illumination is computed from emission color, luminance, temperature and weight babylonMaterial.emissive = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false) ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray() : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)); } else { // Ignore specified roughness and metallic values babylonMaterial.metallic = 0; babylonMaterial.roughness = 0.9f; } // --- Textures --- // 1 - base color ; 9 - transparancy weight ITexmap colorTexmap = _getTexMap(materialNode, 1); ITexmap alphaTexmap = _getTexMap(materialNode, 9); babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(colorTexmap, alphaTexmap, babylonMaterial.baseColor, babylonMaterial.alpha, babylonScene, name); if (isUnlit == false) { // Metallic, roughness, ambient occlusion ITexmap metallicTexmap = _getTexMap(materialNode, 5); ITexmap roughnessTexmap = _getTexMap(materialNode, 4); ITexmap ambientOcclusionTexmap = _getTexMap(materialNode, 6); // Use diffuse roughness map as ambient occlusion // Check if MR or ORM textures are already merged bool areTexturesAlreadyMerged = false; if (metallicTexmap != null && roughnessTexmap != null) { string sourcePathMetallic = getSourcePath(metallicTexmap); string sourcePathRoughness = getSourcePath(roughnessTexmap); if (sourcePathMetallic == sourcePathRoughness) { if (ambientOcclusionTexmap != null && exportParameters.mergeAOwithMR) { string sourcePathAmbientOcclusion = getSourcePath(ambientOcclusionTexmap); if (sourcePathMetallic == sourcePathAmbientOcclusion) { // Metallic, roughness and ambient occlusion are already merged RaiseVerbose("Metallic, roughness and ambient occlusion are already merged", 2); BabylonTexture ormTexture = ExportTexture(metallicTexmap, babylonScene); babylonMaterial.metallicRoughnessTexture = ormTexture; babylonMaterial.occlusionTexture = ormTexture; areTexturesAlreadyMerged = true; } } else { // Metallic and roughness are already merged RaiseVerbose("Metallic and roughness are already merged", 2); BabylonTexture ormTexture = ExportTexture(metallicTexmap, babylonScene); babylonMaterial.metallicRoughnessTexture = ormTexture; areTexturesAlreadyMerged = true; } } } if (areTexturesAlreadyMerged == false) { if (metallicTexmap != null || roughnessTexmap != null) { // Merge metallic, roughness and ambient occlusion RaiseVerbose("Merge metallic and roughness (and ambient occlusion if `mergeAOwithMR` is enabled)", 2); BabylonTexture ormTexture = ExportORMTexture(exportParameters.mergeAOwithMR ? ambientOcclusionTexmap : null, roughnessTexmap, metallicTexmap, babylonMaterial.metallic, babylonMaterial.roughness, babylonScene, invertRoughness); babylonMaterial.metallicRoughnessTexture = ormTexture; if (ambientOcclusionTexmap != null) { if (exportParameters.mergeAOwithMR) { babylonMaterial.occlusionTexture = ormTexture; } else { babylonMaterial.occlusionTexture = ExportPBRTexture(materialNode, 6, babylonScene); } } } else if (ambientOcclusionTexmap != null) { // Simply export occlusion texture RaiseVerbose("Simply export occlusion texture", 2); babylonMaterial.occlusionTexture = ExportTexture(ambientOcclusionTexmap, babylonScene); } } if (ambientOcclusionTexmap != null && !exportParameters.mergeAOwithMR && babylonMaterial.occlusionTexture == null) { RaiseVerbose("Exporting occlusion texture without merging with metallic roughness", 2); babylonMaterial.occlusionTexture = ExportTexture(ambientOcclusionTexmap, babylonScene); } var normalMapAmount = propertyContainer.GetFloatProperty(91); babylonMaterial.normalTexture = ExportPBRTexture(materialNode, 30, babylonScene, normalMapAmount); babylonMaterial.emissiveTexture = ExportPBRTexture(materialNode, 17, babylonScene); } if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { var alphaTestProperty = materialNode.IPropertyContainer.QueryProperty("BabylonAlphaTest"); bool isAlphaTest = alphaTestProperty != null?alphaTestProperty.GetBoolValue() : false; babylonMaterial.transparencyMode = isAlphaTest ? (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHATEST : (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.metallicRoughnessTexture != null) { babylonMaterial.metallic = 1.0f; babylonMaterial.roughness = 1.0f; } babylonScene.MaterialsList.Add(babylonMaterial); } else if (isArnoldMaterial(materialNode)) { var propertyContainer = materialNode.IPropertyContainer; var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial { name = name, id = id, isUnlit = isUnlit }; // Alpha babylonMaterial.alpha = 1.0f - propertyContainer.GetFloatProperty(32); // Color: base * weight float[] baseColor = propertyContainer.GetPoint3Property(5).ToArray(); float baseWeight = propertyContainer.GetFloatProperty(2); babylonMaterial.baseColor = baseColor.Multiply(baseWeight); // Metallic & roughness bool invertRoughness = false; babylonMaterial.roughness = propertyContainer.GetFloatProperty(17); // specular_roughness babylonMaterial.metallic = propertyContainer.GetFloatProperty(29); // Emissive: emission_color * emission float[] emissionColor = propertyContainer.GetPoint3Property(94).ToArray(); float emissionWeight = propertyContainer.GetFloatProperty(91); babylonMaterial.emissive = emissionColor.Multiply(emissionWeight); // --- Textures --- // 1 - base_color ; 5 - diffuse_roughness ; 9 - metalness ; 10 - transparent ITexmap colorTexmap = _getTexMap(materialNode, 1); ITexmap alphaTexmap = _getTexMap(materialNode, 10); babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(colorTexmap, alphaTexmap, babylonMaterial.baseColor, babylonMaterial.alpha, babylonScene, name); if (isUnlit == false) { // Metallic, roughness ITexmap metallicTexmap = _getTexMap(materialNode, 9); ITexmap roughnessTexmap = _getTexMap(materialNode, 5); // Check if MR textures are already merged bool areTexturesAlreadyMerged = false; if (metallicTexmap != null && roughnessTexmap != null) { string sourcePathMetallic = getSourcePath(metallicTexmap); string sourcePathRoughness = getSourcePath(roughnessTexmap); if (sourcePathMetallic == sourcePathRoughness) { // Metallic and roughness are already merged RaiseVerbose("Metallic and roughness are already merged", 2); BabylonTexture ormTexture = ExportTexture(metallicTexmap, babylonScene); babylonMaterial.metallicRoughnessTexture = ormTexture; // The already merged map is assumed to contain Ambient Occlusion in R channel babylonMaterial.occlusionTexture = ormTexture; areTexturesAlreadyMerged = true; } } if (areTexturesAlreadyMerged == false) { if (metallicTexmap != null || roughnessTexmap != null) { // Merge metallic, roughness RaiseVerbose("Merge metallic and roughness", 2); BabylonTexture ormTexture = ExportORMTexture(null, roughnessTexmap, metallicTexmap, babylonMaterial.metallic, babylonMaterial.roughness, babylonScene, invertRoughness); babylonMaterial.metallicRoughnessTexture = ormTexture; } } babylonMaterial.normalTexture = ExportPBRTexture(materialNode, 20, babylonScene); babylonMaterial.emissiveTexture = ExportPBRTexture(materialNode, 30, babylonScene); } // Constraints if (babylonMaterial.baseTexture != null) { babylonMaterial.baseColor = new[] { 1.0f, 1.0f, 1.0f }; babylonMaterial.alpha = 1.0f; } if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.metallicRoughnessTexture != null) { babylonMaterial.metallic = 1.0f; babylonMaterial.roughness = 1.0f; } // Add the material to the scene babylonScene.MaterialsList.Add(babylonMaterial); } else { // isMaterialExportable check should prevent this to happen RaiseError("Unsupported material type: " + materialNode.MaterialClass, 2); } }
private void UpdateMeshesMaterialId(BabylonScene babylonScene) { // --- Update meshes using simple materials --- foreach (MFnDependencyNode material in referencedMaterials) { string materialId = material.uuid().asString(); // If it's an AiStandardSurface material if (materialDuplicationDatas.ContainsKey(materialId)) { MaterialDuplicationData materialDuplicationValue = materialDuplicationDatas[materialId]; // If both Opaque and Transparent meshes are using this material // And the material contains alpha data if (materialDuplicationValue.idOpaque != null && materialDuplicationValue.isDuplicationSuccess) { // The duplicated material is used for Opaque meshes instead of the original one foreach (BabylonMesh meshOpaque in materialDuplicationValue.meshesOpaque) { meshOpaque.materialId = materialDuplicationValue.idOpaque; } } } } // --- Update meshes using multimaterials --- var multiMaterialsList = new List <BabylonMultiMaterial>(babylonScene.MultiMaterialsList); foreach (BabylonMultiMaterial babylonMultiMaterial in multiMaterialsList) { string multiMaterialId = babylonMultiMaterial.id; // If at least one Opaque mesh is using this multimaterial if (meshesOpaqueMultis[multiMaterialId].Count > 0) { List <MFnDependencyNode> subMaterials = multiMaterials[multiMaterialId]; // Build a list of all opaque sub material ids List <string> opaqueSubMaterials = new List <string>(); foreach (MFnDependencyNode subMaterial in subMaterials) { string subMaterialId = subMaterial.uuid().asString(); // If it's an AiStandardSurface material if (materialDuplicationDatas.ContainsKey(subMaterialId)) { MaterialDuplicationData materialDuplicationValue = materialDuplicationDatas[subMaterialId]; // If both Opaque and Transparent meshes are using this sub material // And the sub material contains alpha data if (materialDuplicationValue.idOpaque != null && materialDuplicationValue.isDuplicationSuccess) { // The duplicated material is used for Opaque meshes instead of the original one subMaterialId = materialDuplicationValue.idOpaque; } } opaqueSubMaterials.Add(subMaterialId); } // If both Opaque and Transparent meshes are using this multimaterial if (meshesTransparentMultis[multiMaterialId].Count > 0) { // Duplicate multimaterial BabylonMultiMaterial multiMaterialCloned = new BabylonMultiMaterial(babylonMultiMaterial); // Update id string idMultiMaterialCloned = Tools.GenerateUUID(); multiMaterialCloned.id = idMultiMaterialCloned; // Update sub materials multiMaterialCloned.materials = opaqueSubMaterials.ToArray(); // Store duplication babylonScene.MultiMaterialsList.Add(multiMaterialCloned); // Update meshes id foreach (BabylonMesh meshOpaque in meshesOpaqueMultis[multiMaterialId]) { meshOpaque.materialId = idMultiMaterialCloned; } } else { // Only Opaque meshes are using this multimaterial // Simply override sub materials with all opaque ones babylonMultiMaterial.materials = opaqueSubMaterials.ToArray(); } } } }
private void ExportMaterial(IIGameMaterial materialNode, BabylonScene babylonScene) { var name = materialNode.MaterialName; var id = materialNode.MaxMaterial.GetGuid().ToString(); RaiseMessage(name, 1); if (materialNode.SubMaterialCount > 0) { var babylonMultimaterial = new BabylonMultiMaterial { name = name, id = id }; var guids = new List <string>(); for (var index = 0; index < materialNode.SubMaterialCount; index++) { var subMat = materialNode.GetSubMaterial(index); if (subMat != null) { guids.Add(subMat.MaxMaterial.GetGuid().ToString()); if (!referencedMaterials.Contains(subMat)) { referencedMaterials.Add(subMat); ExportMaterial(subMat, babylonScene); } } else { guids.Add(Guid.Empty.ToString()); } } babylonMultimaterial.materials = guids.ToArray(); babylonScene.MultiMaterialsList.Add(babylonMultimaterial); return; } var babylonMaterial = new BabylonStandardMaterial { name = name, id = id, ambient = materialNode.MaxMaterial.GetAmbient(0, false).ToArray(), diffuse = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(), specular = materialNode.MaxMaterial.GetSpecular(0, false).Scale(materialNode.MaxMaterial.GetShinStr(0, false)), specularPower = materialNode.MaxMaterial.GetShininess(0, false) * 256, emissive = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false) ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray() : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)), alpha = 1.0f - materialNode.MaxMaterial.GetXParency(0, false) }; var stdMat = materialNode.MaxMaterial.GetParamBlock(0).Owner as IStdMat2; if (stdMat != null) { babylonMaterial.backFaceCulling = !stdMat.TwoSided; babylonMaterial.wireframe = stdMat.Wire; // Textures BabylonFresnelParameters fresnelParameters; babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, out fresnelParameters, babylonScene); // Ambient babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, out fresnelParameters, babylonScene); // Diffuse if (fresnelParameters != null) { babylonMaterial.diffuseFresnelParameters = fresnelParameters; } babylonMaterial.specularTexture = ExportTexture(stdMat, 2, out fresnelParameters, babylonScene); // Specular babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, out fresnelParameters, babylonScene); // Emissive if (fresnelParameters != null) { babylonMaterial.emissiveFresnelParameters = fresnelParameters; if (babylonMaterial.emissive[0] == 0 && babylonMaterial.emissive[1] == 0 && babylonMaterial.emissive[2] == 0 && babylonMaterial.emissiveTexture == null) { babylonMaterial.emissive = new float[] { 1, 1, 1 }; } } babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, out fresnelParameters, babylonScene, false, true); // Opacity if (fresnelParameters != null) { babylonMaterial.opacityFresnelParameters = fresnelParameters; if (babylonMaterial.alpha == 1 && babylonMaterial.opacityTexture == null) { babylonMaterial.alpha = 0; } } babylonMaterial.bumpTexture = ExportTexture(stdMat, 8, out fresnelParameters, babylonScene); // Bump babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, out fresnelParameters, babylonScene, true); // Reflection if (fresnelParameters != null) { if (babylonMaterial.reflectionTexture == null) { RaiseWarning("Fallout cannot be used with reflection channel without a texture", 2); } else { babylonMaterial.reflectionFresnelParameters = fresnelParameters; } } // Constraints if (babylonMaterial.diffuseTexture != null) { babylonMaterial.diffuse = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new float[] { 0, 0, 0 }; } if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null && babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name && babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB) { // This is a alpha testing purpose babylonMaterial.opacityTexture = null; babylonMaterial.diffuseTexture.hasAlpha = true; RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", 2); RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", 2); } } babylonScene.MaterialsList.Add(babylonMaterial); }
private void ExportMaterial(IIGameMaterial materialNode, BabylonScene babylonScene) { var name = materialNode.MaterialName; var id = materialNode.MaxMaterial.GetGuid().ToString(); RaiseMessage(name, 1); // --- prints --- { RaiseMessage("materialNode.MaterialClass=" + materialNode.MaterialClass, 2); RaiseMessage("materialNode.NumberOfTextureMaps=" + materialNode.NumberOfTextureMaps, 2); var propertyContainer = materialNode.IPropertyContainer; RaiseMessage("propertyContainer=" + propertyContainer, 2); if (propertyContainer != null) { RaiseMessage("propertyContainer.NumberOfProperties=" + propertyContainer.NumberOfProperties, 3); for (int i = 0; i < propertyContainer.NumberOfProperties; i++) { var prop = propertyContainer.GetProperty(i); if (prop != null) { RaiseMessage("propertyContainer.GetProperty(" + i + ")=" + prop.Name, 3); switch (prop.GetType_) { case PropType.StringProp: string propertyString = ""; RaiseMessage("prop.GetPropertyValue(ref propertyString, 0)=" + prop.GetPropertyValue(ref propertyString, 0), 4); RaiseMessage("propertyString=" + propertyString, 4); break; case PropType.IntProp: int propertyInt = 0; RaiseMessage("prop.GetPropertyValue(ref propertyInt, 0)=" + prop.GetPropertyValue(ref propertyInt, 0), 4); RaiseMessage("propertyInt=" + propertyInt, 4); break; case PropType.FloatProp: float propertyFloat = 0; RaiseMessage("prop.GetPropertyValue(ref propertyFloat, 0)=" + prop.GetPropertyValue(ref propertyFloat, 0, true), 4); RaiseMessage("propertyFloat=" + propertyFloat, 4); RaiseMessage("prop.GetPropertyValue(ref propertyFloat, 0)=" + prop.GetPropertyValue(ref propertyFloat, 0, false), 4); RaiseMessage("propertyFloat=" + propertyFloat, 4); break; case PropType.Point3Prop: IPoint3 propertyPoint3 = Loader.Global.Point3.Create(0, 0, 0); RaiseMessage("prop.GetPropertyValue(ref propertyPoint3, 0)=" + prop.GetPropertyValue(propertyPoint3, 0), 4); RaiseMessage("propertyPoint3=" + Point3ToString(propertyPoint3), 4); break; case PropType.Point4Prop: IPoint4 propertyPoint4 = Loader.Global.Point4.Create(0, 0, 0, 0); RaiseMessage("prop.GetPropertyValue(ref propertyPoint4, 0)=" + prop.GetPropertyValue(propertyPoint4, 0), 4); RaiseMessage("propertyPoint4=" + Point4ToString(propertyPoint4), 4); break; case PropType.UnknownProp: default: RaiseMessage("Unknown property type", 4); break; } } else { RaiseMessage("propertyContainer.GetProperty(" + i + ") IS NULL", 3); } } } } if (materialNode.SubMaterialCount > 0) { var babylonMultimaterial = new BabylonMultiMaterial { name = name, id = id }; var guids = new List <string>(); for (var index = 0; index < materialNode.SubMaterialCount; index++) { var subMat = materialNode.GetSubMaterial(index); if (subMat != null) { guids.Add(subMat.MaxMaterial.GetGuid().ToString()); if (!referencedMaterials.Contains(subMat)) { referencedMaterials.Add(subMat); ExportMaterial(subMat, babylonScene); } } else { guids.Add(Guid.Empty.ToString()); } } babylonMultimaterial.materials = guids.ToArray(); babylonScene.MultiMaterialsList.Add(babylonMultimaterial); return; } var stdMat = materialNode.MaxMaterial.GetParamBlock(0).Owner as IStdMat2; if (stdMat != null) { var babylonMaterial = new BabylonStandardMaterial { name = name, id = id, ambient = materialNode.MaxMaterial.GetAmbient(0, false).ToArray(), diffuse = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(), specular = materialNode.MaxMaterial.GetSpecular(0, false).Scale(materialNode.MaxMaterial.GetShinStr(0, false)), specularPower = materialNode.MaxMaterial.GetShininess(0, false) * 256, emissive = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false) ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray() : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)), alpha = 1.0f - materialNode.MaxMaterial.GetXParency(0, false) }; babylonMaterial.backFaceCulling = !stdMat.TwoSided; babylonMaterial.wireframe = stdMat.Wire; // Textures BabylonFresnelParameters fresnelParameters; babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, out fresnelParameters, babylonScene); // Ambient babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, out fresnelParameters, babylonScene); // Diffuse if (fresnelParameters != null) { babylonMaterial.diffuseFresnelParameters = fresnelParameters; } babylonMaterial.specularTexture = ExportTexture(stdMat, 2, out fresnelParameters, babylonScene); // Specular babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, out fresnelParameters, babylonScene); // Emissive if (fresnelParameters != null) { babylonMaterial.emissiveFresnelParameters = fresnelParameters; if (babylonMaterial.emissive[0] == 0 && babylonMaterial.emissive[1] == 0 && babylonMaterial.emissive[2] == 0 && babylonMaterial.emissiveTexture == null) { babylonMaterial.emissive = new float[] { 1, 1, 1 }; } } babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, out fresnelParameters, babylonScene, false, true); // Opacity if (fresnelParameters != null) { babylonMaterial.opacityFresnelParameters = fresnelParameters; if (babylonMaterial.alpha == 1 && babylonMaterial.opacityTexture == null) { babylonMaterial.alpha = 0; } } babylonMaterial.bumpTexture = ExportTexture(stdMat, 8, out fresnelParameters, babylonScene); // Bump babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, out fresnelParameters, babylonScene, true); // Reflection if (fresnelParameters != null) { if (babylonMaterial.reflectionTexture == null) { RaiseWarning("Fallout cannot be used with reflection channel without a texture", 2); } else { babylonMaterial.reflectionFresnelParameters = fresnelParameters; } } // Constraints if (babylonMaterial.diffuseTexture != null) { babylonMaterial.diffuse = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new float[] { 0, 0, 0 }; } if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null && babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name && babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB) { // This is a alpha testing purpose babylonMaterial.opacityTexture = null; babylonMaterial.diffuseTexture.hasAlpha = true; RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", 2); RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", 2); } babylonScene.MaterialsList.Add(babylonMaterial); } else if (materialNode.MaterialClass == "Physical Material") { var propertyContainer = materialNode.IPropertyContainer; var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial { name = name, id = id }; // --- Global --- // Alpha // --- // TODO - Unclear if alpha must be stored within 'alpha' property of BABYLON.Material // or within alpha channel of 'baseColor' of BABYLON.PBRMetallicRoughnessMaterial // --- // TODO - XParency seems computed from several parameters // 'Transparency' property is one of them // Which value to use? var alphaFromXParency = 1.0f - materialNode.MaxMaterial.GetXParency(0, false); var alphaFromPropertyContainer = 1.0f - propertyContainer.GetFloatProperty(17); RaiseMessage("alphaFromXParency=" + alphaFromXParency, 2); RaiseMessage("alphaFromPropertyContainer=" + alphaFromPropertyContainer, 2); babylonMaterial.alpha = alphaFromXParency; babylonMaterial.baseColor = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(); babylonMaterial.metallic = propertyContainer.GetFloatProperty(6); babylonMaterial.roughness = propertyContainer.GetFloatProperty(4); if (propertyContainer.GetIntProperty(5) == 1) { // Inverse roughness babylonMaterial.roughness = 1 - babylonMaterial.roughness; } // Self illumination is computed from emission color, luminance, temperature and weight babylonMaterial.emissiveColor = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false) ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray() : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)); // --- Textures --- babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(materialNode, babylonScene, name); if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } babylonMaterial.metallicRoughnessTexture = ExportMetallicRoughnessTexture(materialNode, babylonMaterial.metallic, babylonMaterial.roughness, babylonScene, name); babylonMaterial.environmentTexture = ExportPBRTexture(materialNode, 3, babylonScene); var normalMapAmount = propertyContainer.GetFloatProperty(91); babylonMaterial.normalTexture = ExportPBRTexture(materialNode, 30, babylonScene, normalMapAmount); babylonMaterial.emissiveTexture = ExportPBRTexture(materialNode, 17, babylonScene); // Constraints if (babylonMaterial.baseTexture != null) { babylonMaterial.baseColor = new[] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissiveColor = new float[] { 0, 0, 0 }; } babylonScene.MaterialsList.Add(babylonMaterial); } else { RaiseWarning("Unsupported material type: " + materialNode.MaterialClass, 2); } }
private void ExportMaterial(Material materialNode, BabylonScene babylonScene) { var name = materialNode._Mtl.Name; var id = materialNode.GetGuid().ToString(); RaiseMessage(name, true); if (materialNode.NumSubMaterials > 0) { var babylonMultimaterial = new BabylonMultiMaterial(); babylonMultimaterial.name = name; babylonMultimaterial.id = id; var guids = new List <string>(); for (var index = 0; index < materialNode.NumSubMaterials; index++) { var subMat = materialNode.GetSubMaterial(index) as Material; if (subMat != null) { guids.Add(subMat.GetGuid().ToString()); if (!referencedMaterials.Contains(subMat)) { referencedMaterials.Add(subMat); ExportMaterial(subMat, babylonScene); } } else { guids.Add(Guid.Empty.ToString()); } } babylonMultimaterial.materials = guids.ToArray(); babylonScene.MultiMaterialsList.Add(babylonMultimaterial); } var babylonMaterial = new BabylonMaterial(); babylonMaterial.name = name; babylonMaterial.id = id; babylonMaterial.ambient = materialNode.GetAmbient(0).ToArray(); babylonMaterial.diffuse = materialNode.GetDiffuse(0).ToArray(); babylonMaterial.specular = materialNode.GetSpecular(0).Scale(materialNode.GetShininess(0)); babylonMaterial.specularPower = materialNode.GetShinyStrength(0); babylonMaterial.emissive = materialNode.SelfIlluminationColorOn ? materialNode.GetSelfIllumColor(0).ToArray() : materialNode.GetDiffuse(0).Scale(materialNode.GetSelfIllumination(0)); babylonMaterial.alpha = 1.0f - materialNode.GetTransparency(0); var stdMat = materialNode._Mtl.GetParamBlock(0).Owner as IStdMat2; if (stdMat != null) { // Textures babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, babylonScene); // Ambient babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, babylonScene); // Diffuse babylonMaterial.specularTexture = ExportTexture(stdMat, 2, babylonScene); // Specular babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, babylonScene); // Emissive babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, babylonScene); // Opacity babylonMaterial.bumpTexture = ExportTexture(stdMat, 8, babylonScene); // Bump babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, babylonScene); // Reflection // Constraints if (babylonMaterial.diffuseTexture != null) { babylonMaterial.emissive = new [] { 1.0f, 1.0f, 1.0f }; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new float[] { 0, 0, 0 }; } if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null && babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name && babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB) { // This is a alpha testing purpose babylonMaterial.opacityTexture = null; babylonMaterial.diffuseTexture.hasAlpha = true; RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", true); RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", true); } } babylonScene.MaterialsList.Add(babylonMaterial); }