void SkeletonExporter::export_light(INode *node) { Control *c; int size_key, sf; ObjectState os; GenLight* light; struct LightState ls; float near_radius, far_radius; Point3 row; Matrix3 mat; os=node->EvalWorldState(0); if (!os.obj) return; // per sicurezza light=(GenLight*)os.obj; // controlliamo se esiste un padre INode *padre=node->GetParentNode(); if ((padre) && (strcmp(padre->GetName(), "Scene Root")!=0)) sf=strlen(padre->GetName())+1; else sf=0; light->EvalLightState(0, FOREVER, &ls); fprintf(fTXT, "Name : %s\n", node->GetName()); switch (ls.type) { case OMNI_LGT: fprintf(fTXT, "Omni light found\n"); // flag padre + nome padre + pivot + NodeTM(0) + // + colore write_chunk_header(fA3D, OMNI_LIGHT_ID, node->GetName(), 4+sf+12+48+12); if (makeRAY) write_chunk_header(fRAY, OMNI_LIGHT_ID, node->GetName(), 4+sf+12+48+12); break; case SPOT_LGT: fprintf(fTXT, "Spot light found\n"); // flag padre + nome padre + pivot + NodeTM(0) + // + colore + falloff + hotspot write_chunk_header(fA3D, SPOT_LIGHT_ID, node->GetName(), 4+sf+12+48+12+8); if (makeRAY) write_chunk_header(fRAY, SPOT_LIGHT_ID, node->GetName(), 4+sf+12+48+12+8); break; } // ----------- scrivo il padre (flag, nome) ------------------ fwrite(&sf, sizeof(int), 1, fA3D); if (sf>0) write_string0(fA3D, padre->GetName()); if (makeRAY) fwrite(&sf, sizeof(int), 1, fRAY); if (makeRAY) if (sf>0) write_string0(fRAY, padre->GetName()); // --------------- scrittura del punto di pivot ---------------- GetPivotOffset(node, &row); fprintf(fTXT, "Pivot point : %f, %f, %f\n", row.x, row.y, row.z); write_point3(&row, fA3D); if (makeRAY) write_point3(&row, fRAY); // ------------------- salviamo la NodeTM(0) --------------------- mat=node->GetNodeTM(0); row=mat.GetRow(3); fprintf(fTXT, "World position : x=%f, y=%f, z=%f\n", row.x, row.y, row.z); write_matrix(&mat, fA3D); if (makeRAY) write_matrix(&mat, fRAY); // -------------------- salviamo il colore ----------------------- fprintf(fTXT, "Color : R=%f, G=%f, B=%f\n", ls.color.r, ls.color.g, ls.color.b); fwrite(&ls.color.r, sizeof(float), 1, fA3D); fwrite(&ls.color.g, sizeof(float), 1, fA3D); fwrite(&ls.color.b, sizeof(float), 1, fA3D); if (makeRAY) fwrite(&ls.color.r, sizeof(float), 1, fRAY); if (makeRAY) fwrite(&ls.color.g, sizeof(float), 1, fRAY); if (makeRAY) fwrite(&ls.color.b, sizeof(float), 1, fRAY); // ---------------------- falloff e hotpsot ---------------------- if (ls.type == SPOT_LGT) { float hotspot = (float)(ls.hotsize*3.14159265358979323846/180.0); float falloff = (float)(ls.fallsize*3.14159265358979323846/180.0); fwrite(&hotspot, sizeof(float), 1, fA3D); if (makeRAY) fwrite(&hotspot, sizeof(float), 1, fRAY); fwrite(&falloff, sizeof(float), 1, fA3D); if (makeRAY) fwrite(&falloff, sizeof(float), 1, fRAY); } fprintf(fTXT, "Intensity : %f\n", ls.intens); // -------------- esportazione tracce di posizione --------------- c=node->GetTMController()->GetPositionController(); if ((c) && (c->NumKeys()>0)) { if (IsTCBControl(c)) size_key=36; else if (IsBezierControl(c)) size_key=40; else size_key=16; fprintf(fTXT, "Light position track present."); write_chunk_header(fA3D, POSITION_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); export_point3_track(c, 1, fA3D); if (makeRAY) write_chunk_header(fRAY, POSITION_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); if (makeRAY) export_point3_track(c, 1, fRAY); } // --------------- esportazione tracce di colore ----------------- c=light->GetColorControl(); if ((c) && (c->NumKeys()>0)) { if (IsTCBControl(c)) size_key=36; else if (IsBezierControl(c)) size_key=40; else size_key=16; fprintf(fTXT, "Light color track present."); write_chunk_header(fA3D, COLOR_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); export_point3_track(c, 1.0f, fA3D); if (makeRAY) write_chunk_header(fRAY, COLOR_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); if (makeRAY) export_point3_track(c, 1.0f, fRAY); } // -------------- esportazione tracce di hotspot ----------------- c=light->GetHotSpotControl(); if ((c) && (c->NumKeys()>0) && (ls.type == SPOT_LGT)) { if (IsTCBControl(c)) size_key=28; else if (IsBezierControl(c)) size_key=16; else size_key=8; fprintf(fTXT, "Light hotspot track present."); write_chunk_header(fA3D, HOTSPOT_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); export_float_track(c, (float)(3.14159265358979323846/180.0), fA3D); // in radianti if (makeRAY) write_chunk_header(fRAY, HOTSPOT_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); if (makeRAY) export_float_track(c, (float)(3.14159265358979323846/180.0), fRAY); // in radianti } // -------------- esportazione tracce di falloff ----------------- c=light->GetFalloffControl(); if ((c) && (c->NumKeys()>0) && (ls.type == SPOT_LGT)) { if (IsTCBControl(c)) size_key=28; else if (IsBezierControl(c)) size_key=16; else size_key=8; fprintf(fTXT, "Light falloff track present."); write_chunk_header(fA3D, FALLOFF_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); export_float_track(c, (float)(3.14159265358979323846/180.0), fA3D); // in radianti if (makeRAY) write_chunk_header(fRAY, FALLOFF_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); if (makeRAY) export_float_track(c, (float)(3.14159265358979323846/180.0), fRAY); // in radianti } // ------------------------- script ADL -------------------------- Mtl *materiale=node->GetMtl(); // NO far + NO near if ((!light->GetUseAttenNear()) && (!light->GetUseAtten())) { far_radius=near_radius=999999; } else // NO far + SI near if ((light->GetUseAttenNear()) && (!light->GetUseAtten())) { near_radius=light->GetAtten(0, ATTEN1_START, FOREVER); far_radius=999999; } else // SI far + NO near if ((!light->GetUseAttenNear()) && (light->GetUseAtten())) { far_radius=light->GetAtten(0, ATTEN_START, FOREVER); near_radius=far_radius; } // SI far + SI near if ((light->GetUseAttenNear()) && (light->GetUseAtten())) { near_radius=light->GetAtten(0, ATTEN1_START, FOREVER); far_radius=light->GetAtten(0, ATTEN_START, FOREVER); } if (makeADL) { fprintf(fADL, " light %c%s%c\n {\n", '"', node->GetName(), '"'); if (materiale) fprintf(fADL, " material=%c%s%c;\n", '"', materiale->GetName(), '"'); else fprintf(fADL, " material=%cNONE%c;\n", '"', '"'); //fprintf(fADL, " scale_x=%c160%c;\n", '"', '"'); //fprintf(fADL, " scale_y=%c160%c;\n", '"', '"'); //fprintf(fADL, " near_radius=%c%f%c;\n", '"', near_radius, '"'); //fprintf(fADL, " far_radius=%c%f%c;\n", '"', far_radius, '"'); switch (light->GetDecayType()) { case 0: fprintf(fADL, " attenuation0=%c1.0%c;\n", '"', '"'); fprintf(fADL, " attenuation1=%c0%c;\n", '"', '"'); fprintf(fADL, " attenuation2=%c0%c;\n", '"', '"'); break; case 1: fprintf(fADL, " attenuation0=%c0%c;\n", '"', '"'); fprintf(fADL, " attenuation1=%c1.0%c;\n", '"', '"'); fprintf(fADL, " attenuation2=%c0%c;\n", '"', '"'); break; case 2: fprintf(fADL, " attenuation0=%c0%c;\n", '"', '"'); fprintf(fADL, " attenuation1=%c0%c;\n", '"', '"'); fprintf(fADL, " attenuation2=%c1.0%c;\n", '"', '"'); break; } char range[20]; my_ftoa(far_radius, range); fprintf(fADL, " max_range=%c%s%c;\n", '"', range, '"'); fprintf(fADL, " }\n\n"); } fprintf(fTXT, "\n\n\n----------------------------------------------------\n"); }
//--------------------------------------------------------------- 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; }
// Build a CLight bool CExportNel::buildLight (GenLight &maxLight, NL3D::CLight& nelLight, INode& node, TimeValue time) { // Eval the light state fot this time Interval valid=NEVER; LightState ls; if (maxLight.EvalLightState(time, valid, &ls)==REF_SUCCEED) { // Set the light mode switch (maxLight.Type()) { case OMNI_LIGHT: nelLight.setMode (CLight::PointLight); break; case TSPOT_LIGHT: case FSPOT_LIGHT: nelLight.setMode (CLight::SpotLight); break; case DIR_LIGHT: case TDIR_LIGHT: nelLight.setMode (CLight::DirectionalLight); break; default: // Not initialized return false; } // *** Set the light color // Get the color CRGBA nelColor; Point3 maxColor=maxLight.GetRGBColor(time); // Mul by multiply CRGBAF nelFColor; nelFColor.R=maxColor.x; nelFColor.G=maxColor.y; nelFColor.B=maxColor.z; nelFColor.A=1.f; nelFColor*=maxLight.GetIntensity(time); nelColor=nelFColor; // Affect the ambiant color ? if (maxLight.GetAmbientOnly()) { nelLight.setAmbiant (nelColor); nelLight.setDiffuse (CRGBA (0,0,0)); nelLight.setSpecular (CRGBA (0,0,0)); } else { nelLight.setAmbiant (CRGBA (0,0,0)); // Affect the diffuse color ? if (maxLight.GetAffectDiffuse()) nelLight.setDiffuse (nelColor); else nelLight.setDiffuse (CRGBA (0,0,0)); // Affect the specular color ? if (maxLight.GetAffectSpecular()) nelLight.setSpecular (nelColor); else nelLight.setSpecular (CRGBA (0,0,0)); } // Set the light position Point3 pos=node.GetNodeTM(time).GetTrans (); CVector position; position.x=pos.x; position.y=pos.y; position.z=pos.z; // Set the position nelLight.setPosition (position); // Set the light direction CVector direction; INode* target=node.GetTarget (); if (target) { // Get the position of the target Point3 posTarget=target->GetNodeTM (time).GetTrans (); CVector positionTarget; positionTarget.x=posTarget.x; positionTarget.y=posTarget.y; positionTarget.z=posTarget.z; // Direction direction=positionTarget-position; direction.normalize (); } else // No target { // Get orientation of the source as direction CMatrix nelMatrix; convertMatrix (nelMatrix, node.GetNodeTM(time)); // Direction is -Z direction=-nelMatrix.getK(); direction.normalize (); } // Set the direction nelLight.setDirection (direction); // Set spot light information nelLight.setCutoff ((float)(NLMISC::Pi*maxLight.GetFallsize(time)/180.f/2.f)); // Compute the exponent value float angle=(float)(NLMISC::Pi*maxLight.GetHotspot(time)/(2.0*180.0)); nelLight.setupSpotExponent (angle); // *** Set attenuation if (maxLight.GetUseAtten()) { float nearAtten = maxLight.GetAtten (time, ATTEN_START); if (nearAtten == 0) nearAtten = 0.1f; nelLight.setupAttenuation (nearAtten, maxLight.GetAtten (time, ATTEN_END)); } else nelLight.setNoAttenuation (); // Initialized return true; } // Not initialized return false; }