2
Copyright (c) 2008-2009 NetAllied Systems GmbH
4
This file is part of COLLADAMax.
6
Portions of the code are:
7
Copyright (c) 2005-2007 Feeling Software Inc.
8
Copyright (c) 2005-2007 Sony Computer Entertainment America
10
Based on the 3dsMax COLLADASW Tools:
11
Copyright (c) 2005-2006 Autodesk Media Entertainment
13
Licensed under the MIT Open Source License,
14
for details please see LICENSE file or the website
15
http://www.opensource.org/licenses/mit-license.php
19
#include "COLLADAMaxStableHeaders.h"
21
#include "COLLADAMaxLightExporter.h"
23
#include "COLLADAMaxExportSceneGraph.h"
24
#include "COLLADAMaxDocumentExporter.h"
25
#include "COLLADAMaxAnimationExporter.h"
26
#include "COLLADAMaxEffectExporter.h"
27
#include "COLLADAMaxVisualSceneExporter.h"
28
#include "COLLADAMaxExtra.h"
29
#include "COLLADASWLight.h"
37
const String LightExporter::LIGHT_ID_SUFFIX = "-light";
40
const String LightExporter::LIGHT_ELEMENT = "max_light";
41
const String LightExporter::LIGHT_MAP_ELEMENT = "light_map";
42
const int LightExporter::LIGHT_PARAMETER_COUNT = 18;
43
const Extra::ExtraParameter LightExporter::LIGHT_PARAMETERS[] =
45
{TYPE_FLOAT, 1, "multiplier"},
46
{TYPE_FLOAT, 2, "contrast"},
47
{TYPE_FLOAT, 3, "diffuse_soften"},
48
{TYPE_FLOAT, 4, "hotspot_beam"},
49
{TYPE_FLOAT, 5, "falloff"},
50
{TYPE_FLOAT, 6, "aspect_ratio"},
51
{TYPE_FLOAT, 7, "attenuation_near_start"},
52
{TYPE_FLOAT, 8, "attenuation_near_end"},
53
{TYPE_FLOAT, 9, "attenuation_far_start"},
54
{TYPE_FLOAT, 10, "attenuation_far_end"},
55
{TYPE_FLOAT, 11, "decay_falloff"},
56
{TYPE_RGBA, 12, "shadow_color"},
57
{TYPE_INT, 13, "atmosphere_on"},
58
{TYPE_FLOAT, 14, "atmosphere_opacity"},
59
{TYPE_FLOAT, 15, "atmosphere_color_amount"},
60
{TYPE_FLOAT, 16, "shadow_density"},
61
{TYPE_INT, 17, "shadow_map"},
62
{TYPE_FLOAT, 18, "target_distance"}
67
const String LightExporter::SKYLIGHT_ELEMENT = "skylight";
68
const String LightExporter::SKYLIGHT_COLORMAP_ELEMENT = "color_map";
69
const int LightExporter::SKYLIGHT_PARAMETER_COUNT = 10;
70
const Extra::ExtraParameter LightExporter::SKYLIGHT_PARAMETERS[] =
72
//{TYPE_RGBA, 0, "color"}, already exported in the color element of <light>
73
{TYPE_FLOAT, 1, "color_map_amount"},
74
//{TYPE_TEXMAP, 2, "color_map"}, need special handling
75
{TYPE_BOOL, 3, "color_map_on"},
76
{TYPE_INT, 4, "rays_per_sample"},
77
{TYPE_FLOAT, 7, "mode"},
78
{TYPE_FLOAT, 10, "multiplier"},
79
{TYPE_FLOAT, 11, "ray_bias"},
80
{TYPE_BOOL, 12, "cast_shadows"},
81
{TYPE_BOOL, 13, "intensity_on"}
86
const String LightExporter::OVERSHOOT_PARAMETER = "overshoot";
87
const String LightExporter::MULTIPLIER_PARAMETER = "multiplier";
88
const String LightExporter::DECAY_TYPE_PARAMETER = "decay_type";
89
const String LightExporter::DECAY_RADIUS_PARAMETER = "decay_radius";
90
const String LightExporter::USE_FAR_ATTENUATION_PARAMETER = "use_far_attenuation";
91
const String LightExporter::USE_NEAR_ATTENUATION_PARAMETER = "use_near_attenuation";
92
const String LightExporter::NEAR_START_ATTENUATION_PARAMETER = "attenuation_near_start";
93
const String LightExporter::NEAR_END_ATTENUATION_PARAMETER = "attenuation_near_end";
94
const String LightExporter::FAR_START_ATTENUATION_PARAMETER = "attenuation_far_start";
95
const String LightExporter::FAR_END_ATTENUATION_PARAMETER = "attenuation_far_end";
97
const String LightExporter::FALLSIZE_PARAMETER = "decay_falloff";
98
const String LightExporter::HOTSPOT_PARAMETER = "hotspot_beam";
100
const String LightExporter::AFFECT_SPECULAR_PARAMETER = "affect_specular";
101
const String LightExporter::AFFECT_DIFFUSE_PARAMETER = "affect_diffuse";
103
const String LightExporter::SHADOW_ATTRIBS = "shadow_attributes";
104
const String LightExporter::SHADOW_TYPE = "type";
105
const String LightExporter::SHADOW_SIZE = "size";
106
const String LightExporter::SHADOW_TYPE_MAP = "type_map";
107
const String LightExporter::SHADOW_TYPE_RAYTRACE = "type_raytrace";
108
const String LightExporter::SHADOW_AFFECTS_LIST_NODES = "affect_list_nodes";
109
const String LightExporter::SHADOW_AFFECTS_LIST_EXCLUDES = "affect_list_is_exclusive";
110
const String LightExporter::SHADOW_AFFECTS_LIST_ILLUMINATES = "affect_is_illuminated";
111
const String LightExporter::SHADOW_AFFECTS_LIST_CASTS = "affect_casts_shadows";
114
const String LightExporter::SHADOW_MAP = "shadow_map";
115
const String LightExporter::SHADOW_PROJ_IMAGE = "proj_image";
116
const String LightExporter::SHADOW_PROJ_COLOR = "shadow_color";
117
const String LightExporter::SHADOW_PROJ_COLOR_MULT = "shadow_color_mult";
118
const String LightExporter::LIGHT_AFFECTS_SHADOW = "light_affects_shadow";
120
const String LightExporter::ENVIRONMENT_AMBIENT_LIGHT_NAME = "EnvironmentAmbientLight";
121
const String LightExporter::ENVIRONMENT_AMBIENT_LIGHT_ID = "EnvironmentAmbientLight";
124
//---------------------------------------------------------------
125
LightExporter::LightExporter ( COLLADASW::StreamWriter * streamWriter, ExportSceneGraph * exportSceneGraph, DocumentExporter * documentExporter )
126
: COLLADASW::LibraryLights ( streamWriter ),
127
Extra(streamWriter, documentExporter),
128
mExportSceneGraph(exportSceneGraph),
129
mDocumentExporter(documentExporter),
130
mAnimationExporter(documentExporter->getAnimationExporter())
134
//---------------------------------------------------------------
135
String LightExporter::getLightId( const ExportNode& exportNode )
137
return exportNode.getId() + LIGHT_ID_SUFFIX;
141
//---------------------------------------------------------------
142
void LightExporter::doExport()
144
exportEnvironmentAmbientLight();
145
doExport( mExportSceneGraph->getRootExportNode() );
149
//---------------------------------------------------------------
150
void LightExporter::exportEnvironmentAmbientLight()
152
// Add the ambient lighting from the environment settings
153
Point3 ambientColor = mDocumentExporter->getMaxInterface()->GetAmbient(0, FOREVER);
155
COLLADASW::Color ambientLightColor = EffectExporter::maxColor2Color( ambientColor );
157
COLLADASW::AmbientLight ambientLight(COLLADASW::LibraryLights::mSW, ENVIRONMENT_AMBIENT_LIGHT_ID, ENVIRONMENT_AMBIENT_LIGHT_NAME);
159
ambientLight.setColor( ambientLightColor );
160
addLight( ambientLight );
163
//---------------------------------------------------------------
164
void LightExporter::doExport( ExportNode* exportNode )
166
if ( exportNode->getType() == ExportNode::LIGHT )
167
exportLight(exportNode);
169
size_t numberOfChildren = exportNode->getNumberOfChildren();
170
for ( size_t i = 0; i < numberOfChildren; ++i )
171
doExport( exportNode->getChild ( i ) );
175
//---------------------------------------------------------------
176
void LightExporter::exportLight( ExportNode* exportNode )
178
if ( !exportNode->getIsInVisualScene() )
181
String lightId = getLightId(*exportNode);
183
INode * iNode = exportNode->getINode();
185
LightObject* lightObject = (LightObject*) (iNode->GetObjectRef());
190
if ( mDocumentExporter->isExportedObject(ObjectIdentifier(lightObject)) )
193
mDocumentExporter->insertExportedObject(ObjectIdentifier(lightObject), exportNode);
195
// Retrieve the target node, if we are not baking matrices.
196
// Baked matrices must always sample the transform!
197
ULONG ClassId = lightObject->ClassID().PartA();
198
bool isTargeted = !mDocumentExporter->getOptions().getBakeMatrices() && (ClassId == SPOT_LIGHT_CLASS_ID || ClassId == TDIR_LIGHT_CLASS_ID);
200
INode* targetNode = isTargeted ? iNode->GetTarget() : 0;
202
// some lights are not supported at all
205
case FSPOT_LIGHT_CLASS_ID:
206
case SPOT_LIGHT_CLASS_ID:
207
case DIR_LIGHT_CLASS_ID:
208
case TDIR_LIGHT_CLASS_ID:
209
case SKY_LIGHT_CLASS_ID_PART_A:
210
case OMNI_LIGHT_CLASS_ID:
217
// Determine the light's type
219
bool isDirectional = false;
220
bool isPoint = false;
223
COLLADASW::Light::LightType lightType;
227
case FSPOT_LIGHT_CLASS_ID:
228
case SPOT_LIGHT_CLASS_ID:
229
lightType = COLLADASW::Light::SPOT;
232
case DIR_LIGHT_CLASS_ID:
233
case TDIR_LIGHT_CLASS_ID:
234
lightType = COLLADASW::Light::DIRECTIONAL;
235
isDirectional = true;
237
case SKY_LIGHT_CLASS_ID_PART_A:
238
lightType = COLLADASW::Light::POINT;
241
case OMNI_LIGHT_CLASS_ID:
242
lightType = COLLADASW::Light::POINT;
247
COLLADASW::Light * colladaLight = 0;
251
case COLLADASW::Light::DIRECTIONAL:
252
colladaLight = new COLLADASW::DirectionalLight(COLLADASW::LibraryLights::mSW, lightId, COLLADASW::Utils::checkNCName(NativeString(exportNode->getINode()->GetName())));
254
case COLLADASW::Light::POINT:
255
colladaLight = new COLLADASW::PointLight(COLLADASW::LibraryLights::mSW, lightId, COLLADASW::Utils::checkNCName(NativeString(exportNode->getINode()->GetName())));
257
case COLLADASW::Light::SPOT:
258
colladaLight = new COLLADASW::SpotLight(COLLADASW::LibraryLights::mSW, lightId, COLLADASW::Utils::checkNCName(NativeString(exportNode->getINode()->GetName())));
262
// Retrieve the parameter block
263
IParamBlock* parameters = 0;
264
IParamBlock2* parametersSky = 0;
267
parametersSky = (IParamBlock2*) lightObject->GetReference(MaxLight::PBLOCK_REF_SKY);
269
parameters = (IParamBlock*) lightObject->GetReference(MaxLight::PBLOCK_REF);
271
if (!parameters && !parametersSky)
280
bool hasAnimatedColor = mAnimationExporter->addAnimatedParameter(parameters, MaxLight::PB_COLOR, lightId, colladaLight->getColorDefaultSid(), 0 );
281
colladaLight->setColor(EffectExporter::maxColor2Color(parameters->GetColor(MaxLight::PB_COLOR)), hasAnimatedColor);
283
else if (parametersSky )
285
bool hasAnimatedColor = mAnimationExporter->addAnimatedParameter(parametersSky, MaxLight::PB_SKY_COLOR, lightId, colladaLight->getColorDefaultSid(), 0 );
286
colladaLight->setColor(EffectExporter::maxColor2Color(parametersSky->GetColor(MaxLight::PB_SKY_COLOR)), hasAnimatedColor);
290
if (isSpot || isPoint)
292
int decayFunction = parameters->GetInt(isPoint ? MaxLight::PB_DECAY : MaxLight::PB_OMNIDECAY, mDocumentExporter->getOptions().getAnimationStart());
293
switch (decayFunction)
296
colladaLight->setConstantAttenuation(0.0f);
297
colladaLight->setLinearAttenuation(1.0f);
300
colladaLight->setConstantAttenuation(0.0f);
301
colladaLight->setQuadraticAttenuation(1.0f);
305
colladaLight->setConstantAttenuation(1.0f);
311
colladaLight->setConstantAttenuation(1.0f);
314
setExtraTechnique(colladaLight);
319
//addParamBlockAnimatedExtraParameters(LIGHT_ELEMENT, LIGHT_PARAMETERS, LIGHT_PARAMETER_COUNT, parameters, lightId);
322
addParamBlockAnimatedExtraParameters(SKYLIGHT_ELEMENT, SKYLIGHT_PARAMETERS, SKYLIGHT_PARAMETER_COUNT, parametersSky, lightId);
324
// add all the information to extra tag, that are not contained in IParamBlock
325
if (isSpot || isDirectional || isPoint)
327
GenLight* light = (GenLight*)(lightObject);
335
// do not export turned off lights
336
if (light->GetUseLight() != TRUE) {
342
// Export the overshoot flag for directional lights
343
if (isDirectional || isSpot)
345
addExtraChildParameter(LIGHT_ELEMENT, OVERSHOOT_PARAMETER, light->GetOvershoot() != false);
348
addExtraChildParameter(LIGHT_ELEMENT, AFFECT_SPECULAR_PARAMETER, (int)light->GetAffectSpecular());
349
addExtraChildParameter(LIGHT_ELEMENT, AFFECT_DIFFUSE_PARAMETER, (int)light->GetAffectDiffuse());
351
addExtraChildParameter(LIGHT_ELEMENT, DECAY_TYPE_PARAMETER, (int)light->GetDecayType());
352
addExtraChildParameter(LIGHT_ELEMENT, MULTIPLIER_PARAMETER, light->GetIntensity( 0 ));
353
addExtraChildParameter(LIGHT_ELEMENT, DECAY_RADIUS_PARAMETER, light->GetDecayRadius( 0 ));
354
addExtraChildParameter(LIGHT_ELEMENT, USE_NEAR_ATTENUATION_PARAMETER, (light->GetUseAttenNear() != false));
355
addExtraChildParameter(LIGHT_ELEMENT, USE_FAR_ATTENUATION_PARAMETER, (light->GetUseAtten() != false));
356
addExtraChildParameter(LIGHT_ELEMENT, NEAR_START_ATTENUATION_PARAMETER, light->GetAtten( 0, ATTEN1_START ) );
357
addExtraChildParameter(LIGHT_ELEMENT, NEAR_END_ATTENUATION_PARAMETER, light->GetAtten( 0, ATTEN1_END ) );
358
addExtraChildParameter(LIGHT_ELEMENT, FAR_START_ATTENUATION_PARAMETER, light->GetAtten( 0, ATTEN_START ) );
359
addExtraChildParameter(LIGHT_ELEMENT, FAR_END_ATTENUATION_PARAMETER, light->GetAtten( 0, ATTEN_END ) );
362
addExtraChildParameter(LIGHT_ELEMENT, FALLSIZE_PARAMETER, light->GetFallsize( 0 ) );
363
addExtraChildParameter(LIGHT_ELEMENT, HOTSPOT_PARAMETER, light->GetHotspot( 0 ) );
366
exportShadowParameters(light);
368
if (light->GetProjector())
370
Texmap* projectorMap = light->GetProjMap();
373
String imageId = exportTexMap(projectorMap);
374
if ( !imageId.empty() )
376
addExtraChildParameter(LIGHT_ELEMENT, LIGHT_MAP_ELEMENT, "#" + imageId);
385
Texmap *colorMap = parametersSky->GetTexmap(MaxLight::PB_SKY_COLOR_MAP, mDocumentExporter->getOptions().getAnimationStart());
387
String imageId = exportTexMap(colorMap);
388
if ( !imageId.empty())
390
addExtraChildParameter(SKYLIGHT_ELEMENT, SKYLIGHT_COLORMAP_ELEMENT, "#" + imageId);
394
addLight(*colladaLight);
401
void LightExporter::exportShadowParameters(GenLight* light)
403
// Export light shadow attributes
404
if (light->GetShadow())
406
// Light casts shadows
407
int shadowType = light->GetShadowType();
408
if (shadowType == 0) {
409
addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_TYPE, SHADOW_TYPE_MAP);
410
int size = light->GetShadowGenerator()->GetMapSize(0);
411
addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_SIZE, size);
413
else if (shadowType == 1)
414
addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_TYPE, SHADOW_TYPE_RAYTRACE);
417
ExclList& exclusions = light->GetExclusionList();
418
int exclusionsCount = exclusions.Count();
419
if (exclusionsCount > 0)
422
for (int i = 0; i < exclusionsCount; i++)
424
INode* affectedNode = exclusions[i];
428
if ( !nodeURIs.empty() )
431
ExportNode* affectedExportNode = mExportSceneGraph->getExportNode(affectedNode);
432
String nodeURI = '#' + VisualSceneExporter::getNodeId(*affectedExportNode);
435
addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_AFFECTS_LIST_NODES, nodeURIs);
437
if (!exclusions.TestFlag(NT_INCLUDE))
439
addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_AFFECTS_LIST_EXCLUDES, 1);
441
if (exclusions.TestFlag(NT_AFFECT_ILLUM))
443
addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_AFFECTS_LIST_ILLUMINATES, 1);
445
if (exclusions.TestFlag(NT_AFFECT_SHADOWCAST))
447
addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_AFFECTS_LIST_CASTS, 1);
451
// Export our shadow projection map
452
Texmap* shadowProj = light->GetShadowProjMap();
455
IParamBlock* pblock = (IParamBlock*)light->GetReference(MaxLight::PBLOCK_REF);
456
int shadowProjectionOn;
457
pblock->GetValue(MaxLight::PB_OMNISHAD_COLMAP, 0, shadowProjectionOn, Interval::FOREVER);
458
if (shadowProjectionOn)
460
String imageId = exportTexMap(shadowProj);
461
if ( !imageId.empty() )
462
addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_PROJ_IMAGE, "#" + imageId);
466
// Non-animatable is all they get
467
Point3 shadowColor = light->GetShadColor(mDocumentExporter->getOptions().getAnimationStart());
468
String shadowColorString = COLLADASW::Utils::toString(shadowColor.x) + COLLADASW::Utils::toString(shadowColor.y) + COLLADASW::Utils::toString(shadowColor.z);
469
addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_PROJ_COLOR, shadowColorString);
470
addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_PROJ_COLOR_MULT, light->GetShadMult(0));
472
addExtraChildParameter(SHADOW_ATTRIBS, LIGHT_AFFECTS_SHADOW, light->GetLightAffectsShadow());
479
String LightExporter::exportTexMap(Texmap *map)
484
return mDocumentExporter->getEffectExporter()->exportImage(map, fullFileName);