Forráskód Böngészése

- fbx: light & camera conversion was missing in assimp, somehow.

Alexander Gessler 13 éve
szülő
commit
1a5bf26e91
3 módosított fájl, 199 hozzáadás és 2 törlés
  1. 132 0
      code/FBXConverter.cpp
  2. 66 1
      code/FBXDocument.h
  3. 1 1
      code/FBXModel.cpp

+ 132 - 0
code/FBXConverter.cpp

@@ -136,6 +136,8 @@ public:
 		std::for_each(meshes.begin(),meshes.end(),Util::delete_fun<aiMesh>());
 		std::for_each(materials.begin(),materials.end(),Util::delete_fun<aiMaterial>());
 		std::for_each(animations.begin(),animations.end(),Util::delete_fun<aiAnimation>());
+		std::for_each(lights.begin(),lights.end(),Util::delete_fun<aiLight>());
+		std::for_each(cameras.begin(),cameras.end(),Util::delete_fun<aiCamera>());
 	}
 
 
@@ -234,6 +236,9 @@ private:
 					// attach sub-nodes
 					ConvertNodes(model->ID(), *nodes_chain.back(), new_abs_transform);
 
+					ConvertLights(*model);
+					ConvertCameras(*model);
+
 					nodes.push_back(nodes_chain.front());	
 					nodes_chain.clear();
 				}
@@ -254,6 +259,117 @@ private:
 	}
 
 
+	// ------------------------------------------------------------------------------------------------
+	void ConvertLights(const Model& model)
+	{
+		const std::vector<const NodeAttribute*>& node_attrs = model.GetAttributes();
+		BOOST_FOREACH(const NodeAttribute* attr, node_attrs) {
+			const Light* const light = dynamic_cast<const Light*>(attr);
+			if(light) {
+				ConvertLight(model, *light);
+			}
+		}
+	}
+
+
+	// ------------------------------------------------------------------------------------------------
+	void ConvertCameras(const Model& model)
+	{
+		const std::vector<const NodeAttribute*>& node_attrs = model.GetAttributes();
+		BOOST_FOREACH(const NodeAttribute* attr, node_attrs) {
+			const Camera* const cam = dynamic_cast<const Camera*>(attr);
+			if(cam) {
+				ConvertCamera(model, *cam);
+			}
+		}
+	}
+
+
+	// ------------------------------------------------------------------------------------------------
+	void ConvertLight(const Model& model, const Light& light)
+	{
+		lights.push_back(new aiLight());
+		aiLight* const out_light = lights.back();
+
+		out_light->mName.Set(FixNodeName(model.Name()));
+
+		const float intensity = light.Intensity();
+		const aiVector3D& col = light.Color();
+
+		out_light->mColorDiffuse = aiColor3D(col.x,col.y,col.z);
+		out_light->mColorDiffuse.r *= intensity;
+		out_light->mColorDiffuse.g *= intensity;
+		out_light->mColorDiffuse.b *= intensity;
+
+		out_light->mColorSpecular = out_light->mColorDiffuse;
+
+		switch(light.LightType())
+		{
+		case Light::Type_Point:
+			out_light->mType = aiLightSource_POINT;
+			break;
+
+		case Light::Type_Directional:
+			out_light->mType = aiLightSource_DIRECTIONAL;
+			break;
+
+		case Light::Type_Spot:
+			out_light->mType = aiLightSource_SPOT;
+			out_light->mAngleOuterCone = AI_DEG_TO_RAD(light.OuterAngle());
+			out_light->mAngleInnerCone = AI_DEG_TO_RAD(light.InnerAngle());
+			break;
+
+		case Light::Type_Area:
+			FBXImporter::LogWarn("cannot represent area light, set to UNDEFINED");
+			out_light->mType = aiLightSource_UNDEFINED;
+			break;
+
+		case Light::Type_Volume:
+			FBXImporter::LogWarn("cannot represent volume light, set to UNDEFINED");
+			out_light->mType = aiLightSource_UNDEFINED;
+			break;
+		default:
+			ai_assert(false);
+		}
+
+		// XXX: how to best convert the near and far decay ranges?
+		switch(light.DecayType())
+		{
+		case Light::Decay_None:
+			out_light->mAttenuationConstant = 1.0f;
+			break;
+		case Light::Decay_Linear:
+			out_light->mAttenuationLinear = 1.0f;
+			break;
+		case Light::Decay_Quadratic:
+			out_light->mAttenuationQuadratic = 1.0f;
+			break;
+		case Light::Decay_Cubic:
+			FBXImporter::LogWarn("cannot represent cubic attenuation, set to Quadratic");
+			out_light->mAttenuationQuadratic = 1.0f;
+			break;
+		default:
+			ai_assert(false);
+		}
+	}
+
+
+	// ------------------------------------------------------------------------------------------------
+	void ConvertCamera(const Model& model, const Camera& cam)
+	{
+		cameras.push_back(new aiCamera());
+		aiCamera* const out_camera = cameras.back();
+
+		out_camera->mName.Set(FixNodeName(model.Name()));
+
+		out_camera->mAspect = cam.AspectWidth();
+		out_camera->mPosition = cam.Position();
+		out_camera->mLookAt = cam.InterestPosition() - out_camera->mPosition;
+
+		out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView());
+	}
+
+
 	// ------------------------------------------------------------------------------------------------
 	// this returns unified names usable within assimp identifiers (i.e. no space characters -
 	// while these would be allowed, they are a potential trouble spot so better not use them).
@@ -2207,6 +2323,20 @@ private:
 
 			std::swap_ranges(animations.begin(),animations.end(),out->mAnimations);
 		}
+
+		if(lights.size()) {
+			out->mLights = new aiLight*[lights.size()]();
+			out->mNumLights = static_cast<unsigned int>(lights.size());
+
+			std::swap_ranges(lights.begin(),lights.end(),out->mLights);
+		}
+
+		if(cameras.size()) {
+			out->mCameras = new aiCamera*[cameras.size()]();
+			out->mNumCameras = static_cast<unsigned int>(cameras.size());
+
+			std::swap_ranges(cameras.begin(),cameras.end(),out->mCameras);
+		}
 	}
 
 
@@ -2218,6 +2348,8 @@ private:
 	std::vector<aiMesh*> meshes;
 	std::vector<aiMaterial*> materials;
 	std::vector<aiAnimation*> animations;
+	std::vector<aiLight*> lights;
+	std::vector<aiCamera*> cameras;
 
 	typedef std::map<const Material*, unsigned int> MaterialMap;
 	MaterialMap materials_converted;

+ 66 - 1
code/FBXDocument.h

@@ -216,9 +216,21 @@ private:
 
 #define fbx_simple_property(name, type, default_value) \
 	type name() const { \
-		return PropertyGet(Props(), fbx_stringize(name), (default_value)); \
+		return PropertyGet<type>(Props(), fbx_stringize(name), (default_value)); \
 	}
 
+// XXX improve logging
+#define fbx_simple_enum_property(name, type, default_value) \
+	type name() const { \
+		const int ival = PropertyGet<int>(Props(), fbx_stringize(name), static_cast<int>(default_value)); \
+		if (ival < 0 || ival >= AI_CONCAT(type, _MAX)) { \
+			ai_assert(static_cast<int>(default_value) >= 0 && static_cast<int>(default_value) < AI_CONCAT(type, _MAX)); \
+			return static_cast<type>(default_value); \
+		} \
+		return static_cast<type>(ival); \
+}
+
+
 
 /** DOM base class for FBX cameras attached to a node */
 class Camera : public NodeAttribute
@@ -257,10 +269,63 @@ public:
 	Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
 	~Light();
 
+public:
+
+	enum Type
+	{
+		Type_Point,
+		Type_Directional,
+		Type_Spot,
+		Type_Area,
+		Type_Volume,
+
+		Type_MAX // end-of-enum sentinel
+	};
+
+	enum Decay
+	{
+		Decay_None,
+		Decay_Linear,
+		Decay_Quadratic,
+		Decay_Cubic,
+
+		Decay_MAX // end-of-enum sentinel
+	};
+
 public:
 
 	fbx_simple_property(Color, aiVector3D, aiVector3D(1,1,1));
+	fbx_simple_enum_property(LightType, Type, 0);
+	fbx_simple_property(CastLightOnObject, bool, false);
+	fbx_simple_property(DrawVolumetricLight, bool, true);
+	fbx_simple_property(DrawGroundProjection, bool, true);
+	fbx_simple_property(DrawFrontFacingVolumetricLight, bool, false);
 	fbx_simple_property(Intensity, float, 1.0f);
+	fbx_simple_property(InnerAngle, float, 0.0f);
+	fbx_simple_property(OuterAngle, float, 45.0f);
+	fbx_simple_property(Fog, int, 50);
+	fbx_simple_enum_property(DecayType, Decay, 0);
+	fbx_simple_property(DecayStart, int, 0);
+	fbx_simple_property(FileName, std::string, "");
+
+	fbx_simple_property(EnableNearAttenuation, bool, false);
+	fbx_simple_property(NearAttenuationStart, float, 0.0f);
+	fbx_simple_property(NearAttenuationEnd, float, 0.0f);
+	fbx_simple_property(EnableFarAttenuation, bool, false);
+	fbx_simple_property(FarAttenuationStart, float, 0.0f);
+	fbx_simple_property(FarAttenuationEnd, float, 0.0f);
+
+	fbx_simple_property(CastShadows, bool, true);
+	fbx_simple_property(ShadowColor, aiVector3D, aiVector3D(0,0,0));
+
+	fbx_simple_property(AreaLightShape, int, 0);
+
+	fbx_simple_property(LeftBarnDoor, float, 20.0f);
+	fbx_simple_property(RightBarnDoor, float, 20.0f);
+	fbx_simple_property(TopBarnDoor, float, 20.0f);
+	fbx_simple_property(BottomBarnDoor, float, 20.0f);
+	fbx_simple_property(EnableBarnDoor, bool, true);
+
 
 private:
 };

+ 1 - 1
code/FBXModel.cpp

@@ -92,7 +92,7 @@ void Model::ResolveLinks(const Element& element, const Document& doc)
 	const char* const arr[] = {"Geometry","Material","NodeAttribute"};
 
 	// resolve material
-	const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),arr, 2);
+	const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),arr, 3);
 
 	materials.reserve(conns.size());
 	geometry.reserve(conns.size());