summaryrefslogblamecommitdiff
path: root/hw6/src/sceneIO.cpp
blob: 59e586dc5e5fddf16ee02c5538dbee2d8b71669b (plain) (tree)




























































































                                                                                                                                                          
/******************************************************************/
/* 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.
}