public static void updateManipulators(RotateManipContext ctx) { if (ctx == null) return; ctx.deleteManipulators(); // Add the rotate manipulator to each selected object. This produces // behavior different from the default rotate manipulator behavior. Here, // a distinct rotate manipulator is attached to every object. // try { MSelectionList list = MGlobal.activeSelectionList; MItSelectionList iter = new MItSelectionList(list, MFn.Type.kInvalid); for (; !iter.isDone; iter.next()) { // Make sure the selection list item is a depend node and has the // required plugs before manipulating it. // MObject dependNode = new MObject(); iter.getDependNode(dependNode); if (dependNode.isNull || !dependNode.hasFn(MFn.Type.kDependencyNode)) { MGlobal.displayWarning("Object in selection list is not a depend node."); continue; } MFnDependencyNode dependNodeFn = new MFnDependencyNode(dependNode); try { /* MPlug rPlug = */ dependNodeFn.findPlug("rotate"); } catch (System.Exception) { MGlobal.displayWarning("Object cannot be manipulated: " + dependNodeFn.name); continue; } // Add manipulator to the selected object // MObject manipObject = new MObject(); exampleRotateManip manipulator; try { manipulator = exampleRotateManip.newManipulator("exampleRotateManipCSharp", manipObject) as exampleRotateManip; // Add the manipulator // ctx.addManipulator(manipObject); // Connect the manipulator to the object in the selection list. // try { manipulator.connectToDependNode(dependNode); } catch (System.Exception) { MGlobal.displayWarning("Error connecting manipulator to object: " + dependNodeFn.name); } } catch (System.Exception) { } } } catch (System.Exception) { } }
/// <summary> /// Convert the Maya texture animation of a MFnDependencyNode in Babylon animations /// </summary> /// <param name="textureDependencyNode">The MFnDependencyNode of the texture</param> /// <returns>A list of texture animation</returns> public List <BabylonAnimation> GetTextureAnimations(MFnDependencyNode textureDependencyNode) { List <BabylonAnimation> animations = new List <BabylonAnimation>(); // Look for a "place2dTexture" object in the connections of the node. // The "place2dTexture" object contains the animation parameters MPlugArray connections = new MPlugArray(); textureDependencyNode.getConnections(connections); int index = 0; string place2dTexture = null; while (index < connections.Count && place2dTexture == null) { MPlug connection = connections[index]; MObject source = connection.source.node; if (source != null && source.hasFn(MFn.Type.kPlace2dTexture)) { MFnDependencyNode node = new MFnDependencyNode(source); place2dTexture = node.name; } index++; } if (place2dTexture != null) { IDictionary <string, string> properties = new Dictionary <string, string> { ["offsetU"] = "uOffset", ["offsetU"] = "uOffset", ["offsetV"] = "vOffset", ["repeatU"] = "uScale", ["repeatV"] = "vScale" }; // Get the animation for each properties for (index = 0; index < properties.Count; index++) { KeyValuePair <string, string> property = properties.ElementAt(index); BabylonAnimation animation = GetAnimationFloat(place2dTexture, property.Key, property.Value); if (animation != null) { animations.Add(animation); } } // For the rotation, convert degree to radian BabylonAnimation rotationAnimation = GetAnimationFloat(place2dTexture, "rotateFrame", "wAng"); if (rotationAnimation != null) { BabylonAnimationKey[] keys = rotationAnimation.keys; for (index = 0; index < keys.Length; index++) { var key = keys[index]; key.values[0] *= (float)(Math.PI / 180d); } animations.Add(rotationAnimation); } } return(animations); }
//! Ensure that valid geometry is selected bool validGeometrySelected() { MSelectionList list = new MSelectionList(); MGlobal.getActiveSelectionList(list); MItSelectionList iter = new MItSelectionList(list, MFn.Type.kInvalid); for (; !iter.isDone; iter.next()) { MObject dependNode = new MObject(); iter.getDependNode(dependNode); if (dependNode.isNull || !dependNode.hasFn(MFn.Type.kTransform)) { MGlobal.displayWarning("Object in selection list is not right type of node"); return false; } MFnDependencyNode dependNodeFn = new MFnDependencyNode(dependNode); MStringArray attributeNames = new MStringArray(); attributeNames.append("scaleX"); attributeNames.append("translateX"); int i; for ( i = 0; i < attributeNames.length; i++ ) { MPlug plug = dependNodeFn.findPlug(attributeNames[i]); if ( plug.isNull ) { MGlobal.displayWarning("Object cannot be manipulated: " + dependNodeFn.name); return false; } } } return true; }
// // Description: // Overloaded function from MPxDragAndDropBehavior // this method will handle the connection between the slopeShaderNodeCSharp and the shader it is // assigned to as well as any meshes that it is assigned to. // public override void connectNodeToNode(MObject sourceNode, MObject destinationNode, bool force) { MFnDependencyNode src = new MFnDependencyNode(sourceNode); //if we are dragging from a lambert //we want to check what we are dragging //onto. if(sourceNode.hasFn(MFn.Type.kLambert)) { //MObject shaderNode; MPlugArray connections = new MPlugArray(); MObjectArray shaderNodes = new MObjectArray(); shaderNodes.clear(); //if the source node was a lambert //than we will check the downstream connections to see //if a slope shader is assigned to it. // src.getConnections(connections); int i; for(i = 0; i < connections.length; i++) { //check the incoming connections to this plug // MPlugArray connectedPlugs = new MPlugArray(); connections[i].connectedTo(connectedPlugs, true, false); for(uint j = 0; j < connectedPlugs.length; j++) { //if the incoming node is a slope shader than //append the node to the shaderNodes array // MObject currentnode = connectedPlugs[i].node; if (new MFnDependencyNode(currentnode).typeName == "slopeShaderNodeCSharp") { shaderNodes.append(currentnode); } } } //if we found a shading node //than check the destination node //type to see if it is a mesh // if(shaderNodes.length > 0) { MFnDependencyNode dest = new MFnDependencyNode(destinationNode); if(destinationNode.hasFn(MFn.Type.kMesh)) { //if the node is a mesh than for each slopeShaderNodeCSharp //connect the worldMesh attribute to the dirtyShaderPlug //attribute to force an evaluation of the node when the mesh //changes // for(i = 0; i < shaderNodes.length; i++) { MPlug srcPlug = dest.findPlug("worldMesh"); MPlug destPlug = new MFnDependencyNode(shaderNodes[i]).findPlug("dirtyShaderPlug"); if(!srcPlug.isNull && !destPlug.isNull) { string cmd = "connectAttr -na "; cmd += srcPlug.name + " "; cmd += destPlug.name; try { // in slopeShaderBehavior.cpp, this may excute failed but continue on the following code, so we catch it. MGlobal.executeCommand(cmd); } catch (System.Exception) { MGlobal.displayError("ExcuteCommand (" + cmd + ") failed."); } } } //get the shading engine so we can assign the shader //to the mesh after doing the connection // MObject shadingEngine = findShadingEngine(sourceNode); //if there is a valid shading engine than make //the connection // if(!shadingEngine.isNull) { string cmd = "sets -edit -forceElement "; cmd += new MFnDependencyNode(shadingEngine).name + " "; cmd += new MFnDagNode(destinationNode).partialPathName; MGlobal.executeCommand(cmd); } } } } else if (src.typeName == "slopeShaderNodeCSharp") //if we are dragging from a slope shader //than we want to see what we are dragging onto // { if(destinationNode.hasFn(MFn.Type.kMesh)) { //if the user is dragging onto a mesh //than make the connection from the worldMesh //to the dirtyShader plug on the slopeShaderNodeCSharp // MFnDependencyNode dest = new MFnDependencyNode(destinationNode); MPlug srcPlug = dest.findPlug("worldMesh"); MPlug destPlug = src.findPlug("dirtyShaderPlug"); if(!srcPlug.isNull && !destPlug.isNull) { string cmd = "connectAttr -na "; cmd += srcPlug.name + " "; cmd += destPlug.name; MGlobal.executeCommand(cmd); } } } return; }
public override void componentToPlugs(MObject component, MSelectionList list) // // Description // // Converts the given component values into a selection list of plugs. // This method is used to map components to attributes. // // Arguments // // component - the component to be translated to a plug/attribute // list - a list of plugs representing the passed in component // { if ( component.hasFn(MFn.Type.kSingleIndexedComponent) ) { MFnSingleIndexedComponent fnVtxComp = new MFnSingleIndexedComponent( component ); MObject thisNode = thisMObject(); MPlug plug = new MPlug( thisNode, mControlPoints ); // If this node is connected to a tweak node, reset the // plug to point at the tweak node. // convertToTweakNodePlug(plug); int len = fnVtxComp.elementCount; for ( int i = 0; i < len; i++ ) { plug.selectAncestorLogicalIndex((uint)fnVtxComp.element(i), plug.attribute); list.add(plug); } } }
private void ExportMaterial(MFnDependencyNode materialDependencyNode, BabylonScene babylonScene, bool fullPBR) { MObject materialObject = materialDependencyNode.objectProperty; var name = materialDependencyNode.name; var id = materialDependencyNode.uuid().asString(); RaiseMessage(name, 1); RaiseMessage(materialObject.apiType.ToString(), 1); RaiseVerbose("materialObject.hasFn(MFn.Type.kBlinn)=" + materialObject.hasFn(MFn.Type.kBlinn), 2); RaiseVerbose("materialObject.hasFn(MFn.Type.kPhong)=" + materialObject.hasFn(MFn.Type.kPhong), 2); RaiseVerbose("materialObject.hasFn(MFn.Type.kPhongExplorer)=" + materialObject.hasFn(MFn.Type.kPhongExplorer), 2); Print(materialDependencyNode, 2, "Print ExportMaterial materialDependencyNode"); // Retreive Babylon Material dependency node MFnDependencyNode babylonAttributesDependencyNode = getBabylonMaterialNode(materialDependencyNode); // Standard material if (materialObject.hasFn(MFn.Type.kLambert)) { if (materialObject.hasFn(MFn.Type.kBlinn)) { RaiseMessage("Blinn shader", 2); } else if (materialObject.hasFn(MFn.Type.kPhong)) { RaiseMessage("Phong shader", 2); } else if (materialObject.hasFn(MFn.Type.kPhongExplorer)) { RaiseMessage("Phong E shader", 2); } else { RaiseMessage("Lambert shader", 2); } var lambertShader = new MFnLambertShader(materialObject); RaiseVerbose("typeId=" + lambertShader.typeId, 2); RaiseVerbose("typeName=" + lambertShader.typeName, 2); RaiseVerbose("color=" + lambertShader.color.toString(), 2); RaiseVerbose("transparency=" + lambertShader.transparency.toString(), 2); RaiseVerbose("ambientColor=" + lambertShader.ambientColor.toString(), 2); RaiseVerbose("incandescence=" + lambertShader.incandescence.toString(), 2); RaiseVerbose("diffuseCoeff=" + lambertShader.diffuseCoeff, 2); RaiseVerbose("translucenceCoeff=" + lambertShader.translucenceCoeff, 2); BabylonStandardMaterial babylonMaterial = new BabylonStandardMaterial(id) { name = name, diffuse = lambertShader.color.toArrayRGB() }; // User custom attributes babylonMaterial.metadata = ExportCustomAttributeFromMaterial(babylonMaterial); bool isTransparencyModeFromBabylonMaterialNode = false; if (babylonAttributesDependencyNode != null) { // Transparency mode if (babylonAttributesDependencyNode.hasAttribute("babylonTransparencyMode")) { int transparencyMode = babylonAttributesDependencyNode.findPlug("babylonTransparencyMode").asInt(); babylonMaterial.transparencyMode = transparencyMode; isTransparencyModeFromBabylonMaterialNode = true; } } // Maya ambient <=> babylon emissive babylonMaterial.emissive = lambertShader.ambientColor.toArrayRGB(); babylonMaterial.linkEmissiveWithDiffuse = true; // Incandescence (or Illumination) is not exported if (isTransparencyModeFromBabylonMaterialNode == false || babylonMaterial.transparencyMode != 0) { // If transparency is not a shade of grey (shade of grey <=> R=G=B) if (lambertShader.transparency[0] != lambertShader.transparency[1] || lambertShader.transparency[0] != lambertShader.transparency[2]) { RaiseWarning("Transparency color is not a shade of grey. Only it's R channel is used.", 2); } // Convert transparency to opacity babylonMaterial.alpha = 1.0f - lambertShader.transparency[0]; } // Specular power if (materialObject.hasFn(MFn.Type.kReflect)) { var reflectShader = new MFnReflectShader(materialObject); RaiseVerbose("specularColor=" + reflectShader.specularColor.toString(), 2); RaiseVerbose("reflectivity=" + reflectShader.reflectivity, 2); RaiseVerbose("reflectedColor=" + reflectShader.reflectedColor.toString(), 2); babylonMaterial.specular = reflectShader.specularColor.toArrayRGB(); if (materialObject.hasFn(MFn.Type.kBlinn)) { MFnBlinnShader blinnShader = new MFnBlinnShader(materialObject); babylonMaterial.specularPower = (1.0f - blinnShader.eccentricity) * 256; } else if (materialObject.hasFn(MFn.Type.kPhong)) { MFnPhongShader phongShader = new MFnPhongShader(materialObject); float glossiness = (float)Math.Log(phongShader.cosPower, 2) * 10; babylonMaterial.specularPower = glossiness / 100 * 256; } else if (materialObject.hasFn(MFn.Type.kPhongExplorer)) { MFnPhongEShader phongEShader = new MFnPhongEShader(materialObject); // No use of phongE.whiteness and phongE.highlightSize babylonMaterial.specularPower = (1.0f - phongEShader.roughness) * 256; } else { RaiseWarning("Unknown reflect shader type: " + reflectShader.typeName + ". Specular power is default 64. Consider using a Blinn or Phong shader instead.", 2); } } // TODO //babylonMaterial.wireframe = stdMat.Wire; // --- Textures --- babylonMaterial.diffuseTexture = ExportTexture(materialDependencyNode, "color", babylonScene); babylonMaterial.emissiveTexture = ExportTexture(materialDependencyNode, "ambientColor", babylonScene); // Maya ambient <=> babylon emissive babylonMaterial.bumpTexture = ExportTexture(materialDependencyNode, "normalCamera", babylonScene); if (isTransparencyModeFromBabylonMaterialNode == false || babylonMaterial.transparencyMode != 0) { babylonMaterial.opacityTexture = ExportTexture(materialDependencyNode, "transparency", babylonScene, false, true); } if (materialObject.hasFn(MFn.Type.kReflect)) { babylonMaterial.specularTexture = ExportTexture(materialDependencyNode, "specularColor", babylonScene); babylonMaterial.reflectionTexture = ExportTexture(materialDependencyNode, "reflectedColor", babylonScene, true, false, true); } if (isTransparencyModeFromBabylonMaterialNode == false && (babylonMaterial.alpha != 1.0f || (babylonMaterial.diffuseTexture != null && babylonMaterial.diffuseTexture.hasAlpha) || babylonMaterial.opacityTexture != null)) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } // 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.transparencyMode == (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHATEST) { // Set the alphaCutOff value explicitely to avoid different interpretations on different engines // Use the glTF default value rather than the babylon one babylonMaterial.alphaCutOff = 0.5f; } if (babylonAttributesDependencyNode == null) { // Create Babylon Material dependency node babylonStandardMaterialNode.Create(materialDependencyNode); // Retreive Babylon Material dependency node babylonAttributesDependencyNode = getBabylonMaterialNode(materialDependencyNode); } if (babylonAttributesDependencyNode != null) { // Ensure all attributes are setup babylonStandardMaterialNode.Init(babylonAttributesDependencyNode, babylonMaterial); RaiseVerbose("Babylon Attributes of " + babylonAttributesDependencyNode.name, 2); // Common attributes ExportCommonBabylonAttributes(babylonAttributesDependencyNode, babylonMaterial); // Special treatment for Unlit if (babylonMaterial.isUnlit) { if ((babylonMaterial.emissive != null && (babylonMaterial.emissive[0] != 0 || babylonMaterial.emissive[1] != 0 || babylonMaterial.emissive[2] != 0)) || (babylonMaterial.emissiveTexture != null) || (babylonMaterial.emissiveFresnelParameters != null)) { RaiseWarning("Material is unlit. Emission is discarded and replaced by diffuse.", 2); } // Copy diffuse to emissive babylonMaterial.emissive = babylonMaterial.diffuse; babylonMaterial.emissiveTexture = babylonMaterial.diffuseTexture; babylonMaterial.emissiveFresnelParameters = babylonMaterial.diffuseFresnelParameters; babylonMaterial.disableLighting = true; babylonMaterial.linkEmissiveWithDiffuse = false; } // Special treatment for "Alpha test" transparency mode if (babylonMaterial.transparencyMode == (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHATEST && ((babylonMaterial.diffuseTexture != null && babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture.originalPath != babylonMaterial.opacityTexture.originalPath) || (babylonMaterial.diffuseTexture == null && babylonMaterial.opacityTexture != null))) { // Base color and alpha files need to be merged into a single file Color defaultColor = Color.FromArgb((int)(babylonMaterial.diffuse[0] * 255), (int)(babylonMaterial.diffuse[1] * 255), (int)(babylonMaterial.diffuse[2] * 255)); MFnDependencyNode baseColorTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "color"); MFnDependencyNode opacityTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "transparency"); babylonMaterial.diffuseTexture = ExportBaseColorAlphaTexture(baseColorTextureDependencyNode, opacityTextureDependencyNode, babylonScene, name, defaultColor, babylonMaterial.alpha); babylonMaterial.opacityTexture = null; babylonMaterial.alpha = 1.0f; } } babylonScene.MaterialsList.Add(babylonMaterial); } // Stingray PBS material else if (isStingrayPBSMaterial(materialDependencyNode)) { RaiseMessage("Stingray shader", 2); var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial(id) { name = name }; // --- Global --- // Color3 babylonMaterial.baseColor = materialDependencyNode.findPlug("base_color").asFloatArray(); // Alpha string opacityAttributeName = "opacity"; if (materialDependencyNode.hasAttribute(opacityAttributeName)) { float opacityAttributeValue = materialDependencyNode.findPlug(opacityAttributeName).asFloat(); babylonMaterial.alpha = 1.0f - opacityAttributeValue; } // Metallic & roughness babylonMaterial.metallic = materialDependencyNode.findPlug("metallic").asFloat(); babylonMaterial.roughness = materialDependencyNode.findPlug("roughness").asFloat(); // Emissive float emissiveIntensity = materialDependencyNode.findPlug("emissive_intensity").asFloat(); // Factor emissive color with emissive intensity emissiveIntensity = Tools.Clamp(emissiveIntensity, 0f, 1f); babylonMaterial.emissive = materialDependencyNode.findPlug("emissive").asFloatArray().Multiply(emissiveIntensity); // --- Textures --- // Base color & alpha bool useColorMap = materialDependencyNode.findPlug("use_color_map").asBool(); bool useOpacityMap = false; string useOpacityMapAttributeName = "use_opacity_map"; if (materialDependencyNode.hasAttribute(useOpacityMapAttributeName)) { useOpacityMap = materialDependencyNode.findPlug(useOpacityMapAttributeName).asBool(); } if (materialDependencyNode.hasAttribute("mask_threshold")) // Preset "Masked" { if (useColorMap && useOpacityMap) { // Texture is assumed to be already merged babylonMaterial.baseTexture = ExportTexture(materialDependencyNode, "TEX_color_map", babylonScene, false, true); } else if (useColorMap || useOpacityMap) { // Merge Diffuse and Mask Color defaultColor = Color.FromArgb((int)(babylonMaterial.baseColor[0] * 255), (int)(babylonMaterial.baseColor[1] * 255), (int)(babylonMaterial.baseColor[2] * 255)); // In Maya, a Masked StingrayPBS material without opacity or mask textures is counted as being fully transparent // Such material is visible only when the mask threshold is set to 0 float defaultOpacity = 0; // Either use the color map MFnDependencyNode baseColorTextureDependencyNode = null; if (useColorMap) { baseColorTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "TEX_color_map"); } // Or the opacity map MFnDependencyNode opacityTextureDependencyNode = null; if (useOpacityMap) { opacityTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "TEX_color_map"); } // Merge default value and texture babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(baseColorTextureDependencyNode, opacityTextureDependencyNode, babylonScene, babylonMaterial.name, defaultColor, defaultOpacity); } else { // In Maya, a Masked StingrayPBS material without opacity or mask textures is counted as being fully transparent // Such material is visible only when the mask threshold is set to 0 babylonMaterial.alpha = 0; } } else { if (useColorMap || useOpacityMap) { // Force non use map to default value // Ex: if useOpacityMap == false, force alpha = 255 for all pixels. babylonMaterial.baseTexture = ExportTexture(materialDependencyNode, "TEX_color_map", babylonScene, false, useOpacityMap); } } if (babylonMaterial.transparencyMode == (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHATEST) { // Set the alphaCutOff value explicitely to avoid different interpretations on different engines // Use the glTF default value rather than the babylon one babylonMaterial.alphaCutOff = 0.5f; } // Alpha cuttoff if (materialDependencyNode.hasAttribute("mask_threshold")) // Preset "Masked" { babylonMaterial.alphaCutOff = materialDependencyNode.findPlug("mask_threshold").asFloat(); } // Metallic, roughness, ambient occlusion bool useMetallicMap = materialDependencyNode.findPlug("use_metallic_map").asBool(); bool useRoughnessMap = materialDependencyNode.findPlug("use_roughness_map").asBool(); string useAOMapAttributeName = "use_ao_map"; bool useAOMap = materialDependencyNode.hasAttribute(useAOMapAttributeName) && materialDependencyNode.findPlug(useAOMapAttributeName).asBool(); MFnDependencyNode metallicTextureDependencyNode = useMetallicMap ? getTextureDependencyNode(materialDependencyNode, "TEX_metallic_map") : null; MFnDependencyNode roughnessTextureDependencyNode = useRoughnessMap ? getTextureDependencyNode(materialDependencyNode, "TEX_roughness_map") : null; MFnDependencyNode ambientOcclusionTextureDependencyNode = useAOMap ? getTextureDependencyNode(materialDependencyNode, "TEX_ao_map") : null; // Check if MR or ORM textures are already merged bool areTexturesAlreadyMerged = false; if (metallicTextureDependencyNode != null && roughnessTextureDependencyNode != null) { string sourcePathMetallic = getSourcePathFromFileTexture(metallicTextureDependencyNode); string sourcePathRoughness = getSourcePathFromFileTexture(roughnessTextureDependencyNode); if (sourcePathMetallic == sourcePathRoughness) { if (ambientOcclusionTextureDependencyNode != null) { string sourcePathAmbientOcclusion = getSourcePathFromFileTexture(ambientOcclusionTextureDependencyNode); if (sourcePathMetallic == sourcePathAmbientOcclusion) { // Metallic, roughness and ambient occlusion are already merged RaiseVerbose("Metallic, roughness and ambient occlusion are already merged", 2); BabylonTexture ormTexture = ExportTexture(metallicTextureDependencyNode, 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(metallicTextureDependencyNode, babylonScene); babylonMaterial.metallicRoughnessTexture = ormTexture; areTexturesAlreadyMerged = true; } } } if (areTexturesAlreadyMerged == false) { if (metallicTextureDependencyNode != null || roughnessTextureDependencyNode != null) { // Merge metallic, roughness and ambient occlusion RaiseVerbose("Merge metallic, roughness and ambient occlusion", 2); BabylonTexture ormTexture = ExportORMTexture(babylonScene, metallicTextureDependencyNode, roughnessTextureDependencyNode, ambientOcclusionTextureDependencyNode, babylonMaterial.metallic, babylonMaterial.roughness); babylonMaterial.metallicRoughnessTexture = ormTexture; if (ambientOcclusionTextureDependencyNode != null) { babylonMaterial.occlusionTexture = ormTexture; } } else if (ambientOcclusionTextureDependencyNode != null) { // Simply export occlusion texture RaiseVerbose("Simply export occlusion texture", 2); babylonMaterial.occlusionTexture = ExportTexture(ambientOcclusionTextureDependencyNode, babylonScene); } } // Normal if (materialDependencyNode.findPlug("use_normal_map").asBool()) { babylonMaterial.normalTexture = ExportTexture(materialDependencyNode, "TEX_normal_map", babylonScene); } // Emissive bool useEmissiveMap = materialDependencyNode.findPlug("use_emissive_map").asBool(); if (useEmissiveMap) { babylonMaterial.emissiveTexture = ExportTexture(materialDependencyNode, "TEX_emissive_map", babylonScene, false, false, false, emissiveIntensity); } // Constraints if (useColorMap) { babylonMaterial.baseColor = new[] { 1.0f, 1.0f, 1.0f }; } if (useOpacityMap) { babylonMaterial.alpha = 1.0f; } if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { if (materialDependencyNode.hasAttribute("mask_threshold")) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHATEST; } else { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } } if (useMetallicMap) { babylonMaterial.metallic = 1.0f; } if (useRoughnessMap) { babylonMaterial.roughness = 1.0f; } if (useEmissiveMap) { babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f }; } // User custom attributes babylonMaterial.metadata = ExportCustomAttributeFromMaterial(babylonMaterial); if (babylonAttributesDependencyNode == null) { // Create Babylon Material dependency node babylonStingrayPBSMaterialNode.Create(materialDependencyNode); // Retreive Babylon Material dependency node babylonAttributesDependencyNode = getBabylonMaterialNode(materialDependencyNode); } if (babylonAttributesDependencyNode != null) { // Ensure all attributes are setup babylonStingrayPBSMaterialNode.Init(babylonAttributesDependencyNode, babylonMaterial); RaiseVerbose("Babylon Attributes of " + babylonAttributesDependencyNode.name, 2); // Common attributes ExportCommonBabylonAttributes(babylonAttributesDependencyNode, babylonMaterial); babylonMaterial.doubleSided = !babylonMaterial.backFaceCulling; babylonMaterial._unlit = babylonMaterial.isUnlit; // Update displayed Transparency mode value based on StingrayPBS preset material MGlobal.executeCommand($"setAttr - l false {{ \"{babylonAttributesDependencyNode.name}.babylonTransparencyMode\" }}"); // Unlock attribute int babylonTransparencyMode = 0; if (materialDependencyNode.hasAttribute("mask_threshold")) { babylonTransparencyMode = 1; } else if (materialDependencyNode.hasAttribute("use_opacity_map")) { babylonTransparencyMode = 2; } MGlobal.executeCommand($"setAttr \"{babylonAttributesDependencyNode.name}.babylonTransparencyMode\" {babylonTransparencyMode};"); MGlobal.executeCommand($"setAttr - l true {{ \"{babylonAttributesDependencyNode.name}.babylonTransparencyMode\" }}"); // Lock it afterwards } babylonScene.MaterialsList.Add(babylonMaterial); } // Arnold Ai Standard Surface else if (isAiStandardSurface(materialDependencyNode)) { RaiseMessage("Ai Standard Surface shader", 2); var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial(id) { name = name }; // User custom attributes babylonMaterial.metadata = ExportCustomAttributeFromMaterial(babylonMaterial); // --- Global --- bool isTransparencyModeFromBabylonMaterialNode = false; if (babylonAttributesDependencyNode != null) { // Transparency mode if (babylonAttributesDependencyNode.hasAttribute("babylonTransparencyMode")) { babylonMaterial.transparencyMode = babylonAttributesDependencyNode.findPlug("babylonTransparencyMode").asInt(); isTransparencyModeFromBabylonMaterialNode = true; } } // Color3 float baseWeight = materialDependencyNode.findPlug("base").asFloat(); float[] baseColor = materialDependencyNode.findPlug("baseColor").asFloatArray(); babylonMaterial.baseColor = baseColor.Multiply(baseWeight); // Alpha MaterialDuplicationData materialDuplicationData = materialDuplicationDatas[id]; // If at least one mesh is Transparent and is using this material either directly or as a sub material if ((isTransparencyModeFromBabylonMaterialNode == false || babylonMaterial.transparencyMode != 0) && materialDuplicationData.isArnoldTransparent()) { float[] opacityAttributeValue = materialDependencyNode.findPlug("opacity").asFloatArray(); babylonMaterial.alpha = opacityAttributeValue[0]; } else { // Do not bother about alpha babylonMaterial.alpha = 1.0f; } // Metallic & roughness babylonMaterial.metallic = materialDependencyNode.findPlug("metalness").asFloat(); babylonMaterial.roughness = materialDependencyNode.findPlug("specularRoughness").asFloat(); // Emissive float emissionWeight = materialDependencyNode.findPlug("emission").asFloat(); babylonMaterial.emissive = materialDependencyNode.findPlug("emissionColor").asFloatArray().Multiply(emissionWeight); var list = new List <string>(); for (int i = 0; i < materialDependencyNode.attributeCount; i++) { var attr = materialDependencyNode.attribute((uint)i); var plug = materialDependencyNode.findPlug(attr); //string aliasName; //materialDependencyNode.getPlugsAlias(plug, out aliasName); System.Diagnostics.Debug.WriteLine(plug.name + i.ToString()); } // --- Clear Coat --- float coatWeight = materialDependencyNode.findPlug("coat").asFloat(); MFnDependencyNode intensityCoatTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "coat"); if (coatWeight > 0.0f || intensityCoatTextureDependencyNode != null) { babylonMaterial.clearCoat.isEnabled = true; babylonMaterial.clearCoat.indexOfRefraction = materialDependencyNode.findPlug("coatIOR").asFloat(); var coatRoughness = materialDependencyNode.findPlug("coatRoughness").asFloat(); MFnDependencyNode roughnessCoatTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "coatRoughness"); var coatTexture = ExportCoatTexture(intensityCoatTextureDependencyNode, roughnessCoatTextureDependencyNode, babylonScene, name, coatWeight, coatRoughness); if (coatTexture != null) { babylonMaterial.clearCoat.texture = coatTexture; babylonMaterial.clearCoat.roughness = 1.0f; babylonMaterial.clearCoat.intensity = 1.0f; } else { babylonMaterial.clearCoat.intensity = coatWeight; babylonMaterial.clearCoat.roughness = coatRoughness; } float[] coatColor = materialDependencyNode.findPlug("coatColor").asFloatArray(); if (coatColor[0] != 1.0f || coatColor[1] != 1.0f || coatColor[2] != 1.0f) { babylonMaterial.clearCoat.isTintEnabled = true; babylonMaterial.clearCoat.tintColor = coatColor; } babylonMaterial.clearCoat.tintTexture = ExportTexture(materialDependencyNode, "coatColor", babylonScene); if (babylonMaterial.clearCoat.tintTexture != null) { babylonMaterial.clearCoat.tintColor = new[] { 1.0f, 1.0f, 1.0f }; babylonMaterial.clearCoat.isTintEnabled = true; } // EyeBall deduction... babylonMaterial.clearCoat.tintThickness = 0.65f; babylonMaterial.clearCoat.bumpTexture = ExportTexture(materialDependencyNode, "coatNormal", babylonScene); } // --- Textures --- // Base color & alpha if ((isTransparencyModeFromBabylonMaterialNode == false || babylonMaterial.transparencyMode != 0) && materialDuplicationData.isArnoldTransparent()) { MFnDependencyNode baseColorTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "baseColor"); MFnDependencyNode opacityTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "opacity"); if (baseColorTextureDependencyNode != null && opacityTextureDependencyNode != null && getSourcePathFromFileTexture(baseColorTextureDependencyNode) == getSourcePathFromFileTexture(opacityTextureDependencyNode)) { // If the same file is used for base color and opacity // Base color and alpha are already merged into a single file babylonMaterial.baseTexture = ExportTexture(baseColorTextureDependencyNode, babylonScene, false, true); } else { // Base color and alpha files need to be merged into a single file Color _baseColor = Color.FromArgb((int)(baseColor[0] * 255), (int)(baseColor[1] * 255), (int)(baseColor[2] * 255)); babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(baseColorTextureDependencyNode, opacityTextureDependencyNode, babylonScene, name, _baseColor, babylonMaterial.alpha); } } else { // Base color only // Do not bother about alpha babylonMaterial.baseTexture = ExportTexture(materialDependencyNode, "baseColor", babylonScene); } // Metallic & roughness MFnDependencyNode metallicTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "metalness"); MFnDependencyNode roughnessTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "specularRoughness"); if (metallicTextureDependencyNode != null && roughnessTextureDependencyNode != null && getSourcePathFromFileTexture(metallicTextureDependencyNode) == getSourcePathFromFileTexture(roughnessTextureDependencyNode)) { // If the same file is used for metallic and roughness // Then we assume it's an ORM file (Red=Occlusion, Green=Roughness, Blue=Metallic) // Metallic and roughness are already merged into a single file babylonMaterial.metallicRoughnessTexture = ExportTexture(metallicTextureDependencyNode, babylonScene); // Use same file for Ambient occlusion babylonMaterial.occlusionTexture = babylonMaterial.metallicRoughnessTexture; } else { // Metallic and roughness files need to be merged into a single file // Occlusion texture is not exported since aiStandardSurface material doesn't provide input for it babylonMaterial.metallicRoughnessTexture = ExportORMTexture(babylonScene, metallicTextureDependencyNode, roughnessTextureDependencyNode, null, babylonMaterial.metallic, babylonMaterial.roughness); } // Normal babylonMaterial.normalTexture = ExportTexture(materialDependencyNode, "normalCamera", babylonScene); // Emissive babylonMaterial.emissiveTexture = ExportTexture(materialDependencyNode, "emissionColor", babylonScene); // Constraints if (babylonMaterial.baseTexture != null) { babylonMaterial.baseColor = new[] { baseWeight, baseWeight, baseWeight }; babylonMaterial.alpha = 1.0f; } if (babylonMaterial.metallicRoughnessTexture != null) { babylonMaterial.metallic = 1.0f; babylonMaterial.roughness = 1.0f; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new[] { emissionWeight, emissionWeight, emissionWeight }; } // If this material is containing alpha data if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { if (isTransparencyModeFromBabylonMaterialNode == false) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } // If this material is assigned to both Transparent and Opaque meshes (either directly or as a sub material) if (materialDuplicationData.isDuplicationRequired()) { // Duplicate material BabylonPBRMetallicRoughnessMaterial babylonMaterialCloned = DuplicateMaterial(babylonMaterial, materialDuplicationData); // Store duplicated material too babylonScene.MaterialsList.Add(babylonMaterialCloned); } } if (babylonMaterial.transparencyMode == (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHATEST) { // Set the alphaCutOff value explicitely to avoid different interpretations on different engines // Use the glTF default value rather than the babylon one babylonMaterial.alphaCutOff = 0.5f; } if (babylonAttributesDependencyNode == null) { // Create Babylon Material dependency node babylonAiStandardSurfaceMaterialNode.Create(materialDependencyNode); // Retreive Babylon Material dependency node babylonAttributesDependencyNode = getBabylonMaterialNode(materialDependencyNode); } if (babylonAttributesDependencyNode != null) { // Ensure all attributes are setup babylonAiStandardSurfaceMaterialNode.Init(babylonAttributesDependencyNode, babylonMaterial); RaiseVerbose("Babylon Attributes of " + babylonAttributesDependencyNode.name, 2); // Common attributes ExportCommonBabylonAttributes(babylonAttributesDependencyNode, babylonMaterial); babylonMaterial.doubleSided = !babylonMaterial.backFaceCulling; babylonMaterial._unlit = babylonMaterial.isUnlit; } if (fullPBR) { var fullPBRMaterial = new BabylonPBRMaterial(babylonMaterial); babylonScene.MaterialsList.Add(fullPBRMaterial); } else { babylonScene.MaterialsList.Add(babylonMaterial); } } else { RaiseWarning("Unsupported material type '" + materialObject.apiType + "' for material named '" + materialDependencyNode.name + "'", 2); } }
public override bool shouldBeUsedFor(MObject sourceNode, MObject destinationNode, MPlug sourcePlug, MPlug destinationPlug) { bool result = false; if (sourceNode.hasFn(MFn.Type.kLambert)) { //if the source node was a lambert //than we will check the downstream connections to see //if a slope shader is assigned to it. // MObject shaderNode = new MObject(); MFnDependencyNode src = new MFnDependencyNode(sourceNode); MPlugArray connections = new MPlugArray(); src.getConnections(connections); for (int i = 0; i < connections.length; i++) { //check the incoming connections to this plug // MPlugArray connectedPlugs = new MPlugArray(); connections[i].connectedTo(connectedPlugs, true, false); for (int j = 0; j < connectedPlugs.length; j++) { //if the incoming node is a slope shader than //set shaderNode equal to it and break out of the inner //loop // if (new MFnDependencyNode(connectedPlugs[j].node).typeName == "slopeShaderNodeCSharp") { shaderNode = connectedPlugs[j].node; break; } } //if the shaderNode is not null //than we have found a slopeShaderNodeCSharp // if (!shaderNode.isNull) { //if the destination node is a mesh than we will take //care of this connection so set the result to true //and break out of the outer loop // if (destinationNode.hasFn(MFn.Type.kMesh)) { result = true; } break; } } } if (new MFnDependencyNode(sourceNode).typeName == "slopeShaderNodeCSharp") //if the sourceNode is a slope shader than check what we //are dropping on to // { if (destinationNode.hasFn(MFn.Type.kLambert)) { result = true; } else if (destinationNode.hasFn(MFn.Type.kMesh)) { result = true; } } return(result); }
private void ExportMaterial(MFnDependencyNode materialDependencyNode, BabylonScene babylonScene) { MObject materialObject = materialDependencyNode.objectProperty; var name = materialDependencyNode.name; var id = materialDependencyNode.uuid().asString(); RaiseMessage(name, 1); RaiseVerbose("materialObject.hasFn(MFn.Type.kBlinn)=" + materialObject.hasFn(MFn.Type.kBlinn), 2); RaiseVerbose("materialObject.hasFn(MFn.Type.kPhong)=" + materialObject.hasFn(MFn.Type.kPhong), 2); RaiseVerbose("materialObject.hasFn(MFn.Type.kPhongExplorer)=" + materialObject.hasFn(MFn.Type.kPhongExplorer), 2); Print(materialDependencyNode, 2, "Print ExportMaterial materialDependencyNode"); // Standard material if (materialObject.hasFn(MFn.Type.kLambert)) { RaiseMessage("Lambert shader", 2); var lambertShader = new MFnLambertShader(materialObject); RaiseVerbose("typeId=" + lambertShader.typeId, 2); RaiseVerbose("typeName=" + lambertShader.typeName, 2); RaiseVerbose("color=" + lambertShader.color.toString(), 2); RaiseVerbose("transparency=" + lambertShader.transparency.toString(), 2); RaiseVerbose("ambientColor=" + lambertShader.ambientColor.toString(), 2); RaiseVerbose("incandescence=" + lambertShader.incandescence.toString(), 2); RaiseVerbose("diffuseCoeff=" + lambertShader.diffuseCoeff, 2); RaiseVerbose("translucenceCoeff=" + lambertShader.translucenceCoeff, 2); var babylonMaterial = new BabylonStandardMaterial { name = name, id = id, ambient = lambertShader.ambientColor.toArrayRGB(), diffuse = lambertShader.color.toArrayRGB(), emissive = lambertShader.incandescence.toArrayRGB(), alpha = 1.0f - lambertShader.transparency[0] }; // If transparency is not a shade of grey (shade of grey <=> R=G=B) if (lambertShader.transparency[0] != lambertShader.transparency[1] || lambertShader.transparency[0] != lambertShader.transparency[2]) { RaiseWarning("Transparency color is not a shade of grey. Only it's R channel is used.", 2); } // Convert transparency to opacity babylonMaterial.alpha = 1.0f - lambertShader.transparency[0]; // Specular power if (materialObject.hasFn(MFn.Type.kReflect)) { var reflectShader = new MFnReflectShader(materialObject); RaiseVerbose("specularColor=" + reflectShader.specularColor.toString(), 2); RaiseVerbose("reflectivity=" + reflectShader.reflectivity, 2); RaiseVerbose("reflectedColor=" + reflectShader.reflectedColor.toString(), 2); babylonMaterial.specular = reflectShader.specularColor.toArrayRGB(); if (materialObject.hasFn(MFn.Type.kBlinn)) { MFnBlinnShader blinnShader = new MFnBlinnShader(materialObject); babylonMaterial.specularPower = (1.0f - blinnShader.eccentricity) * 256; } else if (materialObject.hasFn(MFn.Type.kPhong)) { MFnPhongShader phongShader = new MFnPhongShader(materialObject); float glossiness = (float)Math.Log(phongShader.cosPower, 2) * 10; babylonMaterial.specularPower = glossiness / 100 * 256; } else if (materialObject.hasFn(MFn.Type.kPhongExplorer)) { MFnPhongEShader phongEShader = new MFnPhongEShader(materialObject); // No use of phongE.whiteness and phongE.highlightSize babylonMaterial.specularPower = (1.0f - phongEShader.roughness) * 256; } else { RaiseWarning("Unknown reflect shader type: " + reflectShader.typeName + ". Specular power is default 64. Consider using a Blinn or Phong shader instead.", 2); } } // TODO //babylonMaterial.backFaceCulling = !stdMat.TwoSided; //babylonMaterial.wireframe = stdMat.Wire; // Textures babylonMaterial.diffuseTexture = ExportTexture(materialDependencyNode, "color", babylonScene); babylonMaterial.ambientTexture = ExportTexture(materialDependencyNode, "ambientColor", babylonScene); babylonMaterial.emissiveTexture = ExportTexture(materialDependencyNode, "incandescence", babylonScene); babylonMaterial.bumpTexture = ExportTexture(materialDependencyNode, "normalCamera", babylonScene); // TODO - Convert transparency to opacity? babylonMaterial.opacityTexture = ExportTexture(materialDependencyNode, "transparency", babylonScene, false, true); if (materialObject.hasFn(MFn.Type.kReflect)) { babylonMaterial.specularTexture = ExportTexture(materialDependencyNode, "specularColor", babylonScene); babylonMaterial.reflectionTexture = ExportTexture(materialDependencyNode, "reflectedColor", babylonScene, true, false, true); } // 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 }; } babylonScene.MaterialsList.Add(babylonMaterial); } // PBR material else if (isPBRMaterial(materialDependencyNode)) { RaiseMessage("Stingray shader", 2); var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial { name = name, id = id }; // --- Global --- // Color3 babylonMaterial.baseColor = materialDependencyNode.findPlug("base_color").asFloatArray(); // Alpha string opacityAttributeName = "opacity"; if (materialDependencyNode.hasAttribute(opacityAttributeName)) { float opacityAttributeValue = materialDependencyNode.findPlug(opacityAttributeName).asFloatProperty; babylonMaterial.alpha = 1.0f - opacityAttributeValue; } // Metallic & roughness babylonMaterial.metallic = materialDependencyNode.findPlug("metallic").asFloatProperty; babylonMaterial.roughness = materialDependencyNode.findPlug("roughness").asFloatProperty; // Emissive float emissiveIntensity = materialDependencyNode.findPlug("emissive_intensity").asFloatProperty; // Factor emissive color with emissive intensity emissiveIntensity = Tools.Clamp(emissiveIntensity, 0f, 1f); babylonMaterial.emissive = materialDependencyNode.findPlug("emissive").asFloatArray(); for (int i = 0; i < babylonMaterial.emissive.Length; i++) { babylonMaterial.emissive[i] *= emissiveIntensity; } // --- Textures --- // Base color & alpha bool useColorMap = materialDependencyNode.findPlug("use_color_map").asBoolProperty; bool useOpacityMap = false; string useOpacityMapAttributeName = "use_opacity_map"; if (materialDependencyNode.hasAttribute(useOpacityMapAttributeName)) { useOpacityMap = materialDependencyNode.findPlug(useOpacityMapAttributeName).asBoolProperty; } if (useColorMap || useOpacityMap) { // TODO - Force non use map to default value ? // Ex: if useOpacityMap == false, force alpha = 255 for all pixels. //babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(materialDependencyNode, useColorMap, useOpacityMap, babylonMaterial.baseColor, babylonMaterial.alpha, babylonScene); babylonMaterial.baseTexture = ExportTexture(materialDependencyNode, "TEX_color_map", babylonScene, false, useOpacityMap); } // Metallic & roughness bool useMetallicMap = materialDependencyNode.findPlug("use_metallic_map").asBoolProperty; bool useRoughnessMap = materialDependencyNode.findPlug("use_roughness_map").asBoolProperty; babylonMaterial.metallicRoughnessTexture = ExportMetallicRoughnessTexture(materialDependencyNode, useMetallicMap, useRoughnessMap, babylonScene, name); if (materialDependencyNode.findPlug("use_normal_map").asBoolProperty) { babylonMaterial.normalTexture = ExportTexture(materialDependencyNode, "TEX_normal_map", babylonScene); } // Emissive bool useEmissiveMap = materialDependencyNode.findPlug("use_emissive_map").asBoolProperty; if (useEmissiveMap) { babylonMaterial.emissiveTexture = ExportTexture(materialDependencyNode, "TEX_emissive_map", babylonScene, false, false, false, emissiveIntensity); } // Ambient occlusion string useAOMapAttributeName = "use_ao_map"; if (materialDependencyNode.hasAttribute(useAOMapAttributeName) && materialDependencyNode.findPlug(useAOMapAttributeName).asBoolProperty) { babylonMaterial.occlusionTexture = ExportTexture(materialDependencyNode, "TEX_ao_map", babylonScene); } // Constraints if (useColorMap) { babylonMaterial.baseColor = new[] { 1.0f, 1.0f, 1.0f }; } if (useOpacityMap) { babylonMaterial.alpha = 1.0f; } if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } if (useMetallicMap) { babylonMaterial.metallic = 1.0f; } if (useRoughnessMap) { babylonMaterial.roughness = 1.0f; } if (useEmissiveMap) { babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f }; } babylonScene.MaterialsList.Add(babylonMaterial); } else { RaiseWarning("Unsupported material type '" + materialObject.apiType + "' for material named '" + materialDependencyNode.name + "'", 2); } }
private void ExportMaterial(MFnDependencyNode materialDependencyNode, BabylonScene babylonScene) { MObject materialObject = materialDependencyNode.objectProperty; var name = materialDependencyNode.name; var id = materialDependencyNode.uuid().asString(); RaiseMessage(name, 1); RaiseVerbose("materialObject.hasFn(MFn.Type.kBlinn)=" + materialObject.hasFn(MFn.Type.kBlinn), 2); RaiseVerbose("materialObject.hasFn(MFn.Type.kPhong)=" + materialObject.hasFn(MFn.Type.kPhong), 2); RaiseVerbose("materialObject.hasFn(MFn.Type.kPhongExplorer)=" + materialObject.hasFn(MFn.Type.kPhongExplorer), 2); Print(materialDependencyNode, 2, "Print ExportMaterial materialDependencyNode"); // Standard material if (materialObject.hasFn(MFn.Type.kLambert)) { if (materialObject.hasFn(MFn.Type.kBlinn)) { RaiseMessage("Blinn shader", 2); } else if (materialObject.hasFn(MFn.Type.kPhong)) { RaiseMessage("Phong shader", 2); } else if (materialObject.hasFn(MFn.Type.kPhongExplorer)) { RaiseMessage("Phong E shader", 2); } else { RaiseMessage("Lambert shader", 2); } var lambertShader = new MFnLambertShader(materialObject); RaiseVerbose("typeId=" + lambertShader.typeId, 2); RaiseVerbose("typeName=" + lambertShader.typeName, 2); RaiseVerbose("color=" + lambertShader.color.toString(), 2); RaiseVerbose("transparency=" + lambertShader.transparency.toString(), 2); RaiseVerbose("ambientColor=" + lambertShader.ambientColor.toString(), 2); RaiseVerbose("incandescence=" + lambertShader.incandescence.toString(), 2); RaiseVerbose("diffuseCoeff=" + lambertShader.diffuseCoeff, 2); RaiseVerbose("translucenceCoeff=" + lambertShader.translucenceCoeff, 2); var babylonMaterial = new BabylonStandardMaterial { name = name, id = id, diffuse = lambertShader.color.toArrayRGB(), alpha = 1.0f - lambertShader.transparency[0] }; // Maya ambient <=> babylon emissive babylonMaterial.emissive = lambertShader.ambientColor.toArrayRGB(); babylonMaterial.linkEmissiveWithDiffuse = true; // Incandescence (or Illumination) is not exported // If transparency is not a shade of grey (shade of grey <=> R=G=B) if (lambertShader.transparency[0] != lambertShader.transparency[1] || lambertShader.transparency[0] != lambertShader.transparency[2]) { RaiseWarning("Transparency color is not a shade of grey. Only it's R channel is used.", 2); } // Convert transparency to opacity babylonMaterial.alpha = 1.0f - lambertShader.transparency[0]; // Specular power if (materialObject.hasFn(MFn.Type.kReflect)) { var reflectShader = new MFnReflectShader(materialObject); RaiseVerbose("specularColor=" + reflectShader.specularColor.toString(), 2); RaiseVerbose("reflectivity=" + reflectShader.reflectivity, 2); RaiseVerbose("reflectedColor=" + reflectShader.reflectedColor.toString(), 2); babylonMaterial.specular = reflectShader.specularColor.toArrayRGB(); if (materialObject.hasFn(MFn.Type.kBlinn)) { MFnBlinnShader blinnShader = new MFnBlinnShader(materialObject); babylonMaterial.specularPower = (1.0f - blinnShader.eccentricity) * 256; } else if (materialObject.hasFn(MFn.Type.kPhong)) { MFnPhongShader phongShader = new MFnPhongShader(materialObject); float glossiness = (float)Math.Log(phongShader.cosPower, 2) * 10; babylonMaterial.specularPower = glossiness / 100 * 256; } else if (materialObject.hasFn(MFn.Type.kPhongExplorer)) { MFnPhongEShader phongEShader = new MFnPhongEShader(materialObject); // No use of phongE.whiteness and phongE.highlightSize babylonMaterial.specularPower = (1.0f - phongEShader.roughness) * 256; } else { RaiseWarning("Unknown reflect shader type: " + reflectShader.typeName + ". Specular power is default 64. Consider using a Blinn or Phong shader instead.", 2); } } // TODO //babylonMaterial.backFaceCulling = !stdMat.TwoSided; //babylonMaterial.wireframe = stdMat.Wire; // --- Textures --- babylonMaterial.diffuseTexture = ExportTexture(materialDependencyNode, "color", babylonScene); babylonMaterial.emissiveTexture = ExportTexture(materialDependencyNode, "ambientColor", babylonScene); // Maya ambient <=> babylon emissive babylonMaterial.bumpTexture = ExportTexture(materialDependencyNode, "normalCamera", babylonScene); babylonMaterial.opacityTexture = ExportTexture(materialDependencyNode, "transparency", babylonScene, false, true); if (materialObject.hasFn(MFn.Type.kReflect)) { babylonMaterial.specularTexture = ExportTexture(materialDependencyNode, "specularColor", babylonScene); babylonMaterial.reflectionTexture = ExportTexture(materialDependencyNode, "reflectedColor", babylonScene, true, false, true); } // 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 }; } babylonScene.MaterialsList.Add(babylonMaterial); } // Stingray PBS material else if (isStingrayPBSMaterial(materialDependencyNode)) { RaiseMessage("Stingray shader", 2); var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial { name = name, id = id }; // --- Global --- // Color3 babylonMaterial.baseColor = materialDependencyNode.findPlug("base_color").asFloatArray(); // Alpha string opacityAttributeName = "opacity"; if (materialDependencyNode.hasAttribute(opacityAttributeName)) { float opacityAttributeValue = materialDependencyNode.findPlug(opacityAttributeName).asFloatProperty; babylonMaterial.alpha = 1.0f - opacityAttributeValue; } // Metallic & roughness babylonMaterial.metallic = materialDependencyNode.findPlug("metallic").asFloatProperty; babylonMaterial.roughness = materialDependencyNode.findPlug("roughness").asFloatProperty; // Emissive float emissiveIntensity = materialDependencyNode.findPlug("emissive_intensity").asFloatProperty; // Factor emissive color with emissive intensity emissiveIntensity = Tools.Clamp(emissiveIntensity, 0f, 1f); babylonMaterial.emissive = materialDependencyNode.findPlug("emissive").asFloatArray().Multiply(emissiveIntensity); // --- Textures --- // Base color & alpha bool useColorMap = materialDependencyNode.findPlug("use_color_map").asBoolProperty; bool useOpacityMap = false; string useOpacityMapAttributeName = "use_opacity_map"; if (materialDependencyNode.hasAttribute(useOpacityMapAttributeName)) { useOpacityMap = materialDependencyNode.findPlug(useOpacityMapAttributeName).asBoolProperty; } if (useColorMap || useOpacityMap) { // TODO - Force non use map to default value ? // Ex: if useOpacityMap == false, force alpha = 255 for all pixels. //babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(materialDependencyNode, useColorMap, useOpacityMap, babylonMaterial.baseColor, babylonMaterial.alpha, babylonScene); babylonMaterial.baseTexture = ExportTexture(materialDependencyNode, "TEX_color_map", babylonScene, false, useOpacityMap); } // Metallic, roughness, ambient occlusion bool useMetallicMap = materialDependencyNode.findPlug("use_metallic_map").asBoolProperty; bool useRoughnessMap = materialDependencyNode.findPlug("use_roughness_map").asBoolProperty; string useAOMapAttributeName = "use_ao_map"; bool useAOMap = materialDependencyNode.hasAttribute(useAOMapAttributeName) && materialDependencyNode.findPlug(useAOMapAttributeName).asBoolProperty; MFnDependencyNode metallicTextureDependencyNode = useMetallicMap ? getTextureDependencyNode(materialDependencyNode, "TEX_metallic_map") : null; MFnDependencyNode roughnessTextureDependencyNode = useRoughnessMap ? getTextureDependencyNode(materialDependencyNode, "TEX_roughness_map") : null; MFnDependencyNode ambientOcclusionTextureDependencyNode = useAOMap ? getTextureDependencyNode(materialDependencyNode, "TEX_ao_map") : null; // Check if MR or ORM textures are already merged bool areTexturesAlreadyMerged = false; if (metallicTextureDependencyNode != null && roughnessTextureDependencyNode != null) { string sourcePathMetallic = getSourcePathFromFileTexture(metallicTextureDependencyNode); string sourcePathRoughness = getSourcePathFromFileTexture(roughnessTextureDependencyNode); if (sourcePathMetallic == sourcePathRoughness) { if (ambientOcclusionTextureDependencyNode != null) { string sourcePathAmbientOcclusion = getSourcePathFromFileTexture(ambientOcclusionTextureDependencyNode); if (sourcePathMetallic == sourcePathAmbientOcclusion) { // Metallic, roughness and ambient occlusion are already merged RaiseVerbose("Metallic, roughness and ambient occlusion are already merged", 2); BabylonTexture ormTexture = ExportTexture(metallicTextureDependencyNode, 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(metallicTextureDependencyNode, babylonScene); babylonMaterial.metallicRoughnessTexture = ormTexture; areTexturesAlreadyMerged = true; } } } if (areTexturesAlreadyMerged == false) { if (metallicTextureDependencyNode != null || roughnessTextureDependencyNode != null) { // Merge metallic, roughness and ambient occlusion RaiseVerbose("Merge metallic, roughness and ambient occlusion", 2); BabylonTexture ormTexture = ExportORMTexture(babylonScene, metallicTextureDependencyNode, roughnessTextureDependencyNode, ambientOcclusionTextureDependencyNode, babylonMaterial.metallic, babylonMaterial.roughness); babylonMaterial.metallicRoughnessTexture = ormTexture; if (ambientOcclusionTextureDependencyNode != null) { babylonMaterial.occlusionTexture = ormTexture; } } else if (ambientOcclusionTextureDependencyNode != null) { // Simply export occlusion texture RaiseVerbose("Simply export occlusion texture", 2); babylonMaterial.occlusionTexture = ExportTexture(ambientOcclusionTextureDependencyNode, babylonScene); } } // Normal if (materialDependencyNode.findPlug("use_normal_map").asBoolProperty) { babylonMaterial.normalTexture = ExportTexture(materialDependencyNode, "TEX_normal_map", babylonScene); } // Emissive bool useEmissiveMap = materialDependencyNode.findPlug("use_emissive_map").asBoolProperty; if (useEmissiveMap) { babylonMaterial.emissiveTexture = ExportTexture(materialDependencyNode, "TEX_emissive_map", babylonScene, false, false, false, emissiveIntensity); } // Constraints if (useColorMap) { babylonMaterial.baseColor = new[] { 1.0f, 1.0f, 1.0f }; } if (useOpacityMap) { babylonMaterial.alpha = 1.0f; } if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; } if (useMetallicMap) { babylonMaterial.metallic = 1.0f; } if (useRoughnessMap) { babylonMaterial.roughness = 1.0f; } if (useEmissiveMap) { babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f }; } babylonScene.MaterialsList.Add(babylonMaterial); } // Arnold Ai Standard Surface else if (isAiStandardSurface(materialDependencyNode)) { RaiseMessage("Ai Standard Surface shader", 2); var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial { name = name, id = id }; // --- Global --- // Color3 float baseWeight = materialDependencyNode.findPlug("base").asFloatProperty; float[] baseColor = materialDependencyNode.findPlug("baseColor").asFloatArray(); babylonMaterial.baseColor = baseColor.Multiply(baseWeight); // Alpha MaterialDuplicationData materialDuplicationData = materialDuplicationDatas[id]; // If at least one mesh is Transparent and is using this material either directly or as a sub material if (materialDuplicationData.isArnoldTransparent()) { float[] opacityAttributeValue = materialDependencyNode.findPlug("opacity").asFloatArray(); babylonMaterial.alpha = opacityAttributeValue[0]; } else { // Do not bother about alpha babylonMaterial.alpha = 1.0f; } // Metallic & roughness babylonMaterial.metallic = materialDependencyNode.findPlug("metalness").asFloatProperty; babylonMaterial.roughness = materialDependencyNode.findPlug("specularRoughness").asFloatProperty; // Emissive float emissionWeight = materialDependencyNode.findPlug("emission").asFloatProperty; babylonMaterial.emissive = materialDependencyNode.findPlug("emissionColor").asFloatArray().Multiply(emissionWeight); // --- Textures --- // Base color & alpha if (materialDuplicationData.isArnoldTransparent()) { MFnDependencyNode baseColorTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "baseColor"); MFnDependencyNode opacityTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "opacity"); if (baseColorTextureDependencyNode != null && opacityTextureDependencyNode != null && getSourcePathFromFileTexture(baseColorTextureDependencyNode) == getSourcePathFromFileTexture(opacityTextureDependencyNode)) { // If the same file is used for base color and opacity // Base color and alpha are already merged into a single file babylonMaterial.baseTexture = ExportTexture(baseColorTextureDependencyNode, babylonScene, false, true); } else { // Base color and alpha files need to be merged into a single file Color _baseColor = Color.FromArgb((int)baseColor[0] * 255, (int)baseColor[1] * 255, (int)baseColor[2] * 255); babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(baseColorTextureDependencyNode, opacityTextureDependencyNode, babylonScene, name, _baseColor, babylonMaterial.alpha); } } else { // Base color only // Do not bother about alpha babylonMaterial.baseTexture = ExportTexture(materialDependencyNode, "baseColor", babylonScene); } // Metallic & roughness MFnDependencyNode metallicTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "metalness"); MFnDependencyNode roughnessTextureDependencyNode = getTextureDependencyNode(materialDependencyNode, "specularRoughness"); if (metallicTextureDependencyNode != null && roughnessTextureDependencyNode != null && getSourcePathFromFileTexture(metallicTextureDependencyNode) == getSourcePathFromFileTexture(roughnessTextureDependencyNode)) { // If the same file is used for metallic and roughness // Then we assume it's an ORM file (Red=Occlusion, Green=Roughness, Blue=Metallic) // Metallic and roughness are already merged into a single file babylonMaterial.metallicRoughnessTexture = ExportTexture(metallicTextureDependencyNode, babylonScene); // Use same file for Ambient occlusion babylonMaterial.occlusionTexture = babylonMaterial.metallicRoughnessTexture; } else { // Metallic and roughness files need to be merged into a single file // Occlusion texture is not exported since aiStandardSurface material doesn't provide input for it babylonMaterial.metallicRoughnessTexture = ExportORMTexture(babylonScene, metallicTextureDependencyNode, roughnessTextureDependencyNode, null, babylonMaterial.metallic, babylonMaterial.roughness); } // Normal babylonMaterial.normalTexture = ExportTexture(materialDependencyNode, "normalCamera", babylonScene); // Emissive babylonMaterial.emissiveTexture = ExportTexture(materialDependencyNode, "emissionColor", babylonScene); // Constraints if (babylonMaterial.baseTexture != null) { babylonMaterial.baseColor = new[] { baseWeight, baseWeight, baseWeight }; babylonMaterial.alpha = 1.0f; } if (babylonMaterial.metallicRoughnessTexture != null) { babylonMaterial.metallic = 1.0f; babylonMaterial.roughness = 1.0f; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new[] { emissionWeight, emissionWeight, emissionWeight }; } // If this material is containing alpha data if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND; // If this material is assigned to both Transparent and Opaque meshes (either directly or as a sub material) if (materialDuplicationData.isDuplicationRequired()) { // Duplicate material BabylonPBRMetallicRoughnessMaterial babylonMaterialCloned = DuplicateMaterial(babylonMaterial, materialDuplicationData); // Store duplicated material too babylonScene.MaterialsList.Add(babylonMaterialCloned); } } babylonScene.MaterialsList.Add(babylonMaterial); } else { RaiseWarning("Unsupported material type '" + materialObject.apiType + "' for material named '" + materialDependencyNode.name + "'", 2); } }
/// <summary> /// /// </summary> /// <param name="mDagPath">DAG path to the transform above light</param> /// <param name="babylonScene"></param> /// <returns></returns> private BabylonNode ExportLight(MDagPath mDagPath, BabylonScene babylonScene) { RaiseMessage(mDagPath.partialPathName, 1); // Transform above light MFnTransform mFnTransform = new MFnTransform(mDagPath); // Light direct child of the transform MFnLight mFnLight = null; for (uint i = 0; i < mFnTransform.childCount; i++) { MObject childObject = mFnTransform.child(i); if (childObject.hasFn(MFn.Type.kLight)) { mFnLight = new MFnLight(childObject); } } if (mFnLight == null) { RaiseError("No light found has child of " + mDagPath.fullPathName); return(null); } RaiseMessage("mFnLight.fullPathName=" + mFnLight.fullPathName, 2); // --- prints --- #region prints // MFnLight RaiseVerbose("BabylonExporter.Light | mFnLight data", 2); RaiseVerbose("BabylonExporter.Light | mFnLight.color.toString()=" + mFnLight.color.toString(), 3); RaiseVerbose("BabylonExporter.Light | mFnLight.intensity=" + mFnLight.intensity, 3); RaiseVerbose("BabylonExporter.Light | mFnLight.useRayTraceShadows=" + mFnLight.useRayTraceShadows, 3); RaiseVerbose("BabylonExporter.Light | mFnLight.shadowColor.toString()=" + mFnLight.shadowColor.toString(), 3); RaiseVerbose("BabylonExporter.Light | mFnLight.centerOfIllumination=" + mFnLight.centerOfIllumination, 3); RaiseVerbose("BabylonExporter.Light | mFnLight.numShadowSamples=" + mFnLight.numShadowSamples, 3); RaiseVerbose("BabylonExporter.Light | mFnLight.rayDepthLimit=" + mFnLight.rayDepthLimit, 3); RaiseVerbose("BabylonExporter.Light | mFnLight.opticalFXvisibility.toString()=" + mFnLight.opticalFXvisibility.toString(), 3); RaiseVerbose("BabylonExporter.Light | mFnLight.lightIntensity.toString()=" + mFnLight.lightIntensity.toString(), 3); RaiseVerbose("BabylonExporter.Light | mFnLight.instanceCount(true)=" + mFnLight.instanceCount(true), 3); RaiseVerbose("BabylonExporter.Light | mFnLight.lightDirection(0).toString()=" + mFnLight.lightDirection(0).toString(), 3); RaiseVerbose("BabylonExporter.Light | mFnLight.lightAmbient=" + mFnLight.lightAmbient, 3); RaiseVerbose("BabylonExporter.Light | mFnLight.lightDiffuse=" + mFnLight.lightDiffuse, 3); RaiseVerbose("BabylonExporter.Light | mFnLight.lightSpecular=" + mFnLight.lightSpecular, 3); switch (mFnLight.objectProperty.apiType) { case MFn.Type.kSpotLight: MFnSpotLight mFnSpotLight = new MFnSpotLight(mFnLight.objectProperty); // MFnNonAmbientLight RaiseVerbose("BabylonExporter.Light | mFnSpotLight.decayRate=" + mFnSpotLight.decayRate, 3); // dropdown enum value // MFnNonExtendedLight RaiseVerbose("BabylonExporter.Light | mFnSpotLight.shadowRadius=" + mFnSpotLight.shadowRadius, 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.castSoftShadows=" + mFnSpotLight.castSoftShadows, 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.useDepthMapShadows=" + mFnSpotLight.useDepthMapShadows, 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.depthMapFilterSize()=" + mFnSpotLight.depthMapFilterSize(), 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.depthMapResolution()=" + mFnSpotLight.depthMapResolution(), 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.depthMapBias()=" + mFnSpotLight.depthMapBias(), 3); // MFnSpotLight RaiseVerbose("BabylonExporter.Light | mFnSpotLight.coneAngle=" + mFnSpotLight.coneAngle, 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.penumbraAngle=" + mFnSpotLight.penumbraAngle, 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.dropOff=" + mFnSpotLight.dropOff, 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.barnDoors=" + mFnSpotLight.barnDoors, 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.useDecayRegions=" + mFnSpotLight.useDecayRegions, 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.startDistance(MFnSpotLight.MDecayRegion.kFirst)=" + mFnSpotLight.startDistance(MFnSpotLight.MDecayRegion.kFirst), 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.endDistance(MFnSpotLight.MDecayRegion.kFirst)=" + mFnSpotLight.endDistance(MFnSpotLight.MDecayRegion.kFirst), 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.startDistance(MFnSpotLight.MDecayRegion.kSecond)=" + mFnSpotLight.startDistance(MFnSpotLight.MDecayRegion.kSecond), 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.endDistance(MFnSpotLight.MDecayRegion.kSecond)=" + mFnSpotLight.endDistance(MFnSpotLight.MDecayRegion.kSecond), 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.startDistance(MFnSpotLight.MDecayRegion.kThird)=" + mFnSpotLight.startDistance(MFnSpotLight.MDecayRegion.kThird), 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.endDistance(MFnSpotLight.MDecayRegion.kThird)=" + mFnSpotLight.endDistance(MFnSpotLight.MDecayRegion.kThird), 3); break; } #endregion if (IsLightExportable(mFnLight, mDagPath) == false) { return(null); } var babylonLight = new BabylonLight { name = mFnTransform.name, id = mFnTransform.uuid().asString() }; // Hierarchy ExportHierarchy(babylonLight, mFnTransform); // Position RaiseVerbose("BabylonExporter.Light | ExportTransform", 2); float[] position = null; GetTransform(mFnTransform, ref position); babylonLight.position = position; // Direction var vDir = new MVector(0, 0, -1); var transformationMatrix = new MTransformationMatrix(mFnTransform.transformationMatrix); vDir = vDir.multiply(transformationMatrix.asMatrixProperty); vDir.normalize(); babylonLight.direction = new[] { (float)vDir.x, (float)vDir.y, -(float)vDir.z }; // Common fields babylonLight.intensity = mFnLight.intensity; babylonLight.diffuse = mFnLight.lightDiffuse ? mFnLight.color.toArrayRGB() : new float[] { 0, 0, 0 }; babylonLight.specular = mFnLight.lightSpecular ? mFnLight.color.toArrayRGB() : new float[] { 0, 0, 0 }; // Type switch (mFnLight.objectProperty.apiType) { case MFn.Type.kPointLight: babylonLight.type = 0; break; case MFn.Type.kSpotLight: MFnSpotLight mFnSpotLight = new MFnSpotLight(mFnLight.objectProperty); babylonLight.type = 2; babylonLight.angle = (float)mFnSpotLight.coneAngle; babylonLight.exponent = 1; if (mFnSpotLight.useDecayRegions) { babylonLight.range = mFnSpotLight.endDistance(MFnSpotLight.MDecayRegion.kThird); // Max distance } break; case MFn.Type.kDirectionalLight: babylonLight.type = 1; break; case MFn.Type.kAmbientLight: babylonLight.type = 3; babylonLight.groundColor = new float[] { 0, 0, 0 }; break; case MFn.Type.kAreaLight: case MFn.Type.kVolumeLight: RaiseError("Unsupported light type '" + mFnLight.objectProperty.apiType + "' for DAG path '" + mFnLight.fullPathName + "'. Light is ignored. Supported light types are: ambient, directional, point and spot."); return(null); default: RaiseWarning("Unknown light type '" + mFnLight.objectProperty.apiType + "' for DAG path '" + mFnLight.fullPathName + "'. Light is ignored."); return(null); } // TODO - Shadows // TODO - Exclusion // TODO - Animations babylonScene.LightsList.Add(babylonLight); return(babylonLight); }
private bool shouldPruneLight( MObject obj ) { return !(obj.hasFn(MFn.Type.kAmbientLight) || obj.hasFn(MFn.Type.kDirectionalLight) || obj.hasFn(MFn.Type.kPointLight) || obj.hasFn(MFn.Type.kSpotLight)); }
private void buildLightNodes() { MItDependencyNodes it = new MItDependencyNodes(MFn.Type.kLight); while (!it.isDone) { MObject mayaObj = it.thisNode; if (shouldPruneLight(mayaObj)) { it.next(); continue; } // Create a new light and add it to the all lights list. MayaLight light = new MayaLight(); allLights.Add(light); light.id = allLights.Count - 1; // Get the dag node of the light for its name and parent. MFnDagNode dagNode = new MFnDagNode(mayaObj); dagNode.getPath(light.mayaObjectPath); light.name = dagNode.fullPathName; // First parent is the source transform node. light.sourceXform = pathXformMap[(new MFnDagNode(dagNode.parent(0))).fullPathName]; // Add the light to the dictionary to search by name. pathLightMap[light.name] = light; // // NOTE: Parent transforms of light sources in Maya can NOT be frozen, // so accessing them is guaranteed to not be frozen. // if (mayaObj.hasFn(MFn.Type.kAmbientLight)) { MFnAmbientLight mayaLight = new MFnAmbientLight(mayaObj); light.type = MayaLight.Type.kAmbient; light.color = new Color(mayaLight.color.r, mayaLight.color.g, mayaLight.color.b, mayaLight.color.a); light.intensity = mayaLight.intensity; } else if (mayaObj.hasFn(MFn.Type.kDirectionalLight)) { MFnDirectionalLight mayaLight = new MFnDirectionalLight(mayaObj); light.type = MayaLight.Type.kDirectional; light.color = new Color(mayaLight.color.r, mayaLight.color.g, mayaLight.color.b, mayaLight.color.a); light.intensity = mayaLight.intensity; } else if (mayaObj.hasFn(MFn.Type.kPointLight)) { MFnPointLight mayaLight = new MFnPointLight(mayaObj); light.type = MayaLight.Type.kPoint; light.color = new Color(mayaLight.color.r, mayaLight.color.g, mayaLight.color.b, mayaLight.color.a); light.intensity = mayaLight.intensity; light.range = (float)mayaLight.centerOfIllumination; } else if (mayaObj.hasFn(MFn.Type.kSpotLight)) { MFnSpotLight mayaLight = new MFnSpotLight(mayaObj); light.type = MayaLight.Type.kSpot; light.color = new Color(mayaLight.color.r, mayaLight.color.g, mayaLight.color.b, mayaLight.color.a); light.intensity = mayaLight.intensity; light.range = (float)mayaLight.centerOfIllumination; float mayaConeAngle = (float)(mayaLight.coneAngle * 0.5); light.coneInnerAngle = 57.29578f * mayaConeAngle; light.coneOuterAngle = 57.29578f * (mayaConeAngle + Math.Abs((float)mayaLight.penumbraAngle)); } it.next(); } }
private bool shouldPruneLight(MObject obj) { return(!(obj.hasFn(MFn.Type.kAmbientLight) || obj.hasFn(MFn.Type.kDirectionalLight) || obj.hasFn(MFn.Type.kPointLight) || obj.hasFn(MFn.Type.kSpotLight))); }
public static void updateManipulators(RotateManipContext ctx) { if (ctx == null) { return; } ctx.deleteManipulators(); // Add the rotate manipulator to each selected object. This produces // behavior different from the default rotate manipulator behavior. Here, // a distinct rotate manipulator is attached to every object. // try { MSelectionList list = MGlobal.activeSelectionList; MItSelectionList iter = new MItSelectionList(list, MFn.Type.kInvalid); for (; !iter.isDone; iter.next()) { // Make sure the selection list item is a depend node and has the // required plugs before manipulating it. // MObject dependNode = new MObject(); iter.getDependNode(dependNode); if (dependNode.isNull || !dependNode.hasFn(MFn.Type.kDependencyNode)) { MGlobal.displayWarning("Object in selection list is not a depend node."); continue; } MFnDependencyNode dependNodeFn = new MFnDependencyNode(dependNode); try { /* MPlug rPlug = */ dependNodeFn.findPlug("rotate"); } catch (System.Exception) { MGlobal.displayWarning("Object cannot be manipulated: " + dependNodeFn.name); continue; } // Add manipulator to the selected object // MObject manipObject = new MObject(); exampleRotateManip manipulator; try { manipulator = exampleRotateManip.newManipulator("exampleRotateManipCSharp", manipObject) as exampleRotateManip; // Add the manipulator // ctx.addManipulator(manipObject); // Connect the manipulator to the object in the selection list. // try { manipulator.connectToDependNode(dependNode); } catch (System.Exception) { MGlobal.displayWarning("Error connecting manipulator to object: " + dependNodeFn.name); } } catch (System.Exception) { } } } catch (System.Exception) { } }
private MFnDependencyNode getTextureDependencyNode(MFnDependencyNode materialDependencyNode, string plugName, List <MFnDependencyNode> textureModifiers = null) { MPlug mPlug = materialDependencyNode.findPlug(plugName); if (mPlug == null || mPlug.isNull || !mPlug.isConnected) { // a compound plug connected to a non-compound plug may not be marked as connected, try to get a child plug: if (mPlug.isCompound) { // Retrieve the first non-empty plug and use the texture connected to it. for (uint i = 0; i < mPlug.numChildren; i++) { MPlug child = mPlug.child(i); if (child == null || child.isNull || !child.isConnected) { continue; } mPlug = child; break; } } if (mPlug == null || mPlug.isNull || !mPlug.isConnected) { return(null); } } MObject sourceObject = mPlug.source.node; MFnDependencyNode textureDependencyNode = new MFnDependencyNode(sourceObject); RaiseMessage(materialDependencyNode.name + "." + plugName, logRankTexture); // Bump texture uses an intermediate node if (sourceObject.hasFn(MFn.Type.kBump)) { Print(textureDependencyNode, logRankTexture, "Print bump node"); logRankTexture++; if (textureModifiers != null) { textureModifiers.Add(textureDependencyNode); } return(getTextureDependencyNode(textureDependencyNode, "bumpValue", textureModifiers)); } // If a reverse node is used as an intermediate node if (sourceObject.hasFn(MFn.Type.kReverse)) { Print(textureDependencyNode, logRankTexture, "Print reverse node"); // TODO - reverse? logRankTexture++; if (textureModifiers != null) { textureModifiers.Add(textureDependencyNode); } return(getTextureDependencyNode(textureDependencyNode, "input", textureModifiers)); } // If a projection node is used as an intermediate node if (sourceObject.hasFn(MFn.Type.kProjection)) { Print(textureDependencyNode, logRankTexture, "Print projection node"); logRankTexture++; if (textureModifiers != null) { textureModifiers.Add(textureDependencyNode); } return(getTextureDependencyNode(textureDependencyNode, "image", textureModifiers)); } return(textureDependencyNode); }
//====================================================================== // // Do the metadata creation. The metadata will be randomly initialized // based on the channel type and the structure specified. For recognized // components the number of metadata elements will correspond to the count // of components in the selected mesh, otherwise a random number of metadata // elements between 1 and 100 will be created (at consecutive indices). // // The previously existing metadata is preserved for later undo. // override public void doIt(MArgList args) { MArgDatabase argsDb = new MArgDatabase(syntax, args); checkArgs(ref argsDb); clearResult(); uint numNodes = fNodes.length; int i; for (i = 0; i < numNodes; ++i) { // fNodes[i] is the transform not the shape itself MFnDagNode dagNode = new MFnDagNode(fNodes[i]); MObject obj = dagNode.child(0); // obj is the shape, which is where we can add the meta data MFnDependencyNode node = new MFnDependencyNode(obj); // Get the current metadata (empty if none yet) Associations newMetadata = new Associations(node.metadata); Channel newChannel = newMetadata.channel(fChannelType); // Check to see if the requested stream name already exists Stream oldStream = newChannel.dataStream(fStreamName); if (oldStream != null) { string fmt = MStringResource.getString(MetaDataRegisterMStringResources.kCreateMetadataHasStream); string msg = String.Format(fmt, fStreamName); MGlobal.displayError(msg); continue; } Stream newStream = new Stream(fStructure, fStreamName); string strmName = newStream.name; int indexCount = 0; MFnMesh mesh = null; Random rndIndexCount = new Random(); // Treat the channel type initializations different for meshes if (obj.hasFn(MFn.Type.kMesh)) { mesh = new MFnMesh(obj); // Get mesh-specific channel type parameters if (fChannelType == "face") { indexCount = mesh.numPolygons; } else if (fChannelType == "edge") { indexCount = mesh.numEdges; } else if (fChannelType == "vertex") { indexCount = mesh.numVertices; } else if (fChannelType == "vertexFace") { indexCount = mesh.numFaceVertices; } else { // Set a random number between 1 to 100 indexCount = rndIndexCount.Next(1, 100); } } else { // Create generic channel type information indexCount = rndIndexCount.Next(1, 100); } // Fill specified stream ranges with random data int structureMemberCount = fStructure.memberCount; uint m, n, d; Random rnd = new Random(); for (m = 0; m < indexCount; ++m) { // Walk each structure member and fill with random data // tailored to the member data type. Handle handle = new Handle(fStructure); for (n = 0; n < structureMemberCount; ++n) { handle.setPositionByMemberIndex(n); switch (handle.dataType) { case Member.eDataType.kBoolean: { bool[] data = new bool[handle.dataLength]; for (d = 0; d < handle.dataLength; ++d) { int randomInt = rnd.Next(0, 2); bool randomBool = randomInt == 1 ? true : false; data[d] = randomBool; } handle.asBooleanArray = data; break; } case Member.eDataType.kDouble: { double[] data = new double[handle.dataLength]; for (d = 0; d < handle.dataLength; ++d) { // Set a random number between -2000000000.0.0 and 2000000000.0.0 data[d] = rnd.NextDouble() * 4000000000.0 - 2000000000.0; } handle.asDoubleArray = data; break; } case Member.eDataType.kDoubleMatrix4x4: { double[] data = new double[handle.dataLength * 16]; for (d = 0; d < handle.dataLength; ++d) { data[d * 16 + 0] = rnd.NextDouble() * 4000000000.0 - 2000000000.0; data[d * 16 + 1] = rnd.NextDouble() * 4000000000.0 - 2000000000.0; data[d * 16 + 2] = rnd.NextDouble() * 4000000000.0 - 2000000000.0; data[d * 16 + 3] = rnd.NextDouble() * 4000000000.0 - 2000000000.0; data[d * 16 + 4] = rnd.NextDouble() * 4000000000.0 - 2000000000.0; data[d * 16 + 5] = rnd.NextDouble() * 4000000000.0 - 2000000000.0; data[d * 16 + 6] = rnd.NextDouble() * 4000000000.0 - 2000000000.0; data[d * 16 + 7] = rnd.NextDouble() * 4000000000.0 - 2000000000.0; data[d * 16 + 8] = rnd.NextDouble() * 4000000000.0 - 2000000000.0; data[d * 16 + 9] = rnd.NextDouble() * 4000000000.0 - 2000000000.0; data[d * 16 + 10] = rnd.NextDouble() * 4000000000.0 - 2000000000.0; data[d * 16 + 11] = rnd.NextDouble() * 4000000000.0 - 2000000000.0; data[d * 16 + 12] = rnd.NextDouble() * 4000000000.0 - 2000000000.0; data[d * 16 + 13] = rnd.NextDouble() * 4000000000.0 - 2000000000.0; data[d * 16 + 14] = rnd.NextDouble() * 4000000000.0 - 2000000000.0; data[d * 16 + 15] = rnd.NextDouble() * 4000000000.0 - 2000000000.0; } handle.asDoubleMatrix4x4 = data; break; } case Member.eDataType.kFloat: { float[] data = new float[handle.dataLength]; for (d = 0; d < handle.dataLength; ++d) { // Set a random number between -2000000.0 and 2000000.0 data[d] = (float)rnd.NextDouble() * 4000000.0f - 2000000.0f; } handle.asFloatArray = data; break; } case Member.eDataType.kFloatMatrix4x4: { float[] data = new float[handle.dataLength * 16]; for (d = 0; d < handle.dataLength; ++d) { // Set a random number between -2000000.0 and 2000000.0 data[d * 16 + 0] = (float)rnd.NextDouble() * 4000000.0f - 2000000.0f; data[d * 16 + 1] = (float)rnd.NextDouble() * 4000000.0f - 2000000.0f; data[d * 16 + 2] = (float)rnd.NextDouble() * 4000000.0f - 2000000.0f; data[d * 16 + 3] = (float)rnd.NextDouble() * 4000000.0f - 2000000.0f; data[d * 16 + 4] = (float)rnd.NextDouble() * 4000000.0f - 2000000.0f; data[d * 16 + 5] = (float)rnd.NextDouble() * 4000000.0f - 2000000.0f; data[d * 16 + 6] = (float)rnd.NextDouble() * 4000000.0f - 2000000.0f; data[d * 16 + 7] = (float)rnd.NextDouble() * 4000000.0f - 2000000.0f; data[d * 16 + 8] = (float)rnd.NextDouble() * 4000000.0f - 2000000.0f; data[d * 16 + 9] = (float)rnd.NextDouble() * 4000000.0f - 2000000.0f; data[d * 16 + 10] = (float)rnd.NextDouble() * 4000000.0f - 2000000.0f; data[d * 16 + 11] = (float)rnd.NextDouble() * 4000000.0f - 2000000.0f; data[d * 16 + 12] = (float)rnd.NextDouble() * 4000000.0f - 2000000.0f; data[d * 16 + 13] = (float)rnd.NextDouble() * 4000000.0f - 2000000.0f; data[d * 16 + 14] = (float)rnd.NextDouble() * 4000000.0f - 2000000.0f; data[d * 16 + 15] = (float)rnd.NextDouble() * 4000000.0f - 2000000.0f; } handle.asFloatMatrix4x4 = data; break; } case Member.eDataType.kInt8: { sbyte[] data = new sbyte[handle.dataLength]; for (d = 0; d < handle.dataLength; ++d) { data[d] = (sbyte)rnd.Next(SByte.MinValue, SByte.MaxValue + 1); } handle.asInt8Array = data; break; } case Member.eDataType.kInt16: { short[] data = new short[handle.dataLength]; for (d = 0; d < handle.dataLength; ++d) { data[d] = (short)rnd.Next(Int16.MinValue, Int16.MaxValue + 1); } handle.asInt16Array = data; break; } case Member.eDataType.kInt32: { int[] data = new int[handle.dataLength]; for (d = 0; d < handle.dataLength; ++d) { // rnd.Next returns a number between [arg1,arg2[ // but unfortunately I can't pass Int32.MaxValue+1 here.... data[d] = rnd.Next(Int32.MinValue, Int32.MaxValue); } handle.asInt32Array = data; break; } case Member.eDataType.kInt64: { long[] data = new long[handle.dataLength]; for (d = 0; d < handle.dataLength; ++d) { // rnd.Next() gives a number between [0,Int32 data[d] = (long)rnd.Next(Int32.MinValue, Int32.MaxValue); if (data[d] >= 0) { data[d] *= Int64.MaxValue / Int32.MaxValue; } else { data[d] *= Int64.MinValue / Int32.MinValue; } } handle.asInt64Array = data; break; } case Member.eDataType.kUInt8: { byte[] data = new byte[handle.dataLength]; for (d = 0; d < handle.dataLength; ++d) { data[d] = (byte)rnd.Next(0, Byte.MaxValue + 1); } handle.asUInt8Array = data; break; } case Member.eDataType.kUInt16: { ushort[] data = new ushort[handle.dataLength]; for (d = 0; d < handle.dataLength; ++d) { data[d] = (ushort)rnd.Next(0, UInt16.MaxValue + 1); } handle.asUInt16Array = data; break; } case Member.eDataType.kUInt32: { uint[] data = new uint[handle.dataLength]; for (d = 0; d < handle.dataLength; ++d) { data[d] = (uint)rnd.Next(); } handle.asUInt32Array = data; break; } case Member.eDataType.kUInt64: { ulong[] data = new ulong[handle.dataLength]; for (d = 0; d < handle.dataLength; ++d) { data[d] = ((ulong)rnd.Next()) * UInt64.MaxValue / UInt32.MaxValue; } handle.asUInt64Array = data; break; } case Member.eDataType.kString: { string[] randomStrings = new string[] { "banana", "tomatoe", "apple", "pineapple", "apricot", "pepper", "olive", "grapefruit" }; string[] data = new string[handle.dataLength]; for (d = 0; d < handle.dataLength; ++d) { int index = rnd.Next(randomStrings.Length); data[d] = randomStrings[index]; } handle.asStringArray = data; break; } default: { Debug.Assert(false, "This should never happen"); break; } } } newStream.setElement(new Index(m), handle); } newChannel.setDataStream(newStream); newMetadata.setChannel(newChannel); // Note: the following will not work if "obj" is a shape constructed by a source object // You need to delete the history of the shape before calling this... fDGModifier.setMetadata(obj, newMetadata); fDGModifier.doIt(); // Set the result to the number of actual metadata values set as a // triple value: // (# nodes, # metadata elements, # members per element) // MIntArray theResult = new MIntArray(); theResult.append((int)fNodes.length); theResult.append((int)indexCount); theResult.append((int)structureMemberCount); setResult(theResult); } }
/// <summary> /// /// </summary> /// <param name="mDagPath">DAG path to the transform above light</param> /// <param name="babylonScene"></param> /// <returns></returns> private BabylonNode ExportLight(MDagPath mDagPath, BabylonScene babylonScene) { RaiseMessage(mDagPath.partialPathName, 1); // Transform above light MFnTransform mFnTransform = new MFnTransform(mDagPath); // Light direct child of the transform MFnLight mFnLight = null; for (uint i = 0; i < mFnTransform.childCount; i++) { MObject childObject = mFnTransform.child(i); if (childObject.hasFn(MFn.Type.kLight)) { var _mFnLight = new MFnLight(childObject); if (!_mFnLight.isIntermediateObject) { mFnLight = _mFnLight; } } } if (mFnLight == null) { RaiseError("No light found has child of " + mDagPath.fullPathName); return(null); } RaiseMessage("mFnLight.fullPathName=" + mFnLight.fullPathName, 2); // --- prints --- #region prints // MFnLight RaiseVerbose("BabylonExporter.Light | mFnLight data", 2); RaiseVerbose("BabylonExporter.Light | mFnLight.color.toString()=" + mFnLight.color.toString(), 3); RaiseVerbose("BabylonExporter.Light | mFnLight.intensity=" + mFnLight.intensity, 3); RaiseVerbose("BabylonExporter.Light | mFnLight.useRayTraceShadows=" + mFnLight.useRayTraceShadows, 3); RaiseVerbose("BabylonExporter.Light | mFnLight.shadowColor.toString()=" + mFnLight.shadowColor.toString(), 3); RaiseVerbose("BabylonExporter.Light | mFnLight.centerOfIllumination=" + mFnLight.centerOfIllumination, 3); RaiseVerbose("BabylonExporter.Light | mFnLight.numShadowSamples=" + mFnLight.numShadowSamples, 3); RaiseVerbose("BabylonExporter.Light | mFnLight.rayDepthLimit=" + mFnLight.rayDepthLimit, 3); RaiseVerbose("BabylonExporter.Light | mFnLight.opticalFXvisibility.toString()=" + mFnLight.opticalFXvisibility.toString(), 3); RaiseVerbose("BabylonExporter.Light | mFnLight.lightIntensity.toString()=" + mFnLight.lightIntensity.toString(), 3); RaiseVerbose("BabylonExporter.Light | mFnLight.instanceCount(true)=" + mFnLight.instanceCount(true), 3); RaiseVerbose("BabylonExporter.Light | mFnLight.lightDirection(0).toString()=" + mFnLight.lightDirection(0).toString(), 3); RaiseVerbose("BabylonExporter.Light | mFnLight.lightAmbient=" + mFnLight.lightAmbient, 3); RaiseVerbose("BabylonExporter.Light | mFnLight.lightDiffuse=" + mFnLight.lightDiffuse, 3); RaiseVerbose("BabylonExporter.Light | mFnLight.lightSpecular=" + mFnLight.lightSpecular, 3); switch (mFnLight.objectProperty.apiType) { case MFn.Type.kSpotLight: MFnSpotLight mFnSpotLight = new MFnSpotLight(mFnLight.objectProperty); // MFnNonAmbientLight RaiseVerbose("BabylonExporter.Light | mFnSpotLight.decayRate=" + mFnSpotLight.decayRate, 3); // dropdown enum value // MFnNonExtendedLight RaiseVerbose("BabylonExporter.Light | mFnSpotLight.shadowRadius=" + mFnSpotLight.shadowRadius, 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.castSoftShadows=" + mFnSpotLight.castSoftShadows, 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.useDepthMapShadows=" + mFnSpotLight.useDepthMapShadows, 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.depthMapFilterSize()=" + mFnSpotLight.depthMapFilterSize(), 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.depthMapResolution()=" + mFnSpotLight.depthMapResolution(), 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.depthMapBias()=" + mFnSpotLight.depthMapBias(), 3); // MFnSpotLight RaiseVerbose("BabylonExporter.Light | mFnSpotLight.coneAngle=" + mFnSpotLight.coneAngle, 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.penumbraAngle=" + mFnSpotLight.penumbraAngle, 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.dropOff=" + mFnSpotLight.dropOff, 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.barnDoors=" + mFnSpotLight.barnDoors, 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.useDecayRegions=" + mFnSpotLight.useDecayRegions, 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.startDistance(MFnSpotLight.MDecayRegion.kFirst)=" + mFnSpotLight.startDistance(MFnSpotLight.MDecayRegion.kFirst), 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.endDistance(MFnSpotLight.MDecayRegion.kFirst)=" + mFnSpotLight.endDistance(MFnSpotLight.MDecayRegion.kFirst), 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.startDistance(MFnSpotLight.MDecayRegion.kSecond)=" + mFnSpotLight.startDistance(MFnSpotLight.MDecayRegion.kSecond), 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.endDistance(MFnSpotLight.MDecayRegion.kSecond)=" + mFnSpotLight.endDistance(MFnSpotLight.MDecayRegion.kSecond), 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.startDistance(MFnSpotLight.MDecayRegion.kThird)=" + mFnSpotLight.startDistance(MFnSpotLight.MDecayRegion.kThird), 3); RaiseVerbose("BabylonExporter.Light | mFnSpotLight.endDistance(MFnSpotLight.MDecayRegion.kThird)=" + mFnSpotLight.endDistance(MFnSpotLight.MDecayRegion.kThird), 3); break; } Print(mFnTransform, 2, "Print ExportLight mFnTransform"); Print(mFnLight, 2, "Print ExportLight mFnLight"); #endregion if (IsLightExportable(mFnLight, mDagPath) == false) { return(null); } var babylonLight = new BabylonLight { name = mFnTransform.name, id = mFnTransform.uuid().asString() }; // Hierarchy ExportHierarchy(babylonLight, mFnTransform); // User custom attributes babylonLight.metadata = ExportCustomAttributeFromTransform(mFnTransform); // Position / rotation / scaling ExportTransform(babylonLight, mFnTransform); // Direction var vDir = new MVector(0, 0, -1); var transformationMatrix = new MTransformationMatrix(mFnTransform.transformationMatrix); vDir = vDir.multiply(transformationMatrix.asMatrixProperty); vDir.normalize(); babylonLight.direction = new[] { (float)vDir.x, (float)vDir.y, -(float)vDir.z }; // Common fields babylonLight.intensity = mFnLight.intensity; babylonLight.diffuse = mFnLight.lightDiffuse ? mFnLight.color.toArrayRGB() : new float[] { 0, 0, 0 }; babylonLight.specular = mFnLight.lightSpecular ? mFnLight.color.toArrayRGB() : new float[] { 0, 0, 0 }; // Type switch (mFnLight.objectProperty.apiType) { case MFn.Type.kPointLight: babylonLight.type = 0; break; case MFn.Type.kSpotLight: MFnSpotLight mFnSpotLight = new MFnSpotLight(mFnLight.objectProperty); babylonLight.type = 2; babylonLight.angle = (float)mFnSpotLight.coneAngle; babylonLight.exponent = 1; if (mFnSpotLight.useDecayRegions) { babylonLight.range = mFnSpotLight.endDistance(MFnSpotLight.MDecayRegion.kThird); // Max distance } break; case MFn.Type.kDirectionalLight: babylonLight.type = 1; break; case MFn.Type.kAmbientLight: babylonLight.type = 3; babylonLight.groundColor = new float[] { 0, 0, 0 }; // No emit diffuse /specular checkbox for ambient light babylonLight.diffuse = mFnLight.color.toArrayRGB(); babylonLight.specular = babylonLight.diffuse; // Direction vDir = new MVector(0, 1, 0); transformationMatrix = new MTransformationMatrix(mFnTransform.transformationMatrix); vDir = vDir.multiply(transformationMatrix.asMatrixProperty); vDir.normalize(); babylonLight.direction = new[] { (float)vDir.x, (float)vDir.y, -(float)vDir.z }; break; case MFn.Type.kAreaLight: case MFn.Type.kVolumeLight: RaiseError("Unsupported light type '" + mFnLight.objectProperty.apiType + "' for DAG path '" + mFnLight.fullPathName + "'. Light is ignored. Supported light types are: ambient, directional, point and spot.", 1); return(null); default: RaiseWarning("Unknown light type '" + mFnLight.objectProperty.apiType + "' for DAG path '" + mFnLight.fullPathName + "'. Light is ignored.", 1); return(null); } // TODO - Shadows //Variable declaration MStringArray enlightedMeshesFullPathNames = new MStringArray(); List <string> includeMeshesIds = new List <string>(); MStringArray kTransMesh = new MStringArray(); String typeMesh = null; MStringArray UUIDMesh = new MStringArray(); //MEL Command that get the enlighted mesh for a given light MGlobal.executeCommand($@"lightlink -query -light {mFnTransform.fullPathName};", enlightedMeshesFullPathNames); //For each enlighted mesh foreach (String Mesh in enlightedMeshesFullPathNames) { //MEL Command use to get the type of each mesh typeMesh = MGlobal.executeCommandStringResult($@"nodeType -api {Mesh};"); //We are targeting the type kMesh and not kTransform (for parenting) if (typeMesh == "kMesh") { MGlobal.executeCommand($@"listRelatives -parent -fullPath {Mesh};", kTransMesh); //And finally the MEL Command for the uuid of each mesh MGlobal.executeCommand($@"ls -uuid {kTransMesh[0]};", UUIDMesh); includeMeshesIds.Add(UUIDMesh[0]); } } babylonLight.includedOnlyMeshesIds = includeMeshesIds.ToArray(); // Animations if (exportParameters.bakeAnimationFrames) { ExportNodeAnimationFrameByFrame(babylonLight, mFnTransform); } else { ExportNodeAnimation(babylonLight, mFnTransform); } babylonScene.LightsList.Add(babylonLight); return(babylonLight); }
public override bool shouldBeUsedFor(MObject sourceNode, MObject destinationNode, MPlug sourcePlug, MPlug destinationPlug) { bool result = false; if(sourceNode.hasFn(MFn.Type.kLambert)) { //if the source node was a lambert //than we will check the downstream connections to see //if a slope shader is assigned to it. // MObject shaderNode = new MObject(); MFnDependencyNode src = new MFnDependencyNode(sourceNode); MPlugArray connections = new MPlugArray(); src.getConnections(connections); for(int i = 0; i < connections.length; i++) { //check the incoming connections to this plug // MPlugArray connectedPlugs = new MPlugArray(); connections[i].connectedTo(connectedPlugs, true, false); for(int j = 0; j < connectedPlugs.length; j++) { //if the incoming node is a slope shader than //set shaderNode equal to it and break out of the inner //loop // if(new MFnDependencyNode(connectedPlugs[j].node).typeName == "slopeShaderNodeCSharp") { shaderNode = connectedPlugs[j].node; break; } } //if the shaderNode is not null //than we have found a slopeShaderNodeCSharp // if(!shaderNode.isNull) { //if the destination node is a mesh than we will take //care of this connection so set the result to true //and break out of the outer loop // if(destinationNode.hasFn(MFn.Type.kMesh)) result = true; break; } } } if (new MFnDependencyNode(sourceNode).typeName == "slopeShaderNodeCSharp") //if the sourceNode is a slope shader than check what we //are dropping on to // { if(destinationNode.hasFn(MFn.Type.kLambert)) result = true; else if (destinationNode.hasFn(MFn.Type.kMesh)) result = true; } return result; }
// // Description // // Converts the given component values into a selection list of plugs. // This method is used to map components to attributes. // // Arguments // // component - the component to be translated to a plug/attribute // list - a list of plugs representing the passed in component // public override void componentToPlugs(MObject component, MSelectionList list) { if ( component.hasFn(MFn.Type.kSingleIndexedComponent) ) { MFnSingleIndexedComponent fnVtxComp = new MFnSingleIndexedComponent( component ); MObject thisNode = thisMObject(); MPlug plug = new MPlug( thisNode, mControlPoints ); // If this node is connected to a tweak node, reset the // plug to point at the tweak node. // convertToTweakNodePlug(plug); int len = fnVtxComp.elementCount; for ( int i = 0; i < len; i++ ) { plug.selectAncestorLogicalIndex((uint)fnVtxComp.element(i), plug.attribute); list.add(plug); } } }
// // Description: // Overloaded function from MPxDragAndDropBehavior // this method will handle the connection between the slopeShaderNodeCSharp and the shader it is // assigned to as well as any meshes that it is assigned to. // public override void connectNodeToNode(MObject sourceNode, MObject destinationNode, bool force) { MFnDependencyNode src = new MFnDependencyNode(sourceNode); //if we are dragging from a lambert //we want to check what we are dragging //onto. if (sourceNode.hasFn(MFn.Type.kLambert)) { //MObject shaderNode; MPlugArray connections = new MPlugArray(); MObjectArray shaderNodes = new MObjectArray(); shaderNodes.clear(); //if the source node was a lambert //than we will check the downstream connections to see //if a slope shader is assigned to it. // src.getConnections(connections); int i; for (i = 0; i < connections.length; i++) { //check the incoming connections to this plug // MPlugArray connectedPlugs = new MPlugArray(); connections[i].connectedTo(connectedPlugs, true, false); for (uint j = 0; j < connectedPlugs.length; j++) { //if the incoming node is a slope shader than //append the node to the shaderNodes array // MObject currentnode = connectedPlugs[i].node; if (new MFnDependencyNode(currentnode).typeName == "slopeShaderNodeCSharp") { shaderNodes.append(currentnode); } } } //if we found a shading node //than check the destination node //type to see if it is a mesh // if (shaderNodes.length > 0) { MFnDependencyNode dest = new MFnDependencyNode(destinationNode); if (destinationNode.hasFn(MFn.Type.kMesh)) { //if the node is a mesh than for each slopeShaderNodeCSharp //connect the worldMesh attribute to the dirtyShaderPlug //attribute to force an evaluation of the node when the mesh //changes // for (i = 0; i < shaderNodes.length; i++) { MPlug srcPlug = dest.findPlug("worldMesh"); MPlug destPlug = new MFnDependencyNode(shaderNodes[i]).findPlug("dirtyShaderPlug"); if (!srcPlug.isNull && !destPlug.isNull) { string cmd = "connectAttr -na "; cmd += srcPlug.name + " "; cmd += destPlug.name; try { // in slopeShaderBehavior.cpp, this may excute failed but continue on the following code, so we catch it. MGlobal.executeCommand(cmd); } catch (System.Exception) { MGlobal.displayError("ExcuteCommand (" + cmd + ") failed."); } } } //get the shading engine so we can assign the shader //to the mesh after doing the connection // MObject shadingEngine = findShadingEngine(sourceNode); //if there is a valid shading engine than make //the connection // if (!shadingEngine.isNull) { string cmd = "sets -edit -forceElement "; cmd += new MFnDependencyNode(shadingEngine).name + " "; cmd += new MFnDagNode(destinationNode).partialPathName; MGlobal.executeCommand(cmd); } } } } else if (src.typeName == "slopeShaderNodeCSharp") //if we are dragging from a slope shader //than we want to see what we are dragging onto // { if (destinationNode.hasFn(MFn.Type.kMesh)) { //if the user is dragging onto a mesh //than make the connection from the worldMesh //to the dirtyShader plug on the slopeShaderNodeCSharp // MFnDependencyNode dest = new MFnDependencyNode(destinationNode); MPlug srcPlug = dest.findPlug("worldMesh"); MPlug destPlug = src.findPlug("dirtyShaderPlug"); if (!srcPlug.isNull && !destPlug.isNull) { string cmd = "connectAttr -na "; cmd += srcPlug.name + " "; cmd += destPlug.name; MGlobal.executeCommand(cmd); } } } return; }