summaryrefslogtreecommitdiff
path: root/hw3/src/sceneIO.cpp
blob: bffff8e2ede79bf5d5f113d453ea8ccccef223d8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/******************************************************************/
/* 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 "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_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<shader_base> shader_cache;
  nodeCache<texture_base> texture_cache;

  // init scene data
  bool autoTuneCamera = false;
  std::unique_ptr<const intersector_factory_base> intersector(new linear_intersector_factory());
 
  // process sceneNode
  for(XMLNode node = sceneNode.firstChild(); node.isValid(); node++)
  {
    // check for general node-types
    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 == "intersector") importIntersector(node, intersector);
    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.
}