/******************************************************************/
/* This file is part of the homework assignments for CSCI-427/527 */
/* at The College of William & Mary and authored by Pieter Peers. */
/* No part of this file, whether altered or in original form, can */
/* be distributed or used outside the context of CSCI-427/527 */
/* without consent of either the College of William & Mary or */
/* Pieter Peers. */
/******************************************************************/
#include "util.h"
#include "scene.h"
#include "raycasting.h"
#include "sceneGraphNode.h"
#include "linear_intersector.h"
#include "sceneIO_xml.h"
#include "sceneIO_core.h"
#include "sceneIO_cache.h"
#include "sceneIO_basis.h"
#include "sceneIO_light.h"
#include "sceneIO_texture.h"
#include "sceneIO_geometry.h"
#include "sceneIO_material.h"
void importScene(const std::string& filename, scene& s)
{
// get root
std::string rootDir = getDirectory(filename);
// open xml
XMLNode sceneNode(filename);
// check if valid scene node
if(!sceneNode.isValid())
errorMessage("Failed to find 'scene' in %s.", filename.c_str());
// create sceneGraphNode, texture, and shader cache
nodeCache<boundedPrimitive> shape_cache;
nodeCache<texture_base> texture_cache;
nodeCache<shader_base> shader_cache;
// init scene data
bool autoTuneCamera = false;
std::unique_ptr<const intersector_factory_base> intersector(new linear_intersector_factory());
s._renderEngine = std::unique_ptr<const render_base>(new raycasting());
// process sceneNode
for(XMLNode node = sceneNode.firstChild(); node.isValid(); node++)
{
// check for general node-types
if(importTexture(node, texture_cache, rootDir)) continue;
if(importMaterial(node, shader_cache, texture_cache, rootDir)) continue;
if(importGeometry(node, shape_cache, shader_cache, texture_cache, rootDir)) continue;
// check for scene-root specific nodes
std::string nodeName = node.name();
if(nodeName == "camera") autoTuneCamera = importCamera(node, s._camera);
else if(nodeName == "light") s._lightsources.push_back( importLight(node, shape_cache, shader_cache, texture_cache, rootDir) );
else if(nodeName == "environmentMap") importEnvironmentMap(node, texture_cache, rootDir, s._environmentMap);
else if(nodeName == "intersector") importIntersector(node, intersector);
else if(nodeName == "renderer") importRenderEngine(node, s._renderEngine);
else errorMessage("Unknown node in scene xml: '%s'", nodeName.c_str());
}
// initialize all node's intersectors
auto nodeList = shape_cache.allNodes();
for(auto itr=nodeList.begin(); itr != nodeList.end(); itr++)
static_cast<boundedCompound*>(itr->get())->initialize(*intersector);
nodeList.clear();
// add all unreferences nodes to the _sceneGraphRoot.
// Note: remove any node without a shader
decltype(nodeList) unusedNodes;
nodeList = shape_cache.unusedNodes();
while(!nodeList.empty())
{
auto bck = nodeList.back();
if(bck->hasShader()) unusedNodes.push_back(bck);
nodeList.pop_back();
}
// -> init + add
std::unique_ptr<boundedCompound> root(new sceneGraphNode( *(reinterpret_cast< std::vector<std::shared_ptr<const boundedPrimitive>>* >(&unusedNodes)) ));
root->initialize(*intersector);
s._sceneGraphRoot = std::unique_ptr<const boundedCompound>(root.release());
// Auto Tune Camera is requested
if(autoTuneCamera)
s._camera.frameBoundingBox( s._sceneGraphRoot->boundingbox() );
// Done.
}