-
Notifications
You must be signed in to change notification settings - Fork 0
/
Scene.cpp
155 lines (147 loc) · 5.36 KB
/
Scene.cpp
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include "Scene.h"
Scene::Scene(xml_node config)
{//constructor for scene. takes an xml_node with the configuration fo this scene.
//read in the path so that the location of the resources are known.
string path = config.attribute("path").value() + string("/");
viewPoint = NULL;
renderer = NULL;
for(xml_node i = config.first_child(); i; i = i.next_sibling())
{//itterate over all the objects in the scene. pulling each one in with no parent.
load(i,NULL,path);
}
}
void Scene::load(xml_node self, Object* parent, string path)
{//this method is a recursive system for loading the scenes. each time the parenting relationship
//goes another step deeper, the recusion does too.
//first off, find out what type of object this is. this will read what it is in from the
//attribute and translate the string into the delta enumerated type.
delta_t name = stringToEnum(self.name());
TRACE(1);
//temporary holder for the instantiation of the new object.
Object* temp;
Event* e;
TRACE(5);
switch(name)
{//switch over all the possibilities. if the object type is one that isn't known, ignore it
//the rest of this is fairly straight forward. create a new whatever object, push
//it on to the vector of the appropriate type.
//if this is the top level, parent is null, so setting parent does nothing. if this isn't
//the top level, this will parent this current object to its parent.
case MODEL:
TRACE(5);
temp = new Model(self,path);
models.push_back((Model*)temp);
((GeoObject*)temp)->setParent((GeoObject*)parent);
break;
case CAMERA:
TRACE(5);
temp = new Camera(self);
cameras.push_back((Camera*)temp);
((GeoObject*)temp)->setParent((GeoObject*)parent);
break;
case PROGRAM:
TRACE(5);
temp = new Program(self,path);
programs.push_back((Program*)temp);
globalRM->AssignID(globalRM->RequestID(),temp);
break;
case EVENT:
TRACE(5);
e = new Event();
if(self.attribute("external").as_bool() && self.attribute("funcID").as_int() != 3)
{
e->receiver = (UID)1;
e->type = EVENT_DELAYED_REQUEST;
e->args[0].datum.v_asInt[0] = self.attribute("funcID").as_int();
e->args[0].datum.v_asInt[1] = self.attribute("binding").as_int();
e->args[1].datum.v_asFloat[0] = self.attribute("arg0").as_float();
e->args[1].datum.v_asFloat[1] = self.attribute("arg1").as_float();
e->args[1].datum.v_asFloat[2] = self.attribute("arg2").as_float();
e->args[1].datum.v_asFloat[3] = self.attribute("arg3").as_float();
strcpy(e->args[2].datum.v_asChar,self.attribute("recv").value());
//printf("LTI: %s\n",e->args[2].datum.v_asChar);
}
else if(self.attribute("funcID").as_int() == 3)
{
e->receiver = (UID)1;
e->type = EVENT_DELAYED_REQUEST;
e->args[0].datum.v_asInt[0] = self.attribute("funcID").as_int();
e->args[0].datum.v_asInt[1] = self.attribute("binding").as_int();
e->args[0].datum.v_asInt[2] = globalRM->LoadMesh((path + string(self.attribute("path").value())).c_str());
e->args[1].datum.v_asFloat[0] = self.attribute("arg0").as_float();
e->args[1].datum.v_asFloat[1] = self.attribute("arg1").as_float();
e->args[1].datum.v_asFloat[2] = self.attribute("arg2").as_float();
strcpy(e->args[2].datum.v_asChar,self.attribute("recv").value());
}
globalRM->RegisterRequest(*e);
break;
default:
TRACE(5);
printf("FAIL!\n");
break;
}
//finally loop through and load all of this object's children. if it doesn't have any, this
//loop never happens. handy no?
for(xml_node i = self.first_child(); i; i = i.next_sibling())
{
TRACE(3);
load(i,temp,path);
}
TRACE(2);
}
void Scene::render()
{
TRACE(2);
if(renderer==NULL) {bindToProgram(0); TRACE(5);}
if(viewPoint == NULL) {viewPoint = cameras[0]; TRACE(5);}
renderer->use();TRACE(3);
glUniformMatrix4fv(renderer->getVP(), 1, GL_FALSE,
glm::value_ptr(viewPoint->getProjection()*viewPoint->view()));TRACE(5);
//this loops through and renders each mesh that is in the vector. I might add a system for
//checking to see if the object is currently flagged to render or not, but for now this
//just gets things onto the screen which is what matters.
for(int i = 0; i < models.size(); i++)
{
TRACE(5);
models[i]->render();
}
TRACE(2);
}
void Scene::bindToProgram(Program *prog, GLint local)
{
//bind the models to the appropriate program. I could have done this in the constructor,
//but this allows for the program to be changed and added later if nescessary. makes things
//easier over all. it just itterates through the models and calls them to bind to prog.
for(int i = 0; i < models.size(); i++)
{
models[i]->bindToProgram(prog,local);
}
}
void Scene::bindToProgram(int val)
{
renderer = programs[val];
GLint local = renderer->getLocal();
//bind the models to a locally saved program. I could have done this in the constructor,
//but this allows for the program to be changed and added later if nescessary. makes things
//easier over all. it just itterates through the models and calls them to bind to prog.
for(int i = 0; i < models.size(); i++)
{
models[i]->bindToProgram(renderer,local);
}
}
bool Scene::onEvent(const Event& event)
{
TRACE(2);
if(event.type == EVENT_SPAWN_OBJECT)
{
TRACE(3);
Object* temp;TRACE(5);
temp = new Model((UID)event.args[0].datum.v_asInt[0],
event.args[0].datum.v_asFloat[1],
event.args[0].datum.v_asFloat[2],
event.args[0].datum.v_asFloat[3]);TRACE(5);
models.push_back((Model*)temp);TRACE(5);
}
return false;
}
/*.S.D.G.*/