COLLADA lights:

* simplify export and import, now that we have blender profiles for lights. The vanilla import is now more in line with the specs. If a blender profile is found, skip normal import, use the profile data instead.
* multiply energy into color rgb export (common profile).
* recalc distance taking metrics in account
This commit is contained in:
Nathan Letwory
2011-03-30 10:51:01 +00:00
parent 22abd53c7e
commit 2b79378f81
4 changed files with 109 additions and 106 deletions

View File

@@ -863,109 +863,35 @@ bool DocumentImporter::writeLight( const COLLADAFW::Light* light )
{
if(mImportStage!=General)
return true;
Lamp *lamp = NULL;
std::string la_id, la_name;
TagsMap::iterator etit;
ExtraTags *et = 0;
etit = uid_tags_map.find(light->getUniqueId().toAscii());
if(etit != uid_tags_map.end())
et = etit->second;
la_id = light->getOriginalId();
la_name = light->getName();
if (la_name.size()) lamp = (Lamp*)add_lamp((char*)la_name.c_str());
else lamp = (Lamp*)add_lamp((char*)la_id.c_str());
if (!lamp) {
fprintf(stderr, "Cannot create lamp. \n");
return true;
}
if (light->getColor().isValid()) {
COLLADAFW::Color col = light->getColor();
lamp->r = col.getRed();
lamp->g = col.getGreen();
lamp->b = col.getBlue();
}
float constatt = light->getConstantAttenuation().getValue();
float linatt = light->getLinearAttenuation().getValue();
float quadatt = light->getQuadraticAttenuation().getValue();
float d = 25.0f;
float att1 = 0.0f;
float att2 = 0.0f;
float e = 1.0f/constatt;
/* NOTE: We assume for now that inv square is used for quadratic light
* and inv linear for linear light. Exported blender lin/quad weighted
* most likely will result in wrong import. */
/* quadratic light */
if(IS_EQ(linatt, 0.0f) && quadatt > 0.0f) {
//quadatt = att2/(d*d*(e*2));
float invquadatt = 1.0f/quadatt;
float d2 = invquadatt / (2 * e);
d = sqrtf(d2);
}
// linear light
else if(IS_EQ(quadatt, 0.0f) && linatt > 0.0f) {
//linatt = att1/(d*e);
float invlinatt = 1.0f/linatt;
d = invlinatt / e;
} else {
printf("no linear nor quad light, using defaults for attenuation, import will be incorrect: Lamp %s\n", lamp->id.name);
att2 = 1.0f;
}
lamp->dist = d;
lamp->energy = e;
COLLADAFW::Light::LightType type = light->getLightType();
switch(type) {
case COLLADAFW::Light::AMBIENT_LIGHT:
{
lamp->type = LA_HEMI;
}
break;
case COLLADAFW::Light::SPOT_LIGHT:
{
lamp->type = LA_SPOT;
lamp->falloff_type = LA_FALLOFF_INVSQUARE;
lamp->att1 = att1;
lamp->att2 = att2;
lamp->spotsize = light->getFallOffAngle().getValue();
lamp->spotblend = light->getFallOffExponent().getValue();
}
break;
case COLLADAFW::Light::DIRECTIONAL_LIGHT:
{
/* our sun is very strong, so pick a smaller energy level */
lamp->type = LA_SUN;
lamp->energy = 1.0;
lamp->mode |= LA_NO_SPEC;
}
break;
case COLLADAFW::Light::POINT_LIGHT:
{
lamp->type = LA_LOCAL;
lamp->falloff_type = LA_FALLOFF_INVSQUARE;
lamp->att1 = att1;
lamp->att2 = att2;
}
break;
case COLLADAFW::Light::UNDEFINED:
{
fprintf(stderr, "Current lamp type is not supported. \n");
lamp->type = LA_LOCAL;
}
break;
}
if(et) {
// if we find an ExtraTags for this, use that instead.
if(et && et->isProfile("blender")) {
et->setData("type", &(lamp->type));
et->setData("flag", &(lamp->flag));
et->setData("mode", &(lamp->mode));
et->setData("gamma", &(lamp->k));
et->setData("red", &(lamp->r));
et->setData("green", &(lamp->g));
et->setData("blue", &(lamp->b));
et->setData("shadow_r", &(lamp->shdwr));
et->setData("shadow_g", &(lamp->shdwg));
et->setData("shadow_b", &(lamp->shdwb));
@@ -1015,7 +941,83 @@ bool DocumentImporter::writeLight( const COLLADAFW::Light* light )
et->setData("sky_exposure", &(lamp->sky_exposure));
et->setData("sky_colorspace", &(lamp->sky_colorspace));
}
else {
float constatt = light->getConstantAttenuation().getValue();
float linatt = light->getLinearAttenuation().getValue();
float quadatt = light->getQuadraticAttenuation().getValue();
float d = 25.0f;
float att1 = 0.0f;
float att2 = 0.0f;
float e = 1.0f;
if (light->getColor().isValid()) {
COLLADAFW::Color col = light->getColor();
lamp->r = col.getRed();
lamp->g = col.getGreen();
lamp->b = col.getBlue();
}
if(IS_EQ(linatt, 0.0f) && quadatt > 0.0f) {
att2 = quadatt;
d = (1.0f/quadatt) * 2;
}
// linear light
else if(IS_EQ(quadatt, 0.0f) && linatt > 0.0f) {
att1 = linatt;
d = (1.0f/linatt) * 2;
} else if (IS_EQ(constatt, 1.0f)) {
att1 = 1.0f;
} else {
// assuming point light (const att = 1.0);
att1 = 1.0f;
}
d *= ( 1.0f / unit_converter.getLinearMeter());
lamp->energy = e;
lamp->dist = d;
COLLADAFW::Light::LightType type = light->getLightType();
switch(type) {
case COLLADAFW::Light::AMBIENT_LIGHT:
{
lamp->type = LA_HEMI;
}
break;
case COLLADAFW::Light::SPOT_LIGHT:
{
lamp->type = LA_SPOT;
lamp->falloff_type = LA_FALLOFF_INVSQUARE;
lamp->att1 = att1;
lamp->att2 = att2;
lamp->spotsize = light->getFallOffAngle().getValue();
lamp->spotblend = light->getFallOffExponent().getValue();
}
break;
case COLLADAFW::Light::DIRECTIONAL_LIGHT:
{
/* our sun is very strong, so pick a smaller energy level */
lamp->type = LA_SUN;
lamp->mode |= LA_NO_SPEC;
}
break;
case COLLADAFW::Light::POINT_LIGHT:
{
lamp->type = LA_LOCAL;
lamp->falloff_type = LA_FALLOFF_INVSQUARE;
lamp->att1 = att1;
lamp->att2 = att2;
}
break;
case COLLADAFW::Light::UNDEFINED:
{
fprintf(stderr, "Current lamp type is not supported. \n");
lamp->type = LA_LOCAL;
}
break;
}
}
this->uid_lamp_map[light->getUniqueId()] = lamp;
return true;
}

View File

@@ -44,6 +44,11 @@ ExtraTags::~ExtraTags()
{
}
bool ExtraTags::isProfile( std::string profile)
{
return this->profile == profile;
}
bool ExtraTags::addTag( std::string tag, std::string data)
{
tags[tag] = data;

View File

@@ -56,6 +56,9 @@ public:
/** Set given char pointer to value of tag, if it exists. */
void setData(std::string tag, char *data);
/** Return true if the extra tags is for specified profile. */
bool isProfile(std::string profile);
private:
/** Disable default copy constructor. */
ExtraTags( const ExtraTags& pre );

View File

@@ -66,32 +66,22 @@ void LightsExporter::operator()(Object *ob)
Lamp *la = (Lamp*)ob->data;
std::string la_id(get_light_id(ob));
std::string la_name(id_name(la));
COLLADASW::Color col(la->r, la->g, la->b);
float att1, att2;
COLLADASW::Color col(la->r * la->energy, la->g * la->energy, la->b * la->energy);
float e, d, constatt, linatt, quadatt;
att1 = att2 = 0.0f;
float r;
d = la->dist;
r = d/2.0f;
constatt = 1.0f;
if(la->falloff_type==LA_FALLOFF_INVLINEAR) {
att1 = 1.0f;
att2 = 0.0f;
linatt = 1.0f / r;
quadatt = 0.0f;
}
else if(la->falloff_type==LA_FALLOFF_INVSQUARE) {
att1 = 0.0f;
att2 = 1.0f;
}
else if(la->falloff_type==LA_FALLOFF_SLIDERS) {
att1 = la->att1;
att2 = la->att2;
}
e = la->energy;
d = la->dist;
constatt = linatt = quadatt = MAXFLOAT;
if(e > 0.0f) {
constatt = 1.0f/e;
linatt = att1/(d*e);
quadatt = att2/(d*d*(e*2));
else {
linatt = 0.0f;
quadatt = 1.0f / r;
}
// sun
@@ -152,6 +142,9 @@ bool LightsExporter::exportBlenderProfile(COLLADASW::Light &cla, Lamp *la)
cla.addExtraTechniqueParameter("blender", "flag", la->flag);
cla.addExtraTechniqueParameter("blender", "mode", la->mode);
cla.addExtraTechniqueParameter("blender", "gamma", la->k);
cla.addExtraTechniqueParameter("blender", "red", la->r);
cla.addExtraTechniqueParameter("blender", "green", la->g);
cla.addExtraTechniqueParameter("blender", "blue", la->b);
cla.addExtraTechniqueParameter("blender", "shadow_r", la->shdwr);
cla.addExtraTechniqueParameter("blender", "shadow_g", la->shdwg);
cla.addExtraTechniqueParameter("blender", "shadow_b", la->shdwb);