summaryrefslogtreecommitdiff
path: root/hw6/src/sceneIO_light.cpp
blob: d7639703e62c16d4bd98940d825e6ea45b612a91 (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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/******************************************************************/
/* 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 <cassert>

#include "errorMessage.h"
#include "random_number.h"

#include "sceneIO_core.h"
#include "sceneIO_basis.h"
#include "sceneIO_light.h"
#include "sceneIO_texture.h"
#include "sceneIO_material.h"
#include "sceneIO_geometry.h"

#include "spotLightsource.h"
#include "areaLightsource.h"
#include "pointLightsource.h"
#include "directionalLightsource.h"

#include "lightsourceGeometry.h"

static std::shared_ptr<const lightsource_base> importDirectionalLight(const XMLNode& node)
{
  // get properties
  vec3d direction = getVec3d(node, "direction", vec3d(0.0f, 0.0f, 1.0f));
  color power = getColor(node, "power", color(1.0f, 1.0f, 1.0f));
                                
  // Done.
  return std::shared_ptr<const lightsource_base>( new directionalLightsource( direction, power));
}


static std::shared_ptr<const lightsource_base> importPointLight(const XMLNode& node)
{
  // get properties
  vec3d position = getVec3d(node, "position", vec3d(0.0f, 0.0f, 0.0f));
  color power = getColor(node, "power", color(1.0f, 1.0f, 1.0f));
  vec3d attenuation = getVec3d(node, "attenuation", vec3d(0.0f, 0.0f, 1.0f));

  // Done
  return std::shared_ptr<const lightsource_base>( new pointLightsource(position, power, attenuation)); 
}


static std::shared_ptr<const lightsource_base> importSpotLight(const XMLNode& node)
{
  // Get properties
  vec3d position = getVec3d(node, "position", vec3d(0.0f, 0.0f, 0.0f));
  vec3d direction = getVec3d(node, "direction", vec3d(0.0f, 0.0f, 1.0f));
  float cutoff = getFloat(node, "cutoff", 30.0f);
  float sharpness = getFloat(node, "sharpness", 1.0f);
  color power = getColor(node, "power", color(1.0f, 1.0f, 1.0f));
  vec3d attenuation = getVec3d(node, "attenuation", vec3d(0.0f, 0.0f, 1.0f));

  // Done.
  return std::shared_ptr<const lightsource_base>(new spotLightsource( position, direction, cutoff, sharpness, power, attenuation ));
}


static std::shared_ptr<const lightsource_base> importAreaLight(const XMLNode& node, nodeCache<boundedPrimitive>& shape_cache, nodeCache<shader_base>& shader_cache, nodeCache<texture_base>& texture_cache, const std::string& rootDir)
{
  // get properties
  color power = getColor(node, "power", color(1.0f, 1.0f, 1.0f));
  vec3d attenuation = getVec3d(node, "attenuation", vec3d(0.0f, 0.0f, 1.0f));

  // node properties
  std::shared_ptr<const shader_base> reflectanceMaterial;
  std::shared_ptr<const boundedPrimitive> geometry;

  // get children
  for(XMLNode child = node.firstChild(); child.isValid(); child++)
  {
    std::string name = child.name();

    // general child nodes
    auto tempMat = importMaterial(child, shader_cache, texture_cache, rootDir);
    auto tempGeom = importGeometry(child, shape_cache, shader_cache, texture_cache, rootDir);

    // specific child nodes
    if(tempMat) reflectanceMaterial = tempMat;
    else if(tempGeom) geometry = tempGeom;
    else errorMessage("Unknown child-node in areaLightsource (%s).", name.c_str());
  }
  
  // produce warning if shader defined on the geometry
  if(geometry && geometry->hasShader() && !reflectanceMaterial)
    warningMessage("Any shader defined on the geometry are ignored in AreaLightsource. Define a reflectance material explicitely in AreaLightsource instead.");

  // Create
  // 1) light source
  // 2) light source geometry
  std::shared_ptr<const lightsource_base> ls( new areaLightsource(power, geometry, attenuation) );
  std::shared_ptr<boundedPrimitive> lsShape( new lightsourceGeometry(geometry, ls, reflectanceMaterial) );

  // Add lsShape to shape_cache
  char id[32]; sprintf(id, "lightgeometry-%u", random_int());
shape_cache.add(std::string(id), lsShape);

  // Done.
  return ls;
}


std::shared_ptr<const lightsource_base> importLight(const XMLNode& node, nodeCache<boundedPrimitive>& shape_cache, nodeCache<shader_base>& shader_cache, nodeCache<texture_base>& texture_cache, const std::string& rootDir)
{
  // sanity check
  assert(node.name() == "light");

  // get light source type
  std::string type = getString(node, "type", "directional");
 
  // create light source
  std::shared_ptr<const lightsource_base> ls;
  if(type == "directional") ls = importDirectionalLight(node);
  else if(type == "point") ls = importPointLight(node);
  else if(type == "spot") ls = importSpotLight(node);
  else if(type == "area") ls = importAreaLight(node, shape_cache, shader_cache, texture_cache, rootDir);
  else errorMessage("Unknown light source type (%s)", type.c_str());

  // Done.
  return ls;
}