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
132
133
134
135
136
|
#include "sceneparser.h"
#include "scenefilereader.h"
#include <glm/gtx/transform.hpp>
#include <QImage>
#include <iostream>
/**
* @brief Stores the image specified from the input file in this class's
* `std::vector<RGBA> m_image`.
* @param file: file path to an image
* @return True if successfully loads image, False otherwise.
*/
TextureData loadTextureFromFile(const QString &file) {
QImage myTexture;
int width; int height;
if (!myTexture.load(file)) {
std::cout<<"Failed to load in image: " << file.toStdString() << std::endl;
return TextureData{0, 0, nullptr};
}
myTexture = myTexture.convertToFormat(QImage::Format_RGBX8888);
width = myTexture.width();
height = myTexture.height();
RGBA* texture = new RGBA[width*height];
QByteArray arr = QByteArray::fromRawData((const char*) myTexture.bits(), myTexture.sizeInBytes());
for (int i = 0; i < arr.size() / 4.f; i++){
texture[i] = RGBA{(std::uint8_t) arr[4*i], (std::uint8_t) arr[4*i+1], (std::uint8_t) arr[4*i+2], (std::uint8_t) arr[4*i+3]};
}
return TextureData{width, height, texture};
}
// helper to handle recursive creation of tree
void initTree(SceneNode* currentNode, std::vector<RenderShapeData> *shapes, std::vector<SceneLightData> *lights, glm::mat4 currentCTM) {
for (auto t : currentNode->transformations) {
switch (t->type)
{
case TransformationType::TRANSFORMATION_TRANSLATE:
currentCTM *= glm::translate(glm::vec3(t->translate[0], t->translate[1], t->translate[2]));
break;
case TransformationType::TRANSFORMATION_SCALE:
currentCTM *= glm::scale(glm::vec3(t->scale[0], t->scale[1], t->scale[2]));
break;
case TransformationType::TRANSFORMATION_ROTATE:
currentCTM *= glm::rotate(t->angle, glm::vec3(t->rotate[0], t->rotate[1], t->rotate[2]));
break;
case TransformationType::TRANSFORMATION_MATRIX:
currentCTM *= glm::mat4(t->matrix);
break;
default:
std::cout << "Invalid transformation type" << std::endl;
break;
}
}
for(auto primitive : currentNode->primitives) {
primitive->material.textureData = loadTextureFromFile(QString::fromStdString(primitive->material.textureMap.filename));
RenderShapeData rsd = {*primitive, currentCTM, glm::inverse(currentCTM)};
shapes->push_back(rsd);
}
// add the lights
for(auto l : currentNode->lights) {
SceneLightData sld{};
sld.id = l->id;
sld.color = l->color;
sld.function = l->function;
switch (l->type)
{
case LightType::LIGHT_POINT:
sld.type = LightType::LIGHT_POINT;
sld.pos = currentCTM * glm::vec4(0.f, 0.f, 0.f, 1.f);
sld.dir = glm::vec4(0.0f);
break;
case LightType::LIGHT_DIRECTIONAL:
sld.type = LightType::LIGHT_DIRECTIONAL;
sld.pos = glm::vec4(0.0f);
sld.dir = glm::vec4(currentCTM * l->dir);
break;
case LightType::LIGHT_SPOT:
sld.type = LightType::LIGHT_SPOT;
sld.pos = currentCTM * glm::vec4(0.f, 0.f, 0.f, 1.f);
sld.dir = currentCTM * l->dir;
sld.penumbra = l->penumbra;
sld.angle = l->angle;
break;
case LightType::LIGHT_AREA:
sld.type = LightType::LIGHT_AREA;
sld.pos = currentCTM * glm::vec4(0.f, 0.f, 0.f, 1.f);
sld.width = l->width;
sld.height = l->height;
break;
default:
std::cout << "Invalid light type" << std::endl;
continue;
}
lights->push_back(sld);
}
for (auto child : currentNode->children) {
initTree(child, shapes, lights, currentCTM);
}
}
bool SceneParser::parse(std::string filepath, RenderData &renderData) {
ScenefileReader fileReader = ScenefileReader(filepath);
bool success = fileReader.readJSON();
if (!success) {
return false;
}
// TODO: Use your Lab 5 code here
// Task 5: populate renderData with global data, and camera data;
renderData.globalData = fileReader.getGlobalData();
renderData.cameraData = fileReader.getCameraData();
// Task 6: populate renderData's list of primitives and their transforms.
// This will involve traversing the scene graph, and we recommend you
// create a helper function to do so!
SceneNode* root = fileReader.getRootNode();
renderData.shapes.clear();
renderData.lights.clear();
auto currentCTM = glm::mat4(1.0f);
initTree(root, &renderData.shapes, &renderData.lights, currentCTM);
return true;
}
|