Skip to content

Instantly share code, notes, and snippets.

@borisbat
Created November 5, 2013 05:10
Show Gist options
  • Save borisbat/7314207 to your computer and use it in GitHub Desktop.
Save borisbat/7314207 to your computer and use it in GitHub Desktop.
instanceNodes
///////////////////////////////////////////
// parse library_visual_scenes (nodes) here
void importDaeNodeArray ( const pugi::xpath_node_set & nodes, vector<NodePtr> & outNodes, const WeakNodePtr & parent )
{
using namespace pugi;
if ( nodes.size()==0 )
return;
outNodes.resize(nodes.size());
for ( unsigned int ni=0; ni<nodes.size(); ni++ )
{
const xml_node & node = nodes[ni].node();
NodePtr pNode(new Node());
outNodes[ni] = pNode;
pNode->mParent = parent;
pNode->mDae = mpDae->shared_from_this();
pNode->mId = node.attribute("id").value();
pNode->mName = node.attribute("name").value();
if ( node.attribute("id") )
mpDae->mNodeId2Node[pNode->mId] = pNode;
// check if its joint
pNode->mIsJoint = string(node.attribute("type").value()) == "JOINT";
// sid
// note: according to Remi, its "ass id"
if ( node.attribute("sid") )
if ( nodeSid2Node.find(node.attribute("sid").value())==nodeSid2Node.end() )
nodeSid2Node[node.attribute("sid").value()] = pNode;
else
Log() << TAG::ERROR() << "duplicate node sid=" << node.attribute("sid").value() << TAG::_ERROR() << endl;
// transforms
auto arm = node.select_nodes("matrix");
for ( unsigned int mi=0; mi<arm.size(); mi++ )
{
float4x4simd matrix;
const char * matrix_ptr = arm[mi].node().child_value();
parseMatrix ( matrix, matrix_ptr );
// TODO: verify order
float4x4simd nodeMulMatrix;
Mul ( nodeMulMatrix, matrix, pNode->transform );
pNode->transform = nodeMulMatrix;
}
auto art = node.select_nodes( "translate" );
for ( unsigned int ti=0; ti<art.size(); ti++ )
{
const char * translate_ptr = art[ti].node().child_value();
float x = strtof( translate_ptr, &translate_ptr );
float y = strtof( translate_ptr, &translate_ptr );
float z = strtof( translate_ptr, &translate_ptr );
float4x4simd matrix;
Translation(matrix, x, y, z );
float4x4simd nodeMulMatrix;
Mul ( nodeMulMatrix, matrix, pNode->transform );
pNode->transform = nodeMulMatrix;
}
auto arr = node.select_nodes( "rotate" );
for ( unsigned int ri=0; ri<arr.size(); ri++ )
{
const char * rotate_ptr = arr[ri].node().child_value();
float x = strtof( rotate_ptr, &rotate_ptr );
float y = strtof( rotate_ptr, &rotate_ptr );
float z = strtof( rotate_ptr, &rotate_ptr );
float w = strtof( rotate_ptr, &rotate_ptr );
float4x4simd matrix;
RotationAxis(matrix, Float4simd(x, y, z, 0), Degree2Rad(w) );
float4x4simd nodeMulMatrix;
Mul ( nodeMulMatrix, matrix, pNode->transform );
pNode->transform = nodeMulMatrix;
}
auto ars = node.select_nodes( "scale" );
for ( unsigned int si=0; si<ars.size(); si++ )
{
const char * scale_ptr = ars[si].node().child_value();
float x = strtof( scale_ptr, &scale_ptr );
float y = strtof( scale_ptr, &scale_ptr );
float z = strtof( scale_ptr, &scale_ptr );
float4x4simd matrix;
Scale(matrix, x, y, z );
float4x4simd nodeMulMatrix;
Mul ( nodeMulMatrix, matrix, pNode->transform );
pNode->transform = nodeMulMatrix;
}
// instance geometries
auto geometries = node.select_nodes( "instance_geometry" );
if ( geometries.size() )
{
pNode->mGeometries.resize(geometries.size());
for ( unsigned int ig=0; ig<geometries.size(); ig++ )
{
// make new
InstanceGeometryPtr pInstanceGeometry(new InstanceGeometry());
const xml_node & pig = geometries[ig].node();
string geomId = string(pig.attribute( "url" ).value()).substr(1);
GeometryMap::const_iterator itg = geometryId2Geometry.find(geomId);
if ( itg!=geometryId2Geometry.end() )
{
pInstanceGeometry->mpGeometry = itg->second;
GeometryPtr pGeom = pInstanceGeometry->mpGeometry.lock();
const xml_node & pbm = pig.child("bind_material");
if ( pGeom && pbm )
bindGeomMaterials ( pGeom, pbm );
}
else
Log() << TAG::WARNING() << "referring to unknown geometry " << geomId << TAG::_WARNING() << endl;
pNode->mGeometries[ig] = pInstanceGeometry;
}
}
//handle all extras here
auto extras = node.select_nodes( "extra" );
for ( unsigned int nExtra=0; nExtra<extras.size(); ++nExtra )
{
auto extra = extras[nExtra].node();
auto techniques = extra.select_nodes( "technique" );
for ( unsigned int nTechnique=0; nTechnique<techniques.size(); ++nTechnique )
{
auto technique = techniques[nTechnique].node();
const char * techniqueProfile = technique.attribute( "profile" ).value();
// handle fl4re technique
if ( stricmp(techniqueProfile, "fl4re") == 0 )
{
// instance audio objects
importDaeInstanceAudioObjects(technique, pNode);
importDaeNodeParticleSystem(technique, pNode);
}
}
}
// instance controllers
auto ika = node.select_nodes("instance_controller");
if ( ika.size() )
{
pNode->mInstanceControllers.resize(ika.size());
for ( unsigned int ink=0; ink<ika.size(); ink++ )
{
const xml_node & ikontroller = ika[ink].node();
string url = string(ikontroller.attribute("url").value()).substr(1);
if ( url.size() )
{
InstanceControllerPtr pInstController ( new InstanceController() );
pInstController->mControllerId = url;
// lookup controller
ControllerMap::iterator it = controllerId2Controller.find(pInstController->mControllerId);
if ( it!=controllerId2Controller.end() )
{
pInstController->mpController = it->second;
GeometryPtr pGeom = pInstController->mpController.lock()->mpGeometry.lock();
const xml_node & pbm = ikontroller.child("bind_material");
if ( pGeom && pbm )
bindGeomMaterials ( pGeom, pbm );
}
else
Log() << TAG::ERROR() << "undefined controller instance " << pInstController->mControllerId << TAG::_ERROR() << endl;
// we good
pNode->mInstanceControllers[ink] = pInstController;
}
else
{
Log() << TAG::ERROR() << "instance controller with garbage url" << TAG::_ERROR() << endl;
}
}
}
//
// TODO:
//
// bellow are 3 identical loops
// they vary in few different ways, but the code is very common
// it would be nice to turn it into more or less one function
// it should handle dependencies for cameras and lights too
// it should allow external file cameras and lights
// basically very similar to that node goo
//
// instance nodes
auto ina = node.select_nodes("instance_node");
if ( ina.size() )
{
// lets see how many non-garbage ones are there
for ( unsigned int ini=0; ini<ina.size(); ini++ )
{
const xml_node & inode = ina[ini].node();
string url = string(inode.attribute("url").value());
if ( url.size() )
{
Uri daeUri = resolveUri( Uri(url) );
Uri strippedUri = daeUri.stripped();
// ok, lets test if its really local dependency
// TODO: we need to resolve it right here, right?
if ( strippedUri!=mpDae->mUri )
dependencies.insert(strippedUri);
InstanceNodePtr inp ( new InstanceNode() );
inp->mDaeUri = strippedUri;
inp->mNodeId = daeUri.getFragment();
pNode->mInstanceNodes.push_back(inp);
}
}
}
// instance cameras
auto ica = node.select_nodes("instance_camera");
if ( ica.size() )
{
pNode->mInstanceCameras.resize(ica.size());
for ( unsigned int inc=0; inc<ica.size(); inc++ )
{
const xml_node & icamera = ica[inc].node();
string url = string(icamera.attribute("url").value()).substr(1);
if ( url.size() )
{
InstanceCameraPtr pInstCam ( new InstanceCamera() );
pInstCam->mCameraId = url;
// lookup camera
CameraMap::iterator it = cameraId2Camera.find(pInstCam->mCameraId);
if ( it!=cameraId2Camera.end() )
pInstCam->mpCamera = it->second;
// we good
pNode->mInstanceCameras[inc] = pInstCam;
}
else
{
Log() << TAG::ERROR() << "instance camera with garbage url " << TAG::_ERROR() << endl;
}
}
}
// instance lights
auto ila = node.select_nodes( "instance_light" );
if ( ila.size() )
{
pNode->mInstanceLights.resize(ila.size());
for ( unsigned int inl=0; inl<ila.size(); inl++ )
{
const xml_node & ilight = ila[inl].node();
string url = string(ilight.attribute("url").value()).substr(1);
if ( url.size() )
{
InstanceLightPtr pInstLight ( new InstanceLight() );
pInstLight->mLightId = url;
// lookup light
LightMap::iterator it = lightId2Light.find(pInstLight->mLightId);
if ( it!=lightId2Light.end() )
pInstLight->Set ( it->second );
else
Log() << TAG::ERROR() << "undefined light instance " << pInstLight->mLightId << TAG::_ERROR() << endl;
// we good
pNode->mInstanceLights[inl] = pInstLight;
}
else
{
Log() << TAG::ERROR() << "instance light with garbage url" << TAG::_ERROR() << endl;
}
}
}
// Log() << "Node " << pNode->mId << ", " << pNode->mName << endl << JsValue(pNode->transform) << endl;
// recursively import
importDaeNodeArray(node.select_nodes("node"), pNode->mChildren, pNode);
// build mesh-and-style pairs
// as well as bounding boxes
pNode->BuildMeshAndStyleInfo();
// BBATKIN: SPEAKER!!!
/*
<extra>
<technique profile="fl4re">
<param name="group_id" type="int">4</param>
</technique>
</extra>
*/
if ( const xml_node& extra = node.child("extra") )
{
if ( const xml_node& technique = extra.child("technique") )
{
string profile = technique.attribute("profile").value();
if ( profile=="fl4re" )
{
SpeakerProfilePtr pSpeaker = make_shared<SpeakerProfile>();
pSpeaker->mNodeId = pNode->mId;
auto params = technique.select_nodes("param");
if ( params.size())
{
for ( unsigned int pi=0; pi<params.size(); pi++ )
{
const xml_node & param = params[pi].node();
if ( auto name = param.attribute("name") )
{
string paramname = name.value();
if ( paramname=="group_id" )
{
pSpeaker->mGroupId = stoi ( param.child_value() );
}
else if ( paramname=="type" )
{
pSpeaker->mSpeaker = param.child_value();
}
}
}
}
if ( pSpeaker->mGroupId >= 0 )
mpDae->mLibrarySpeakerProfiles.push_back(pSpeaker);
}
}
}
}
}
void importDaeLibraryNodes ( pugi::xml_node & lnd )
{
if ( !lnd )
return;
importDaeNodeArray ( lnd.select_nodes("node"), mpDae->mLibraryNodes, WeakNodePtr() );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment