//--------------------------------------------------------------- void LightExporter::exportLight( ExportNode* exportNode ) { if ( !exportNode->getIsInVisualScene() ) return; String lightId = getLightId(*exportNode); INode * iNode = exportNode->getINode(); LightObject* lightObject = (LightObject*) (iNode->GetObjectRef()); if ( !lightObject ) return; if ( mDocumentExporter->isExportedObject(ObjectIdentifier(lightObject)) ) return; mDocumentExporter->insertExportedObject(ObjectIdentifier(lightObject), exportNode); // Retrieve the target node, if we are not baking matrices. // Baked matrices must always sample the transform! ULONG ClassId = lightObject->ClassID().PartA(); bool isTargeted = !mDocumentExporter->getOptions().getBakeMatrices() && (ClassId == SPOT_LIGHT_CLASS_ID || ClassId == TDIR_LIGHT_CLASS_ID); INode* targetNode = isTargeted ? iNode->GetTarget() : 0; // some lights are not supported at all switch (ClassId) { case FSPOT_LIGHT_CLASS_ID: case SPOT_LIGHT_CLASS_ID: case DIR_LIGHT_CLASS_ID: case TDIR_LIGHT_CLASS_ID: case SKY_LIGHT_CLASS_ID_PART_A: case OMNI_LIGHT_CLASS_ID: break; default: return; } // Determine the light's type bool isSpot = false; bool isDirectional = false; bool isPoint = false; bool isSky = false; COLLADASW::Light::LightType lightType; switch (ClassId) { case FSPOT_LIGHT_CLASS_ID: case SPOT_LIGHT_CLASS_ID: lightType = COLLADASW::Light::SPOT; isSpot = true; break; case DIR_LIGHT_CLASS_ID: case TDIR_LIGHT_CLASS_ID: lightType = COLLADASW::Light::DIRECTIONAL; isDirectional = true; break; case SKY_LIGHT_CLASS_ID_PART_A: lightType = COLLADASW::Light::POINT; isSky = true; break; case OMNI_LIGHT_CLASS_ID: lightType = COLLADASW::Light::POINT; isPoint = true; break; } COLLADASW::Light * colladaLight = 0; switch ( lightType ) { case COLLADASW::Light::DIRECTIONAL: colladaLight = new COLLADASW::DirectionalLight(COLLADASW::LibraryLights::mSW, lightId, COLLADASW::Utils::checkNCName(NativeString(exportNode->getINode()->GetName()))); break; case COLLADASW::Light::POINT: colladaLight = new COLLADASW::PointLight(COLLADASW::LibraryLights::mSW, lightId, COLLADASW::Utils::checkNCName(NativeString(exportNode->getINode()->GetName()))); break; case COLLADASW::Light::SPOT: colladaLight = new COLLADASW::SpotLight(COLLADASW::LibraryLights::mSW, lightId, COLLADASW::Utils::checkNCName(NativeString(exportNode->getINode()->GetName()))); break; } // Retrieve the parameter block IParamBlock* parameters = 0; IParamBlock2* parametersSky = 0; if (isSky) parametersSky = (IParamBlock2*) lightObject->GetReference(MaxLight::PBLOCK_REF_SKY); else parameters = (IParamBlock*) lightObject->GetReference(MaxLight::PBLOCK_REF); if (!parameters && !parametersSky) { delete colladaLight; return; } if (parameters) { bool hasAnimatedColor = mAnimationExporter->addAnimatedParameter(parameters, MaxLight::PB_COLOR, lightId, colladaLight->getColorDefaultSid(), 0 ); colladaLight->setColor(EffectExporter::maxColor2Color(parameters->GetColor(MaxLight::PB_COLOR)), hasAnimatedColor); } else if (parametersSky ) { bool hasAnimatedColor = mAnimationExporter->addAnimatedParameter(parametersSky, MaxLight::PB_SKY_COLOR, lightId, colladaLight->getColorDefaultSid(), 0 ); colladaLight->setColor(EffectExporter::maxColor2Color(parametersSky->GetColor(MaxLight::PB_SKY_COLOR)), hasAnimatedColor); } if (isSpot || isPoint) { int decayFunction = parameters->GetInt(isPoint ? MaxLight::PB_DECAY : MaxLight::PB_OMNIDECAY, mDocumentExporter->getOptions().getAnimationStart()); switch (decayFunction) { case 1: colladaLight->setConstantAttenuation(0.0f); colladaLight->setLinearAttenuation(1.0f); break; case 2: colladaLight->setConstantAttenuation(0.0f); colladaLight->setQuadraticAttenuation(1.0f); break; case 0: default: colladaLight->setConstantAttenuation(1.0f); break; } } else if (isSky) { colladaLight->setConstantAttenuation(1.0f); } setExtraTechnique(colladaLight); if ( parameters ) addParamBlockAnimatedExtraParameters(LIGHT_ELEMENT, LIGHT_PARAMETERS, LIGHT_PARAMETER_COUNT, parameters, lightId); else addParamBlockAnimatedExtraParameters(SKYLIGHT_ELEMENT, SKYLIGHT_PARAMETERS, SKYLIGHT_PARAMETER_COUNT, parametersSky, lightId); // add all the information to extra tag, that are not contained in IParamBlock if (isSpot || isDirectional || isPoint) { GenLight* light = (GenLight*)(lightObject); if (!light) { delete colladaLight; return; } // Export the overshoot flag for directional lights if (isDirectional || isSpot) { addExtraChildParameter(LIGHT_ELEMENT, OVERSHOOT_PARAMETER, light->GetOvershoot() != false); } addExtraChildParameter(LIGHT_ELEMENT, DECAY_TYPE_PARAMETER, (int)light->GetDecayType()); addExtraChildParameter(LIGHT_ELEMENT, USE_NEAR_ATTENUATION_PARAMETER, (light->GetUseAttenNear() != false)); addExtraChildParameter(LIGHT_ELEMENT, USE_FAR_ATTENUATION_PARAMETER, (light->GetUseAtten() != false)); exportShadowParameters(light); if (light->GetProjector()) { Texmap* projectorMap = light->GetProjMap(); if (projectorMap) { String imageId = exportTexMap(projectorMap); if ( !imageId.empty() ) { addExtraChildParameter(LIGHT_ELEMENT, LIGHT_MAP_ELEMENT, "#" + imageId); } } } } else // isSky { Texmap *colorMap = parametersSky->GetTexmap(MaxLight::PB_SKY_COLOR_MAP, mDocumentExporter->getOptions().getAnimationStart()); String imageId = exportTexMap(colorMap); if ( !imageId.empty()) { addExtraChildParameter(SKYLIGHT_ELEMENT, SKYLIGHT_COLORMAP_ELEMENT, "#" + imageId); } } addLight(*colladaLight); delete colladaLight; }
// ------------------------------------ bool LightExporter::exportLight ( const MDagPath& dagPath ) { if ( !ExportOptions::exportLights() ) return false; MObject lightNode = dagPath.node(); // Retrieve the Maya light object MStatus status; MFnLight lightFn(lightNode, &status); CHECK_STAT(status); if (status != MStatus::kSuccess) return false; // Get the maya light id. String mayaLightId = mDocumentExporter->dagPathToColladaId ( dagPath ); // Generate a COLLADA id for the new object String colladaLightId; // Check if there is an extra attribute "colladaId" and use this as export id. MString attributeValue; DagHelper::getPlugValue ( lightNode, COLLADA_ID_ATTRIBUTE_NAME, attributeValue ); if ( attributeValue != EMPTY_CSTRING ) { // Generate a valid collada name, if necessary. colladaLightId = mDocumentExporter->mayaNameToColladaName ( attributeValue, false ); } else { // Generate a COLLADA id for the new object colladaLightId = mDocumentExporter->dagPathToColladaId ( dagPath ); } // Make the id unique and store it in a map. colladaLightId = mLightIdList.addId ( colladaLightId ); mMayaIdColladaIdMap [ mayaLightId ] = colladaLightId; // Get a pointer to the stream writer. COLLADASW::StreamWriter* streamWriter = mDocumentExporter->getStreamWriter(); // The light name String lightName = mDocumentExporter->dagPathToColladaName ( dagPath ); // Figure out the type of light and create it COLLADASW::Light* light = NULL; MFn::Type type = lightNode.apiType(); switch (type) { case MFn::kAmbientLight: light = new COLLADASW::AmbientLight( streamWriter, colladaLightId, lightName ); break; case MFn::kDirectionalLight: light = new COLLADASW::DirectionalLight( streamWriter, colladaLightId, lightName ); break; case MFn::kSpotLight: light = new COLLADASW::SpotLight( streamWriter, colladaLightId, lightName ); break; case MFn::kPointLight: // Intentional pass-through default: light = new COLLADASW::PointLight( streamWriter, colladaLightId, lightName ); break; } // Export the original maya name. light->addExtraTechniqueParameter ( PROFILE_MAYA, PARAMETER_MAYA_ID, mayaLightId ); // Get a pointer to the animation exporter. AnimationExporter* anim = mDocumentExporter->getAnimationExporter(); bool animated = false; // Color/Intensity are the common attributes of all lights MColor mayaColor = lightFn.color ( &status ); CHECK_STAT(status); COLLADASW::Color lightColor ( mayaColor.r, mayaColor.g, mayaColor.b, mayaColor.a ); animated = anim->addNodeAnimation ( lightNode, ATTR_COLOR, kColour, RGBA_PARAMETERS ); light->setColor( lightColor, animated ); float intensity = lightFn.intensity ( &status ); CHECK_STAT(status); animated = anim->addNodeAnimation ( lightNode, ATTR_INTENSITY, kSingle ); light->setIntensity( intensity, animated ); // Export light intensity light->addExtraTechniqueParameter(PROFILE_MAYA, ATTR_INTENSITY, intensity); // Add the type specific attributes if (lightNode.hasFn(MFn::kNonAmbientLight)) { // Needed Point and Spot light types parameters: Attenuation and Attenuation_Scale // Attenuation in COLLADA is equal to Decay in Maya. MFnNonAmbientLight naLightFn(lightNode); int decayRate = naLightFn.decayRate(&status); CHECK_STAT(status); decayRate = std::min ( decayRate, 2 ); decayRate = std::max ( decayRate, 0 ); light->setConstantAttenuation ( ( decayRate == 0 ) ? 1.0f : 0.0f); light->setLinearAttenuation ( ( decayRate == 1 ) ? 1.0f : 0.0f); light->setQuadraticAttenuation ( ( decayRate == 2 ) ? 1.0f : 0.0f); } else if (lightNode.hasFn(MFn::kAmbientLight)) { MFnAmbientLight ambientLightFn ( lightNode ); float ambientShade = ambientLightFn.ambientShade(); String paramSid = EMPTY_STRING; animated = anim->addNodeAnimation ( lightNode, ATTR_AMBIENT_SHADE, kSingle ); if ( animated ) paramSid = ATTR_AMBIENT_SHADE; light->addExtraTechniqueParameter ( PROFILE_MAYA, MAYA_AMBIENTSHADE_LIGHT_PARAMETER, ambientShade, paramSid ); } if (lightNode.hasFn(MFn::kSpotLight)) { // Put in the needed spot light type attributes : Falloff, Falloff_Scale and Angle MFnSpotLight spotFn(lightNode); float fallOffAngle = COLLADABU::Math::Utils::radToDegF ( (float)spotFn.coneAngle( &status ) ); CHECK_STAT(status); animated = anim->addNodeAnimation ( lightNode, ATTR_CONE_ANGLE, ( SampleType ) ( kSingle | kAngle ) ); light->setFallOffAngle ( fallOffAngle, animated ); light->setFallOffExponent ( 1.0f ); float penumbraValue = COLLADABU::Math::Utils::radToDegF ( (float)spotFn.penumbraAngle( &status ) ); CHECK_STAT(status); animated = anim->addNodeAnimation ( lightNode, ATTR_PENUMBRA_ANGLE, ( SampleType ) ( kSingle | kAngle ) ); // Export spot setting float dropOff = (float)spotFn.dropOff(&status); CHECK_STAT(status); light->addExtraTechniqueParameter(PROFILE_MAYA, MAYA_PENUMBRA_LIGHT_PARAMETER, penumbraValue); light->addExtraTechniqueParameter(PROFILE_MAYA, MAYA_DROPOFF_LIGHT_PARAMETER, dropOff); // TODO // FCDLightTools::LoadPenumbra(light, penumbraValue, colladaLight->GetOuterAngle().GetAnimated()); // TODO // animated = anim->addNodeAnimation ( lightNode, ATTR_DROP_OFF, kSingle ); // light->setDropOff ( (float) spotFn.dropOff ( &status ), animated ); CHECK_MSTATUS(status); } SceneElement* sceneElement = NULL; SceneGraph* sceneGraph = mDocumentExporter->getSceneGraph(); sceneElement = sceneGraph->findElement(dagPath); exportExtraAttributes(sceneElement, light); addLight ( *light ); delete light; return true; }