private GLTFNode ExportLight(ref GLTFNode gltfNode, BabylonLight babylonLight, GLTF gltf, GLTFNode gltfParentNode, BabylonScene babylonScene) { if (exportParameters.enableKHRLightsPunctual) { if (babylonLight.type == 3) // ambient light { RaiseMessage($"GLTFExporter.Light | Ambient light {babylonLight.name} is not supported in KHR_lights_punctual."); } else { RaiseMessage("GLTFExporter.Light | Export light named: " + babylonLight.name, 2); // new light in the node extensions GLTFLight light = new GLTFLight { light = AddLightExtension(ref gltf, babylonLight) }; if (gltfNode.extensions == null) { gltfNode.extensions = new GLTFExtensions(); } gltfNode.extensions[KHR_lights_punctuals] = light; } } return(gltfNode); }
private GLTFNode ExportLight(ref GLTFNode gltfNode, BabylonLight babylonLight, GLTF gltf, GLTFNode gltfParentNode, BabylonScene babylonScene) { // Custom user properties if (babylonLight.metadata != null && babylonLight.metadata.Count != 0) { gltfNode.extras = babylonLight.metadata; } if (exportParameters.enableKHRLightsPunctual) { if (babylonLight.type == 3) // ambient light { logger.RaiseMessage($"GLTFExporter.Light | Ambient light {babylonLight.name} is not supported in KHR_lights_punctual."); } else { logger.RaiseMessage("GLTFExporter.Light | Export light named: " + babylonLight.name, 2); // new light in the node extensions GLTFLight light = new GLTFLight { light = AddLightExtension(ref gltf, babylonLight) }; if (gltfNode.extensions == null) { gltfNode.extensions = new GLTFExtensions(); } gltfNode.extensions[KHR_lights_punctuals] = light; } } ExportGLTFExtension(babylonLight, ref gltfNode, gltf); return(gltfNode); }
public const string KHR_lights = "KHR_lights"; // Name of the extension /// <summary> /// Add the light the global extensions /// </summary> /// <param name="gltf">The gltf data</param> /// <param name="babylonLight">The light to export</param> /// <returns>the index of the light</returns> private int AddLightExtension(ref GLTF gltf, BabylonLight babylonLight) { if (gltf.extensionsUsed.Contains(KHR_lights) == false) { gltf.extensionsUsed.Add(KHR_lights); } // new light in the gltf extensions GLTFLight light = new GLTFLight { color = babylonLight.diffuse, type = ((GLTFLight.LightType)babylonLight.type).ToString(), intensity = babylonLight.intensity, }; switch (babylonLight.type) { case (0): // point light.type = GLTFLight.LightType.point.ToString(); light.range = babylonLight.range; break; case (1): // directional light.type = GLTFLight.LightType.directional.ToString(); break; case (2): // spot light.type = GLTFLight.LightType.spot.ToString(); light.range = babylonLight.range; light.spot = new GLTFLight.Spot { //innerConeAngle = 0, Babylon doesn't support the innerConeAngle outerConeAngle = babylonLight.angle }; break; case (3): // ambient light.type = GLTFLight.LightType.ambient.ToString(); break; } Dictionary <string, List <GLTFLight> > KHR_lightsExtension; if (gltf.extensions.ContainsKey(KHR_lights)) { KHR_lightsExtension = (Dictionary <string, List <GLTFLight> >)gltf.extensions[KHR_lights]; KHR_lightsExtension["lights"].Add(light); } else { KHR_lightsExtension = new Dictionary <string, List <GLTFLight> >(); KHR_lightsExtension["lights"] = new List <GLTFLight>(); KHR_lightsExtension["lights"].Add(light); gltf.extensions[KHR_lights] = KHR_lightsExtension; } return(KHR_lightsExtension["lights"].Count - 1); // the index of the light }
private void ConvertUnityLightToBabylon(Light light, float progress) { if (!light.isActiveAndEnabled || light.alreadyLightmapped) { return; } ExporterWindow.ReportProgress(progress, "Exporting light: " + light.name); BabylonLight babylonLight = new BabylonLight { name = light.name, id = GetID(light.gameObject), parentId = GetParentID(light.transform) }; switch (light.type) { case LightType.Spot: babylonLight.type = 2; break; case LightType.Directional: babylonLight.type = 1; break; case LightType.Point: babylonLight.type = 0; babylonLight.range = light.range; break; case LightType.Area: // TODO break; } babylonLight.position = light.transform.localPosition.ToFloat(); var direction = new Vector3(0, 0, 1); var transformedDirection = light.transform.TransformDirection(direction); babylonLight.direction = transformedDirection.ToFloat(); babylonLight.diffuse = light.color.ToFloat(); babylonLight.intensity = light.intensity; babylonLight.angle = light.spotAngle * (float)Math.PI / 180; babylonLight.exponent = 1.0f; babylonScene.LightsList.Add(babylonLight); // Animations ExportAnimations(light.transform, babylonLight); // Shadows if ((light.type == LightType.Directional || light.type == LightType.Spot) && light.shadows != LightShadows.None) { GenerateShadowsGenerator(light); } }
private GLTFNode ExportLight(BabylonLight babylonLight, GLTF gltf, GLTFNode gltfParentNode) { RaiseMessage("GLTFExporter.Light | ExportLight babylonLight.name=" + babylonLight.name, 1); // -------------------------- // ---------- Node ---------- // -------------------------- RaiseMessage("GLTFExporter.Light | Node", 2); // Node var gltfNode = new GLTFNode(); gltfNode.name = babylonLight.name; gltfNode.index = gltf.NodesList.Count; gltf.NodesList.Add(gltfNode); // Hierarchy if (gltfParentNode != null) { RaiseMessage("GLTFExporter.Light | Add " + babylonLight.name + " as child to " + gltfParentNode.name, 3); gltfParentNode.ChildrenList.Add(gltfNode.index); gltfNode.parent = gltfParentNode; } else { // It's a root node // Only root nodes are listed in a gltf scene RaiseMessage("GLTFExporter.Light | Add " + babylonLight.name + " as root node to scene", 3); gltf.scenes[0].NodesList.Add(gltfNode.index); } // Transform gltfNode.translation = babylonLight.position; // No rotation defined for babylon light. Use identity instead. gltfNode.rotation = new float[4] { 0, 0, 0, 1 }; // No scaling defined for babylon light. Use identity instead. gltfNode.scale = new float[3] { 1, 1, 1 }; // Switch coordinate system at object level gltfNode.translation[2] *= -1; gltfNode.rotation[0] *= -1; gltfNode.rotation[1] *= -1; // TODO - Animations //ExportNodeAnimation(babylonLight, gltf, gltfNode); return(gltfNode); }
void DumpLights(NovaScene scene, BabylonScene babylonScene) { foreach (NovaLight light in scene.Lights) { if (light.Enabled) { var babylonLight = new BabylonLight(); babylonScene.LightsList.Add(babylonLight); babylonLight.name = light.Name; babylonLight.id = light.ID.ToString(); switch (light.Type) { case NovaLightType.Point: babylonLight.type = 0; babylonLight.position = light.Position.ToArray(); break; case NovaLightType.Spot: case NovaLightType.Directional: babylonLight.type = 1; babylonLight.position = light.Position.ToArray(); babylonLight.direction = light.Direction.ToArray(); break; } babylonLight.diffuse = light.Diffuse.ToArray(); babylonLight.specular = light.Specular.ToArray(); babylonLight.intensity = light.Multiplicator; if (light.ShadowMembers.Count > 0) { var shadowGenerator = new BabylonShadowGenerator { useVarianceShadowMap = true, lightId = light.ID.ToString(), mapSize = light.ShadowMapSize, renderList = light.ShadowMembers.Select(m => m.ID.ToString()).ToArray() }; babylonScene.ShadowGeneratorsList.Add(shadowGenerator); } if (light.LensFlares != null) { light.LensFlares.Tag = light; lensFlareSystemToExport.Add(light.LensFlares); } } } }
void ExportDefaultLight(BabylonScene babylonScene) { var babylonLight = new BabylonLight(); babylonLight.name = "Default light"; babylonLight.id = Guid.NewGuid().ToString(); babylonLight.type = 3; babylonLight.groundColor = new float[] { 0, 0, 0 }; babylonLight.direction = new[] { 0, 1.0f, 0 }; babylonLight.intensity = 1; babylonLight.diffuse = new[] { 1.0f, 1.0f, 1.0f }; babylonLight.specular = new[] { 1.0f, 1.0f, 1.0f }; babylonScene.LightsList.Add(babylonLight); }
private GLTFNode ExportLight(ref GLTFNode gltfNode, BabylonLight babylonLight, GLTF gltf, GLTFNode gltfParentNode, BabylonScene babylonScene) { RaiseMessage("GLTFExporter.Light | Export light named: " + babylonLight.name, 2); // new light in the node extensions GLTFLight light = new GLTFLight { light = AddLightExtension(ref gltf, babylonLight) }; if (gltfNode.extensions == null) { gltfNode.extensions = new GLTFExtensions(); } gltfNode.extensions[KHR_lights] = light; return(gltfNode); }
private void ConvertUnityLightToBabylon(Light light, GameObject gameObject, float progress, ref UnityMetaData metaData, ref List <BabylonExport.Entities.BabylonParticleSystem> particleSystems, ref List <UnityFlareSystem> lensFlares, ref string componentTags) { // No Inactive Or Baking Lights if (light.isActiveAndEnabled == false || light.type == LightType.Area || light.lightmappingMode == LightmappingMode.Baked) { return; } ExporterWindow.ReportProgress(progress, "Exporting light: " + light.name); BabylonLight babylonLight = new BabylonLight { name = light.name, id = GetID(light.gameObject), parentId = GetParentID(light.transform) }; metaData.type = "Light"; babylonLight.tags = componentTags; switch (light.type) { case LightType.Point: babylonLight.type = 0; babylonLight.range = light.range; break; case LightType.Directional: babylonLight.type = 1; break; case LightType.Spot: babylonLight.type = 2; break; } babylonLight.position = light.transform.localPosition.ToFloat(); var direction = new Vector3(0, 0, 1); var transformedDirection = light.transform.TransformDirection(direction); transformedDirection[0] += exportationOptions.LightRotationOffset.X; transformedDirection[1] += exportationOptions.LightRotationOffset.Y; transformedDirection[2] += exportationOptions.LightRotationOffset.Z; babylonLight.direction = transformedDirection.ToFloat(); babylonLight.diffuse = light.color.ToFloat(); babylonLight.intensity = light.intensity * exportationOptions.LightIntensityFactor; babylonLight.angle = light.spotAngle * (float)Math.PI / 180; babylonLight.exponent = 1.0f; babylonLight.metadata = metaData; babylonScene.LightsList.Add(babylonLight); // Animations ExportAnimations(light.transform, babylonLight); // Lens Flares ParseLensFlares(gameObject, babylonLight.id, ref lensFlares); // Particles Systems ParseParticleSystems(gameObject, babylonLight.id, ref particleSystems); // Shadow Maps if (exportationOptions.ExportShadows) { if ((light.type == LightType.Directional || light.type == LightType.Spot) && light.shadows != LightShadows.None) { GenerateShadowsGenerator(light, progress); } } }
/// <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 //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 }; // 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); }
private BabylonNode ExportLight(IIGameScene scene, IIGameNode lightNode, BabylonScene babylonScene) { if (IsLightExportable(lightNode) == false) { return(null); } var gameLight = lightNode.IGameObject.AsGameLight(); var initialized = gameLight.InitializeData; var babylonLight = new BabylonLight(); RaiseMessage(lightNode.Name, 1); babylonLight.name = lightNode.Name; // Export the custom attributes of this light babylonLight.metadata = ExportExtraAttributes(lightNode, babylonScene); // To preserve the position/rotation and the hierarchy, we create a dummy that will contains as direct children the light and the light children // The light will have no children. The dummy will contains the position and rotation animations. bool createDummy = lightNode.ChildCount > 0; BabylonNode dummy = null; if (createDummy) { dummy = ExportDummy(scene, lightNode, babylonScene); dummy.name = "_" + dummy.name + "_"; babylonLight.id = Guid.NewGuid().ToString(); babylonLight.parentId = dummy.id; babylonLight.hasDummy = true; } else { babylonLight.id = lightNode.MaxNode.GetGuid().ToString(); if (lightNode.NodeParent != null) { babylonLight.parentId = lightNode.NodeParent.MaxNode.GetGuid().ToString(); } } // Type var maxLight = (lightNode.MaxNode.ObjectRef as ILightObject); var lightState = Loader.Global.LightState.Create(); maxLight.EvalLightState(0, Tools.Forever, lightState); switch (lightState.Type) { case LightType.OmniLgt: babylonLight.type = 0; break; case LightType.SpotLgt: babylonLight.type = 2; babylonLight.angle = (float)(maxLight.GetFallsize(0, Tools.Forever) * Math.PI / 180.0f); babylonLight.exponent = 1; break; case LightType.DirectLgt: babylonLight.type = 1; break; case LightType.AmbientLgt: babylonLight.type = 3; babylonLight.groundColor = new float[] { 0, 0, 0 }; break; } // Shadows if (maxLight.ShadowMethod == 1) { if (lightState.Type == LightType.DirectLgt || lightState.Type == LightType.SpotLgt || lightState.Type == LightType.OmniLgt) { ExportShadowGenerator(lightNode.MaxNode, babylonScene, babylonLight); } else { RaiseWarning("Shadows maps are only supported for point, directional and spot lights", 2); } } // Position / rotation / scaling if (createDummy) { // The position is stored by the dummy parent and the default direction is downward and it is updated by the rotation of the parent dummy babylonLight.position = new[] { 0f, 0f, 0f }; babylonLight.direction = new[] { 0f, -1f, 0f }; } else { exportTransform(babylonLight, lightNode); // Position var localMatrix = lightNode.GetLocalTM(0); var position = localMatrix.Translation; // Direction var target = gameLight.LightTarget; if (target != null) { var targetWm = target.GetObjectTM(0); var targetPosition = targetWm.Translation; var direction = targetPosition.Subtract(position).Normalize; babylonLight.direction = new[] { direction.X, direction.Y, direction.Z }; } else { var vDir = Loader.Global.Point3.Create(0, -1, 0); vDir = localMatrix.ExtractMatrix3().VectorTransform(vDir).Normalize; babylonLight.direction = new[] { vDir.X, vDir.Y, vDir.Z }; } } // The HemisphericLight simulates the ambient environment light, so the passed direction is the light reflection direction, not the incoming direction. // So we need the opposite direction if (babylonLight.type == 3) { var worldRotation = lightNode.GetWorldTM(0).Rotation; BabylonQuaternion quaternion = new BabylonQuaternion(worldRotation.X, worldRotation.Y, worldRotation.Z, worldRotation.W); babylonLight.direction = quaternion.Rotate(new BabylonVector3(0f, 1f, 0f)).ToArray(); } var maxScene = Loader.Core.RootNode; // Exclusion try { var inclusion = maxLight.ExclList.TestFlag(1); //NT_INCLUDE var checkExclusionList = maxLight.ExclList.TestFlag(2); //NT_AFFECT_ILLUM if (checkExclusionList) { var excllist = new List <string>(); var incllist = new List <string>(); foreach (var meshNode in maxScene.NodesListBySuperClass(SClass_ID.Geomobject)) { #if MAX2017 || MAX2018 || MAX2019 || MAX2020 if (meshNode.CastShadows) #else if (meshNode.CastShadows == 1) #endif { var inList = maxLight.ExclList.FindNode(meshNode) != -1; if (inList) { if (inclusion) { incllist.Add(meshNode.GetGuid().ToString()); } else { excllist.Add(meshNode.GetGuid().ToString()); } } } } babylonLight.includedOnlyMeshesIds = incllist.ToArray(); babylonLight.excludedMeshesIds = excllist.ToArray(); } } catch (Exception e) { RaiseMessage("Light exclusion not supported", 2); } // Other fields babylonLight.intensity = maxLight.GetIntensity(0, Tools.Forever); babylonLight.diffuse = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 }; babylonLight.specular = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 }; if (maxLight.UseAtten) { babylonLight.range = maxLight.GetAtten(0, 3, Tools.Forever); } if (exportParameters.exportAnimations) { // Animations var animations = new List <BabylonAnimation>(); if (createDummy) { // Position and rotation animations are stored by the parent (the dummy). The direction result from the parent rotation except for the HemisphericLight. if (babylonLight.type == 3) { BabylonVector3 direction = new BabylonVector3(0, 1, 0); ExportVector3Animation("direction", animations, key => { var worldRotation = lightNode.GetWorldTM(key).Rotation; BabylonQuaternion quaternion = new BabylonQuaternion(worldRotation.X, worldRotation.Y, worldRotation.Z, worldRotation.W); return(quaternion.Rotate(direction).ToArray()); }); } } else { GeneratePositionAnimation(lightNode, animations); ExportVector3Animation("direction", animations, key => { var localMatrixAnimDir = lightNode.GetLocalTM(key); var positionLight = localMatrixAnimDir.Translation; var lightTarget = gameLight.LightTarget; if (lightTarget != null) { var targetWm = lightTarget.GetObjectTM(key); var targetPosition = targetWm.Translation; var direction = targetPosition.Subtract(positionLight).Normalize; return(new[] { direction.X, direction.Y, direction.Z }); } else { var vDir = Loader.Global.Point3.Create(0, -1, 0); vDir = localMatrixAnimDir.ExtractMatrix3().VectorTransform(vDir).Normalize; // The HemisphericLight (type == 3) simulates the ambient environment light, so the passed direction is the light reflection direction, not the incoming direction. // So we need the opposite direction return(babylonLight.type != 3 ? new[] { vDir.X, vDir.Y, vDir.Z } : new[] { -vDir.X, -vDir.Y, -vDir.Z }); } }); // Animation temporary stored for gltf but not exported for babylon // TODO - Will cause an issue when externalizing the glTF export process var extraAnimations = new List <BabylonAnimation>(); // Do not check if node rotation properties are animated GenerateRotationAnimation(lightNode, extraAnimations, true); babylonLight.extraAnimations = extraAnimations; } ExportFloatAnimation("intensity", animations, key => new[] { maxLight.GetIntensity(key, Tools.Forever) }); ExportColor3Animation("diffuse", animations, key => { return(lightState.AffectDiffuse? maxLight.GetRGBColor(key, Tools.Forever).ToArray() : new float[] { 0, 0, 0 }); }); babylonLight.animations = animations.ToArray(); if (lightNode.MaxNode.GetBoolProperty("babylonjs_autoanimate")) { babylonLight.autoAnimate = true; babylonLight.autoAnimateFrom = (int)lightNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_from"); babylonLight.autoAnimateTo = (int)lightNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_to"); babylonLight.autoAnimateLoop = lightNode.MaxNode.GetBoolProperty("babylonjs_autoanimateloop"); } } babylonScene.LightsList.Add(babylonLight); return(createDummy ? dummy : babylonLight); }
/// <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 BabylonShadowGenerator ExportShadowGenerator(IINode lightNode, BabylonScene babylonScene, BabylonLight babylonLight) { var maxLight = (lightNode.ObjectRef as ILightObject); var babylonShadowGenerator = new BabylonShadowGenerator(); RaiseMessage("Exporting shadow map", 2); babylonShadowGenerator.lightId = babylonLight.id; babylonShadowGenerator.mapSize = maxLight.GetMapSize(0, Tools.Forever); babylonShadowGenerator.bias = lightNode.GetFloatProperty("babylonjs_shadows_bias", 0.00005f); babylonShadowGenerator.forceBackFacesOnly = lightNode.GetBoolProperty("babylonjs_forcebackfaces"); var shadowsType = lightNode.GetStringProperty("babylonjs_shadows_type", "Blurred ESM"); switch (shadowsType) { case "Hard shadows": break; case "Poisson Sampling": babylonShadowGenerator.usePoissonSampling = true; break; case "ESM": babylonShadowGenerator.useExponentialShadowMap = true; break; case "Blurred ESM": babylonShadowGenerator.useBlurExponentialShadowMap = true; babylonShadowGenerator.blurScale = lightNode.GetFloatProperty("babylonjs_shadows_blurScale", 2); babylonShadowGenerator.blurBoxOffset = lightNode.GetFloatProperty("babylonjs_shadows_blurBoxOffset", 1); break; } var list = new List <string>(); var inclusion = maxLight.ExclList.TestFlag(1); //NT_INCLUDE var checkExclusionList = maxLight.ExclList.TestFlag(4); //NT_AFFECT_SHADOWCAST foreach (var meshNode in Loader.Core.RootNode.NodesListBySuperClass(SClass_ID.Geomobject)) { #if MAX2017 || MAX2018 || MAX2019 || MAX2020 if (meshNode.CastShadows) #else if (meshNode.CastShadows == 1) #endif { var inList = maxLight.ExclList.FindNode(meshNode) != -1; if (!checkExclusionList || (inList && inclusion) || (!inList && !inclusion)) { list.Add(meshNode.GetGuid().ToString()); } } } babylonShadowGenerator.renderList = list.ToArray(); babylonScene.ShadowGeneratorsList.Add(babylonShadowGenerator); return(babylonShadowGenerator); }
public const string KHR_lights_punctuals = "KHR_lights_punctual"; // Name of the extension /// <summary> /// Add the light the global extensions /// </summary> /// <param name="gltf">The gltf data</param> /// <param name="babylonLight">The light to export</param> /// <returns>the index of the light</returns> private int AddLightExtension(ref GLTF gltf, BabylonLight babylonLight) { if (gltf.extensionsUsed.Contains(KHR_lights_punctuals) == false) { gltf.extensionsUsed.Add(KHR_lights_punctuals); } // new light in the gltf extensions GLTFLight light = new GLTFLight { color = babylonLight.diffuse, type = ((GLTFLight.LightType)babylonLight.type).ToString(), intensity = babylonLight.intensity, }; switch (babylonLight.type) { case (0): // point light.type = GLTFLight.LightType.point.ToString(); light.range = babylonLight.range; break; case (1): // directional light.type = GLTFLight.LightType.directional.ToString(); break; case (2): // spot light.type = GLTFLight.LightType.spot.ToString(); light.range = babylonLight.range; light.spot = new GLTFLight.Spot { //innerConeAngle = 0, Babylon doesn't support the innerConeAngle outerConeAngle = babylonLight.angle }; break; default: RaiseError($"Unsupported light type {light.type} for glTF"); throw new System.Exception($"Unsupported light type {light.type} for glTF"); } Dictionary <string, List <GLTFLight> > KHR_lightsExtension; if (gltf.extensions.ContainsKey(KHR_lights_punctuals)) { KHR_lightsExtension = (Dictionary <string, List <GLTFLight> >)gltf.extensions[KHR_lights_punctuals]; KHR_lightsExtension["lights"].Add(light); } else { KHR_lightsExtension = new Dictionary <string, List <GLTFLight> >(); KHR_lightsExtension["lights"] = new List <GLTFLight>(); KHR_lightsExtension["lights"].Add(light); gltf.extensions[KHR_lights_punctuals] = KHR_lightsExtension; if (gltf.extensionsUsed == null) { gltf.extensionsUsed = new List <string>(); } if (!gltf.extensionsUsed.Contains(KHR_lights_punctuals)) { gltf.extensionsUsed.Add(KHR_lights_punctuals); } } return(KHR_lightsExtension["lights"].Count - 1); // the index of the light }
private void ConvertUnityLightToBabylon(Light light, GameObject gameObject, float progress, ref UnityMetaData metaData, ref List <UnityFlareSystem> lensFlares, ref string componentTags) { if (light.isActiveAndEnabled == false) { return; } if (light.type != LightType.Area && light.lightmapBakeType == LightmapBakeType.Baked) { return; } if (light.type == LightType.Area && exportationOptions.BakedLightsMode == (int)BabylonAreaLights.ExcludeAreaBakingLights) { return; } ExporterWindow.ReportProgress(progress, "Exporting light: " + light.name); BabylonLight babylonLight = (light.type == LightType.Directional) ? new BabylonDirectionalLight() : new BabylonLight(); babylonLight.name = light.name; babylonLight.id = GetID(light.gameObject); babylonLight.parentId = GetParentID(light.transform); metaData.type = "Light"; babylonLight.tags = componentTags; switch (light.type) { case LightType.Area: case LightType.Point: babylonLight.type = 0; babylonLight.range = light.range; break; case LightType.Directional: babylonLight.type = 1; break; case LightType.Spot: babylonLight.type = 2; break; } babylonLight.position = light.transform.localPosition.ToFloat(); var direction = new Vector3(0, 0, 1); var transformedDirection = light.transform.TransformDirection(direction); babylonLight.direction = transformedDirection.ToFloat(); //light.intensityMode = BABYLON.Light.INTENSITYMODE_AUTOMATIC; // Lumen (lm) //light.intensityMode = BABYLON.Light.INTENSITYMODE_LUMINOUSPOWER; // Candela (lm/sr) //light.intensityMode = BABYLON.Light.INTENSITYMODE_LUMINOUSINTENSITY; // Lux (lm/m^2) //light.intensityMode = BABYLON.Light.INTENSITYMODE_ILLUMINANCE; // Nit (cd/m^2) //light.intensityMode = BABYLON.Light.INTENSITYMODE_LUMINANCE; babylonLight.intensity = light.intensity; babylonLight.intensityMode = (int)BabylonLightIntensity.Automatic; var lightScale = gameObject.GetComponent <LightScale>(); if (lightScale != null) { babylonLight.intensity *= lightScale.lightIntensity; babylonLight.intensityMode = (int)lightScale.intensityMode; } babylonLight.diffuse = light.color.ToFloat(); babylonLight.specular = Color.white.ToFloat(); babylonLight.exponent = 1.0f; babylonLight.angle = light.spotAngle * (float)Math.PI / 180; // Animations ExportTransformAnimationClips(light.transform, babylonLight, ref metaData); // Tagging if (!String.IsNullOrEmpty(babylonLight.tags)) { babylonLight.tags = babylonLight.tags.Trim(); } babylonLight.metadata = metaData; babylonScene.LightsList.Add(babylonLight); // Lens Flares ParseLensFlares(gameObject, babylonLight.id, ref lensFlares); // Realtime Shadows if (light.shadows != LightShadows.None) { GenerateShadowsGenerator(babylonLight, light, progress); } if (!exportationOptions.ExportMetadata) { babylonLight.metadata = null; } }
private void ExportLight(IIGameScene scene, IIGameNode lightNode, BabylonScene babylonScene) { if (lightNode.MaxNode.GetBoolProperty("babylonjs_noexport")) { return; } var gameLight = lightNode.IGameObject.AsGameLight(); var initialized = gameLight.InitializeData; var babylonLight = new BabylonLight(); RaiseMessage(lightNode.Name, 1); babylonLight.name = lightNode.Name; babylonLight.id = lightNode.MaxNode.GetGuid().ToString(); if (lightNode.NodeParent != null) { babylonLight.parentId = GetParentID(lightNode.NodeParent, babylonScene, scene); } // Type var maxLight = (lightNode.MaxNode.ObjectRef as ILightObject); var lightState = Loader.Global.LightState.Create(); maxLight.EvalLightState(0, Tools.Forever, lightState); switch (lightState.Type) { case LightType.OmniLgt: babylonLight.type = 0; break; case LightType.SpotLgt: babylonLight.type = 2; babylonLight.angle = (float)(maxLight.GetFallsize(0, Tools.Forever) * Math.PI / 180.0f); babylonLight.exponent = 1; break; case LightType.DirectLgt: babylonLight.type = 1; break; case LightType.AmbientLgt: babylonLight.type = 3; babylonLight.groundColor = new float[] { 0, 0, 0 }; break; } // Shadows if (maxLight.ShadowMethod == 1) { if (lightState.Type == LightType.DirectLgt || lightState.Type == LightType.SpotLgt || lightState.Type == LightType.OmniLgt) { ExportShadowGenerator(lightNode.MaxNode, babylonScene); } else { RaiseWarning("Shadows maps are only supported for point, directional and spot lights", 2); } } // Position var wm = lightNode.GetObjectTM(0); if (lightNode.NodeParent != null) { var parentWorld = lightNode.NodeParent.GetObjectTM(0); wm.MultiplyBy(parentWorld.Inverse); } var position = wm.Translation; babylonLight.position = new[] { position.X, position.Y, position.Z }; // Direction var target = gameLight.LightTarget; if (target != null) { var targetWm = target.GetObjectTM(0); var targetPosition = targetWm.Translation; var direction = targetPosition.Subtract(position).Normalize; babylonLight.direction = new[] { direction.X, direction.Y, direction.Z }; } else { var vDir = Loader.Global.Point3.Create(0, -1, 0); vDir = wm.ExtractMatrix3().VectorTransform(vDir).Normalize; babylonLight.direction = new[] { vDir.X, vDir.Y, vDir.Z }; } var maxScene = Loader.Core.RootNode; // Exclusion var inclusion = maxLight.ExclList.TestFlag(1); //NT_INCLUDE var checkExclusionList = maxLight.ExclList.TestFlag(2); //NT_AFFECT_ILLUM if (checkExclusionList) { var excllist = new List <string>(); var incllist = new List <string>(); foreach (var meshNode in maxScene.NodesListBySuperClass(SClass_ID.Geomobject)) { if (meshNode.CastShadows == 1) { var inList = maxLight.ExclList.FindNode(meshNode) != -1; if (inList) { if (inclusion) { incllist.Add(meshNode.GetGuid().ToString()); } else { excllist.Add(meshNode.GetGuid().ToString()); } } } } babylonLight.includedOnlyMeshesIds = incllist.ToArray(); babylonLight.excludedMeshesIds = excllist.ToArray(); } // Other fields babylonLight.intensity = maxLight.GetIntensity(0, Tools.Forever); babylonLight.diffuse = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 }; babylonLight.specular = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 }; if (maxLight.UseAtten) { babylonLight.range = maxLight.GetAtten(0, 3, Tools.Forever); } // Animations var animations = new List <BabylonAnimation>(); ExportVector3Animation("position", animations, key => { var mat = lightNode.GetObjectTM(key); if (lightNode.NodeParent != null) { var parentWorld = lightNode.NodeParent.GetObjectTM(key); mat.MultiplyBy(parentWorld.Inverse); } var pos = mat.Translation; return(new[] { pos.X, pos.Y, pos.Z }); }); ExportVector3Animation("direction", animations, key => { var wmLight = lightNode.GetObjectTM(key); if (lightNode.NodeParent != null) { var parentWorld = lightNode.NodeParent.GetObjectTM(key); wmLight.MultiplyBy(parentWorld.Inverse); } var positionLight = wmLight.Translation; var lightTarget = gameLight.LightTarget; if (lightTarget != null) { var targetWm = lightTarget.GetObjectTM(key); var targetPosition = targetWm.Translation; var direction = targetPosition.Subtract(positionLight).Normalize; return(new[] { direction.X, direction.Y, direction.Z }); } else { var vDir = Loader.Global.Point3.Create(0, -1, 0); vDir = wmLight.ExtractMatrix3().VectorTransform(vDir).Normalize; return(new[] { vDir.X, vDir.Y, vDir.Z }); } }); ExportFloatAnimation("intensity", animations, key => new[] { maxLight.GetIntensity(key, Tools.Forever) }); ExportColor3Animation("diffuse", animations, key => { return(lightState.AffectDiffuse? maxLight.GetRGBColor(key, Tools.Forever).ToArray() : new float[] { 0, 0, 0 }); }); babylonLight.animations = animations.ToArray(); if (lightNode.MaxNode.GetBoolProperty("babylonjs_autoanimate")) { babylonLight.autoAnimate = true; babylonLight.autoAnimateFrom = (int)lightNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_from"); babylonLight.autoAnimateTo = (int)lightNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_to"); babylonLight.autoAnimateLoop = lightNode.MaxNode.GetBoolProperty("babylonjs_autoanimateloop"); } babylonScene.LightsList.Add(babylonLight); }
private void GenerateShadowsGenerator(BabylonLight babylonLight, Light light, float progress) { var shadows = light.gameObject.GetComponent <UnityEditor.ShadowGenerator>(); if (shadows != null && shadows.isActiveAndEnabled) { if (babylonLight is BabylonDirectionalLight) { ((BabylonDirectionalLight)babylonLight).shadowOrthoScale = shadows.shadowOrthoScale; } float strength = light.shadowStrength * shadows.shadowStrengthScale; var generator = new BabylonExport.Entities.BabylonShadowGenerator { lightId = GetID(light.gameObject), bias = shadows.shadowMapBias, mapSize = shadows.shadowMapSize, darkness = (1.0f - strength), depthScale = shadows.shadowDepthScale, blurScale = shadows.shadowBlurScale, blurBoxOffset = shadows.shadowBlurOffset, forceBackFacesOnly = shadows.forceBackFacesOnly }; switch (shadows.shadowMapFilter) { case BabylonLightingFilter.PoissonSampling: generator.usePoissonSampling = true; break; case BabylonLightingFilter.ExponentialShadowMap: generator.useExponentialShadowMap = true; break; case BabylonLightingFilter.BlurExponentialShadowMap: generator.useBlurExponentialShadowMap = true; break; } // Light Shadow Generator Render List var renderList = new List <string>(); foreach (var gameObject in gameObjects) { if (gameObject.layer != ExporterWindow.PrefabIndex) { if (!gameObject.IsLightapStatic()) { var shadowmap = gameObject.GetComponent <ShadowMap>(); if (shadowmap != null && shadowmap.runtimeShadows == BabylonEnabled.Enabled) { var renderer = gameObject.GetComponent <Renderer>(); var meshFilter = gameObject.GetComponent <MeshFilter>(); if (meshFilter != null && renderer != null && renderer.shadowCastingMode != ShadowCastingMode.Off) { renderList.Add(GetID(gameObject)); continue; } var skinnedMesh = gameObject.GetComponent <SkinnedMeshRenderer>(); if (skinnedMesh != null && renderer != null && renderer.shadowCastingMode != ShadowCastingMode.Off) { renderList.Add(GetID(gameObject)); } } } } } if (renderList.Count > 0) { generator.renderList = renderList.ToArray(); babylonScene.ShadowGeneratorsList.Add(generator); } } }
public const string KHR_lights_punctuals = "KHR_lights_punctual"; // Name of the extension /// <summary> /// Add the light the global extensions /// </summary> /// <param name="gltf">The gltf data</param> /// <param name="babylonLight">The light to export</param> /// <returns>the index of the light</returns> private int AddLightExtension(ref GLTF gltf, BabylonLight babylonLight) { if (gltf.extensionsUsed.Contains(KHR_lights_punctuals) == false) { gltf.extensionsUsed.Add(KHR_lights_punctuals); } // new light in the gltf extensions GLTFLight light = new GLTFLight { color = babylonLight.diffuse, type = ((GLTFLight.LightType)babylonLight.type).ToString(), intensity = babylonLight.intensity, }; // Custom user properties if (babylonLight.metadata != null && babylonLight.metadata.Count != 0) { light.extras = babylonLight.metadata; } switch (babylonLight.type) { case (0): // point light.type = GLTFLight.LightType.point.ToString(); light.range = babylonLight.range; break; case (1): // directional light.type = GLTFLight.LightType.directional.ToString(); break; case (2): // spot light.type = GLTFLight.LightType.spot.ToString(); light.range = babylonLight.range; light.spot = new GLTFLight.Spot { //innerConeAngle = 0, Babylon doesn't support the innerConeAngle outerConeAngle = babylonLight.angle / 2 // divide by 2 as glTF measures light outer angle from the light's center, while Babylon's light angle measures the whole light's cone angle. }; break; default: logger.RaiseError($"Unsupported light type {light.type} for glTF"); throw new System.Exception($"Unsupported light type {light.type} for glTF"); } Dictionary <string, List <GLTFLight> > KHR_lightsExtension; if (gltf.extensions.ContainsKey(KHR_lights_punctuals)) { KHR_lightsExtension = (Dictionary <string, List <GLTFLight> >)gltf.extensions[KHR_lights_punctuals]; KHR_lightsExtension["lights"].Add(light); } else { KHR_lightsExtension = new Dictionary <string, List <GLTFLight> >(); KHR_lightsExtension["lights"] = new List <GLTFLight>(); KHR_lightsExtension["lights"].Add(light); gltf.extensions[KHR_lights_punctuals] = KHR_lightsExtension; if (gltf.extensionsUsed == null) { gltf.extensionsUsed = new List <string>(); } if (!gltf.extensionsUsed.Contains(KHR_lights_punctuals)) { gltf.extensionsUsed.Add(KHR_lights_punctuals); } } ExportGLTFExtension(babylonLight, ref light, gltf); return(KHR_lightsExtension["lights"].Count - 1); // the index of the light }
private void ConvertUnityLightToBabylon(Light light, GameObject gameObject, float progress, ref UnityMetaData metaData, ref List <UnityFlareSystem> lensFlares, ref string componentTags) { // Note: No Inactive Or Full Baking Lights Exported if (light.isActiveAndEnabled == false || light.type == LightType.Area || light.lightmapBakeType == LightmapBakeType.Baked) { return; } ExporterWindow.ReportProgress(progress, "Exporting light: " + light.name); BabylonLight babylonLight = (light.type == LightType.Directional) ? new BabylonDirectionalLight() : new BabylonLight(); babylonLight.name = light.name; babylonLight.id = GetID(light.gameObject); babylonLight.parentId = GetParentID(light.transform); metaData.type = "Light"; babylonLight.tags = componentTags; switch (light.type) { case LightType.Point: babylonLight.type = 0; babylonLight.range = light.range; break; case LightType.Directional: babylonLight.type = 1; break; case LightType.Spot: babylonLight.type = 2; break; } babylonLight.position = light.transform.localPosition.ToFloat(); var direction = new Vector3(0, 0, 1); var transformedDirection = light.transform.TransformDirection(direction); var defaultRotationOffset = (SceneController != null) ? SceneController.lightingOptions.rotationOffset : ExporterWindow.DefaultRotationOffset; transformedDirection[0] += defaultRotationOffset.x; transformedDirection[1] += defaultRotationOffset.y; transformedDirection[2] += defaultRotationOffset.z; babylonLight.direction = transformedDirection.ToFloat(); babylonLight.diffuse = light.color.ToFloat(); float defaultIntenistyFactor = (SceneController != null) ? SceneController.lightingOptions.intensityScale : ExporterWindow.DefaultIntensityScale; babylonLight.intensity = light.intensity * defaultIntenistyFactor; babylonLight.angle = light.spotAngle * (float)Math.PI / 180; babylonLight.exponent = 1.0f; // Animations ExportTransformAnimationClips(light.transform, babylonLight, ref metaData); // Tagging if (!String.IsNullOrEmpty(babylonLight.tags)) { babylonLight.tags = babylonLight.tags.Trim(); } babylonLight.metadata = metaData; babylonScene.LightsList.Add(babylonLight); // Lens Flares ParseLensFlares(gameObject, babylonLight.id, ref lensFlares); // Realtime Shadow Maps (Scene Controller Required) if ((light.type == LightType.Directional || light.type == LightType.Point || light.type == LightType.Spot) && light.shadows != LightShadows.None) { GenerateShadowsGenerator(babylonLight, light, progress); } if (!exportationOptions.ExportMetadata) { babylonLight.metadata = null; } }
private BabylonLight ExportLight(Node lightNode, BabylonScene babylonScene) { var maxLight = (lightNode.Object as Light); var babylonLight = new BabylonLight(); RaiseMessage(maxLight.Name, true); babylonLight.name = lightNode.Name; babylonLight.id = lightNode.GetGuid().ToString(); // Type var lightState = Loader.Global.LightState.Create(); maxLight._Light.EvalLightState(0, Interval.Forever._IInterval, lightState); var directionScale = -1; switch (lightState.Type) { case LightType.OmniLgt: babylonLight.type = 0; break; case LightType.SpotLgt: babylonLight.type = 2; babylonLight.angle = (float)(maxLight.GetFallOffSize(0, Interval.Forever) * Math.PI / 180.0f); babylonLight.exponent = 1; break; case LightType.DirectLgt: babylonLight.type = 1; // Shadows if (maxLight.ShadowMethod == 1) { ExportShadowGenerator(lightNode, babylonScene); } break; case LightType.AmbientLgt: babylonLight.type = 3; babylonLight.groundColor = new float[] { 0, 0, 0 }; directionScale = 1; break; } // Position var wm = lightNode.GetWorldMatrix(0, false); var position = wm.Trans; babylonLight.position = position.ToArraySwitched(); // Direction var target = lightNode._Node.Target; if (target != null) { var targetWm = target.GetObjTMBeforeWSM(0, Interval.Forever._IInterval); var targetPosition = targetWm.Trans; var direction = targetPosition.Subtract(position); babylonLight.direction = direction.ToArraySwitched(); } else { var dir = wm.GetRow(2).MultiplyBy(directionScale); babylonLight.direction = dir.ToArraySwitched(); } // Exclusion var maxScene = Kernel.Scene; var inclusion = maxLight._Light.ExclList.TestFlag(1); //NT_INCLUDE var checkExclusionList = maxLight._Light.ExclList.TestFlag(2); //NT_AFFECT_ILLUM if (checkExclusionList) { var list = new List <string>(); foreach (var meshNode in maxScene.NodesListBySuperClass(SuperClassID.GeometricObject)) { if (meshNode._Node.CastShadows == 1) { var inList = maxLight._Light.ExclList.FindNode(meshNode._Node) != -1; if ((!inList && inclusion) || (inList && !inclusion)) { list.Add(meshNode.GetGuid().ToString()); } } } babylonLight.excludedMeshesIds = list.ToArray(); } // Other fields babylonLight.intensity = maxLight.GetIntensity(0, Interval.Forever); babylonLight.diffuse = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Interval.Forever).ToArray() : new float[] { 0, 0, 0 }; babylonLight.specular = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Interval.Forever).ToArray() : new float[] { 0, 0, 0 }; if (maxLight.UseAttenuation) { babylonLight.range = maxLight.GetAttenuation(0, 1, Interval.Forever); } // Animations var animations = new List <BabylonAnimation>(); ExportVector3Animation("position", animations, key => { var worldMatrix = lightNode.GetWorldMatrix(key, lightNode.HasParent()); return(worldMatrix.Trans.ToArraySwitched()); }); ExportVector3Animation("direction", animations, key => { var targetNode = lightNode._Node.Target; if (targetNode != null) { var targetWm = target.GetObjTMBeforeWSM(0, Interval.Forever._IInterval); var targetPosition = targetWm.Trans; var direction = targetPosition.Subtract(position); return(direction.ToArraySwitched()); } var dir = wm.GetRow(2).MultiplyBy(directionScale); return(dir.ToArraySwitched()); }); ExportFloatAnimation("intensity", animations, key => new[] { maxLight.GetIntensity(key, Interval.Forever) }); babylonLight.animations = animations.ToArray(); if (lightNode._Node.GetBoolProperty("babylonjs_autoanimate")) { babylonLight.autoAnimate = true; babylonLight.autoAnimateFrom = (int)lightNode._Node.GetFloatProperty("babylonjs_autoanimate_from"); babylonLight.autoAnimateTo = (int)lightNode._Node.GetFloatProperty("babylonjs_autoanimate_to"); babylonLight.autoAnimateLoop = lightNode._Node.GetBoolProperty("babylonjs_autoanimateloop"); } babylonScene.LightsList.Add(babylonLight); return(babylonLight); }
private void GenerateShadowsGenerator(BabylonLight babylonLight, Light light, float progress) { BabylonLightingFilter shadowMapFilter = BabylonLightingFilter.BlurCloseExponentialShadowMap; int shadowMapSize = 1024; float shadowMapBias = 0.00005f; float normalMapBias = 0.0f; float shadowNearPlane = 0.1f; float shadowFarPlane = 100.0f; bool shadowKernelBlur = false; float shadowBlurKernel = 1.0f; float shadowBlurScale = 2.0f; float shadowBlurOffset = 0.0f; float shadowOrthoScale = 0.1f; float shadowStrengthScale = 1.0f; float shadowDepthScale = 50.0f; float frustumEdgeFalloff = 0.0f; bool forceBackFacesOnly = true; bool transparencyShadow = false; float contactHardening = 0.1f; var shadows = light.gameObject.GetComponent <UnityEditor.ShadowGenerator>(); if (shadows != null && shadows.isActiveAndEnabled) { shadowMapSize = shadows.shadowMapSize; shadowMapBias = shadows.shadowMapBias; normalMapBias = shadows.shadowNormBias; shadowNearPlane = shadows.shadowNearPlane; shadowFarPlane = shadows.shadowFarPlane; shadowMapFilter = shadows.shadowMapFilter; shadowKernelBlur = shadows.shadowKernelBlur; shadowBlurKernel = shadows.shadowBlurKernel; shadowBlurScale = shadows.shadowBlurScale; shadowBlurOffset = shadows.shadowBlurOffset; shadowOrthoScale = shadows.shadowOrthoScale; shadowStrengthScale = shadows.shadowStrengthScale; shadowDepthScale = shadows.shadowDepthScale; forceBackFacesOnly = shadows.forceBackFacesOnly; transparencyShadow = shadows.transparencyShadow; contactHardening = shadows.contactHardening; frustumEdgeFalloff = shadows.frustumEdgeFalloff; } babylonLight.shadowMinZ = shadowNearPlane; babylonLight.shadowMaxZ = shadowFarPlane; if (babylonLight is BabylonDirectionalLight) { ((BabylonDirectionalLight)babylonLight).shadowOrthoScale = shadowOrthoScale; } float strength = light.shadowStrength * shadowStrengthScale; var generator = new BabylonExport.Entities.BabylonShadowGenerator { lightId = GetID(light.gameObject), bias = shadowMapBias, normalBias = normalMapBias, mapSize = shadowMapSize, darkness = (1.0f - strength), depthScale = shadowDepthScale, blurScale = shadowBlurScale, blurKernel = shadowBlurKernel, blurBoxOffset = shadowBlurOffset, useKernelBlur = shadowKernelBlur, forceBackFacesOnly = forceBackFacesOnly, transparencyShadow = transparencyShadow, frustumEdgeFalloff = frustumEdgeFalloff, contactHardeningLightSizeUVRatio = contactHardening }; switch (shadowMapFilter) { case BabylonLightingFilter.PoissonSampling: generator.usePoissonSampling = true; break; case BabylonLightingFilter.ExponentialShadowMap: generator.useExponentialShadowMap = true; break; case BabylonLightingFilter.BlurExponentialShadowMap: generator.useBlurExponentialShadowMap = true; break; case BabylonLightingFilter.CloseExponentialShadowMap: generator.useCloseExponentialShadowMap = true; break; case BabylonLightingFilter.BlurCloseExponentialShadowMap: generator.useBlurCloseExponentialShadowMap = true; break; case BabylonLightingFilter.PercentageCloserFiltering: generator.usePercentageCloserFiltering = true; break; case BabylonLightingFilter.ContactHardeningShadowMap: generator.useContactHardeningShadow = true; break; } // .. // Light Shadow Generator Render List (TODO: Support Specific Meshes Or Layers Or Tags) // .. var renderList = new List <string>(); renderList.Add(rootInstance.id); foreach (var gameObject in gameObjects) { if (gameObject.layer != ExporterWindow.PrefabIndex) { if (!gameObject.IsLightapStatic()) { var meshFilter = gameObject.GetComponent <MeshFilter>(); var meshRender = gameObject.GetComponent <MeshRenderer>(); if (meshFilter != null && meshRender != null && meshRender.enabled == true && meshRender.shadowCastingMode != ShadowCastingMode.Off) { renderList.Add(GetID(gameObject)); continue; } var skinnedMesh = gameObject.GetComponent <SkinnedMeshRenderer>(); if (skinnedMesh != null && skinnedMesh.enabled == true && skinnedMesh.shadowCastingMode != ShadowCastingMode.Off) { renderList.Add(GetID(gameObject)); } } } } generator.renderList = renderList.ToArray(); babylonScene.ShadowGeneratorsList.Add(generator); }