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;

	}
Exemple #3
0
// 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;
}