Beispiel #1
0
// ------------------------------------------------------------------------------------------------
// Recursively build the scenegraph
void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<AttachmentInfo>& attach,
	BatchLoader& batch,
	aiCamera**& camOut,
	aiLight**& lightOut, 
	std::vector<aiNodeAnim*>& animOut)
{
	// Setup a very cryptic name for the node, we want the user to be happy
	SetupNodeName(nd,src);

	// If this is an object from an external file - get the scene and setup proper attachment tags
	aiScene* obj = NULL;
	if (src.type == LWS::NodeDesc::OBJECT && src.path.length() ) {
		obj = batch.GetImport(src.id);
		if (!obj) {
			DefaultLogger::get()->error("LWS: Failed to read external file " + src.path);
		}
		else {
			attach.push_back(AttachmentInfo(obj,nd));
		}
	}

	// If object is a light source - setup a corresponding ai structure
	else if (src.type == LWS::NodeDesc::LIGHT) {
		aiLight* lit = *lightOut++ = new aiLight();

		// compute final light color
		lit->mColorDiffuse = lit->mColorSpecular = src.lightColor*src.lightIntensity;

		// name to attach light to node -> unique due to LWs indexing system
		lit->mName = nd->mName;

		// detemine light type and setup additional members
		if (src.lightType == 2) { /* spot light */

			lit->mType = aiLightSource_SPOT;
			lit->mAngleInnerCone = (float)AI_DEG_TO_RAD( src.lightConeAngle );
			lit->mAngleOuterCone = lit->mAngleInnerCone+(float)AI_DEG_TO_RAD( src.lightEdgeAngle );

		}
		else if (src.lightType == 1) { /* directional light source */
			lit->mType = aiLightSource_DIRECTIONAL;
		}
		else lit->mType = aiLightSource_POINT;

		// fixme: no proper handling of light falloffs yet
		if (src.lightFalloffType == 1)
			lit->mAttenuationConstant = 1.f;
		else if (src.lightFalloffType == 1)
			lit->mAttenuationLinear = 1.f;
		else 
			lit->mAttenuationQuadratic = 1.f;
	}

	// If object is a camera - setup a corresponding ai structure
	else if (src.type == LWS::NodeDesc::CAMERA) {
		aiCamera* cam = *camOut++ = new aiCamera();

		// name to attach cam to node -> unique due to LWs indexing system
		cam->mName = nd->mName;
	}

	// Get the node transformation from the LWO key
	LWO::AnimResolver resolver(src.channels,fps);
	resolver.ExtractBindPose(nd->mTransformation);

	// .. and construct animation channels
	aiNodeAnim* anim = NULL;

	if (first != last) {
		resolver.SetAnimationRange(first,last);
		resolver.ExtractAnimChannel(&anim,AI_LWO_ANIM_FLAG_SAMPLE_ANIMS|AI_LWO_ANIM_FLAG_START_AT_ZERO);
		if (anim) {
			anim->mNodeName = nd->mName;
			animOut.push_back(anim);
		}
	}

	// process pivot point, if any
	if (src.pivotPos != aiVector3D()) {
		aiMatrix4x4 tmp;
		aiMatrix4x4::Translation(-src.pivotPos,tmp);

		if (anim) {
		
			// We have an animation channel for this node. Problem: to combine the pivot
			// point with the node anims, we'd need to interpolate *all* keys, get 
			// transformation matrices from them, apply the translation and decompose
			// the resulting matrices again in order to reconstruct the keys. This 
			// solution here is *much* easier ... we're just inserting an extra node
			// in the hierarchy.
			// Maybe the final optimization here will be done during postprocessing.

			aiNode* pivot = new aiNode();
			pivot->mName.length = sprintf( pivot->mName.data, "$Pivot_%s",nd->mName.data);
			pivot->mTransformation = tmp;

			pivot->mChildren = new aiNode*[pivot->mNumChildren = 1];
			pivot->mChildren[0] = nd;

			pivot->mParent = nd->mParent;
			nd->mParent    = pivot;
			
			// swap children and hope the parents wont see a huge difference
			pivot->mParent->mChildren[pivot->mParent->mNumChildren-1] = pivot;
		}
		else {
			nd->mTransformation = tmp*nd->mTransformation;
		}
	}

	// Add children
	if (src.children.size()) {
		nd->mChildren = new aiNode*[src.children.size()];
		for (std::list<LWS::NodeDesc*>::iterator it = src.children.begin(); it != src.children.end(); ++it) {
			aiNode* ndd = nd->mChildren[nd->mNumChildren++] = new aiNode();
			ndd->mParent = nd;

			BuildGraph(ndd,**it,attach,batch,camOut,lightOut,animOut);
		}
	}
}
// ------------------------------------------------------------------------------------------------
// Recursively build the scenegraph
void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<AttachmentInfo>& attach,
	BatchLoader& batch,
	aiCamera**& camOut,
	aiLight**& lightOut, 
	std::vector<aiNodeAnim*>& animOut)
{
	// Setup a very cryptic name for the node, we want the user to be happy
	SetupNodeName(nd,src);
    aiNode* ndAnim = nd;

	// If the node is an object
	if (src.type == LWS::NodeDesc::OBJECT) {

		// If the object is from an external file, get it
		aiScene* obj = NULL;
        if (src.path.length() ) {
            obj = batch.GetImport(src.id);
            if (!obj) {
                DefaultLogger::get()->error("LWS: Failed to read external file " + src.path);
            }
            else {
                if (obj->mRootNode->mNumChildren == 1) {
					
                    //If the pivot is not set for this layer, get it from the external object
                    if (!src.isPivotSet) {
                        src.pivotPos.x = +obj->mRootNode->mTransformation.a4;
                        src.pivotPos.y = +obj->mRootNode->mTransformation.b4;
                        src.pivotPos.z = -obj->mRootNode->mTransformation.c4; //The sign is the RH to LH back conversion
                    }
					
                    //Remove first node from obj (the old pivot), reset transform of second node (the mesh node)
                    aiNode* newRootNode = obj->mRootNode->mChildren[0];
					obj->mRootNode->mChildren[0] = NULL;
					delete obj->mRootNode;

                    obj->mRootNode = newRootNode;
                    obj->mRootNode->mTransformation.a4 = 0.0;
                    obj->mRootNode->mTransformation.b4 = 0.0;
                    obj->mRootNode->mTransformation.c4 = 0.0;
                }
            }
        }
		
		//Setup the pivot node (also the animation node), the one we received
        nd->mName = std::string("Pivot:") + nd->mName.data;
		ndAnim = nd;
		
        //Add the attachment node to it
        nd->mNumChildren = 1;
        nd->mChildren = new aiNode*[1];
        nd->mChildren[0] = new aiNode();
        nd->mChildren[0]->mParent = nd;
        nd->mChildren[0]->mTransformation.a4 = -src.pivotPos.x;
        nd->mChildren[0]->mTransformation.b4 = -src.pivotPos.y;
        nd->mChildren[0]->mTransformation.c4 = -src.pivotPos.z;
		SetupNodeName(nd->mChildren[0], src);
		
		//Update the attachment node
		nd = nd->mChildren[0];
		
        //Push attachment, if the object came from an external file
        if (obj) {
            attach.push_back(AttachmentInfo(obj,nd));
        }
    }

	// If object is a light source - setup a corresponding ai structure
	else if (src.type == LWS::NodeDesc::LIGHT) {
		aiLight* lit = *lightOut++ = new aiLight();

		// compute final light color
		lit->mColorDiffuse = lit->mColorSpecular = src.lightColor*src.lightIntensity;

		// name to attach light to node -> unique due to LWs indexing system
		lit->mName = nd->mName;

		// detemine light type and setup additional members
		if (src.lightType == 2) { /* spot light */

			lit->mType = aiLightSource_SPOT;
			lit->mAngleInnerCone = (float)AI_DEG_TO_RAD( src.lightConeAngle );
			lit->mAngleOuterCone = lit->mAngleInnerCone+(float)AI_DEG_TO_RAD( src.lightEdgeAngle );

		}
		else if (src.lightType == 1) { /* directional light source */
			lit->mType = aiLightSource_DIRECTIONAL;
		}
		else lit->mType = aiLightSource_POINT;

		// fixme: no proper handling of light falloffs yet
		if (src.lightFalloffType == 1)
			lit->mAttenuationConstant = 1.f;
		else if (src.lightFalloffType == 1)
			lit->mAttenuationLinear = 1.f;
		else 
			lit->mAttenuationQuadratic = 1.f;
	}

	// If object is a camera - setup a corresponding ai structure
	else if (src.type == LWS::NodeDesc::CAMERA) {
		aiCamera* cam = *camOut++ = new aiCamera();

		// name to attach cam to node -> unique due to LWs indexing system
		cam->mName = nd->mName;
	}

	// Get the node transformation from the LWO key
	LWO::AnimResolver resolver(src.channels,fps);
	resolver.ExtractBindPose(ndAnim->mTransformation);

	// .. and construct animation channels
	aiNodeAnim* anim = NULL;

	if (first != last) {
		resolver.SetAnimationRange(first,last);
		resolver.ExtractAnimChannel(&anim,AI_LWO_ANIM_FLAG_SAMPLE_ANIMS|AI_LWO_ANIM_FLAG_START_AT_ZERO);
		if (anim) {
			anim->mNodeName = ndAnim->mName;
			animOut.push_back(anim);
		}
	}

	// Add children
	if (src.children.size()) {
		nd->mChildren = new aiNode*[src.children.size()];
		for (std::list<LWS::NodeDesc*>::iterator it = src.children.begin(); it != src.children.end(); ++it) {
			aiNode* ndd = nd->mChildren[nd->mNumChildren++] = new aiNode();
			ndd->mParent = nd;

			BuildGraph(ndd,**it,attach,batch,camOut,lightOut,animOut);
		}
	}
}