rev |
line source |
nuclear@0
|
1 #include "goat3d.h"
|
nuclear@0
|
2 #include "goat3d_impl.h"
|
nuclear@9
|
3 #include "chunk.h"
|
nuclear@11
|
4 #include "node.h"
|
nuclear@0
|
5
|
nuclear@0
|
6 Scene::Scene()
|
nuclear@0
|
7 : name("unnamed"), ambient(0.05, 0.05, 0.05)
|
nuclear@0
|
8 {
|
nuclear@0
|
9 }
|
nuclear@0
|
10
|
nuclear@0
|
11 Scene::~Scene()
|
nuclear@0
|
12 {
|
nuclear@0
|
13 clear();
|
nuclear@0
|
14 }
|
nuclear@0
|
15
|
nuclear@0
|
16 void Scene::clear()
|
nuclear@0
|
17 {
|
nuclear@0
|
18 for(size_t i=0; i<materials.size(); i++) {
|
nuclear@0
|
19 delete materials[i];
|
nuclear@0
|
20 }
|
nuclear@0
|
21 materials.clear();
|
nuclear@0
|
22
|
nuclear@0
|
23 for(size_t i=0; i<meshes.size(); i++) {
|
nuclear@0
|
24 delete meshes[i];
|
nuclear@0
|
25 }
|
nuclear@0
|
26 meshes.clear();
|
nuclear@0
|
27
|
nuclear@0
|
28 for(size_t i=0; i<lights.size(); i++) {
|
nuclear@0
|
29 delete lights[i];
|
nuclear@0
|
30 }
|
nuclear@0
|
31 lights.clear();
|
nuclear@0
|
32
|
nuclear@0
|
33 for(size_t i=0; i<cameras.size(); i++) {
|
nuclear@0
|
34 delete cameras[i];
|
nuclear@0
|
35 }
|
nuclear@0
|
36 cameras.clear();
|
nuclear@0
|
37
|
nuclear@10
|
38 for(size_t i=0; i<objects.size(); i++) {
|
nuclear@10
|
39 delete_node_tree(objects[i]);
|
nuclear@0
|
40 }
|
nuclear@10
|
41 objects.clear();
|
nuclear@0
|
42
|
nuclear@0
|
43 name = "unnamed";
|
nuclear@0
|
44 }
|
nuclear@0
|
45
|
nuclear@0
|
46 void Scene::set_name(const char *name)
|
nuclear@0
|
47 {
|
nuclear@0
|
48 this->name = name;
|
nuclear@0
|
49 }
|
nuclear@0
|
50
|
nuclear@0
|
51 const char *Scene::get_name() const
|
nuclear@0
|
52 {
|
nuclear@0
|
53 return name.c_str();
|
nuclear@0
|
54 }
|
nuclear@8
|
55
|
nuclear@8
|
56 void Scene::set_ambient(const Vector3 &amb)
|
nuclear@8
|
57 {
|
nuclear@8
|
58 ambient = amb;
|
nuclear@8
|
59 }
|
nuclear@8
|
60
|
nuclear@8
|
61 const Vector3 &Scene::get_ambient() const
|
nuclear@8
|
62 {
|
nuclear@8
|
63 return ambient;
|
nuclear@8
|
64 }
|
nuclear@8
|
65
|
nuclear@8
|
66 void Scene::add_material(Material *mat)
|
nuclear@8
|
67 {
|
nuclear@8
|
68 materials.push_back(mat);
|
nuclear@8
|
69 }
|
nuclear@8
|
70
|
nuclear@8
|
71 Material *Scene::get_material(int idx) const
|
nuclear@8
|
72 {
|
nuclear@8
|
73 return idx >=0 && idx < (int)materials.size() ? materials[idx] : 0;
|
nuclear@8
|
74 }
|
nuclear@8
|
75
|
nuclear@8
|
76 Material *Scene::get_material(const char *name) const
|
nuclear@8
|
77 {
|
nuclear@8
|
78 for(size_t i=0; i<materials.size(); i++) {
|
nuclear@8
|
79 if(materials[i]->name == std::string(name)) {
|
nuclear@8
|
80 return materials[i];
|
nuclear@8
|
81 }
|
nuclear@8
|
82 }
|
nuclear@8
|
83 return 0;
|
nuclear@8
|
84 }
|
nuclear@8
|
85
|
nuclear@9
|
86 int Scene::get_material_count() const
|
nuclear@9
|
87 {
|
nuclear@9
|
88 return (int)materials.size();
|
nuclear@9
|
89 }
|
nuclear@9
|
90
|
nuclear@9
|
91
|
nuclear@8
|
92 void Scene::add_mesh(Mesh *mesh)
|
nuclear@8
|
93 {
|
nuclear@8
|
94 meshes.push_back(mesh);
|
nuclear@8
|
95 }
|
nuclear@8
|
96
|
nuclear@8
|
97 Mesh *Scene::get_mesh(int idx) const
|
nuclear@8
|
98 {
|
nuclear@8
|
99 return idx >= 0 && idx < (int)meshes.size() ? meshes[idx] : 0;
|
nuclear@8
|
100 }
|
nuclear@8
|
101
|
nuclear@8
|
102 Mesh *Scene::get_mesh(const char *name) const
|
nuclear@8
|
103 {
|
nuclear@8
|
104 for(size_t i=0; i<meshes.size(); i++) {
|
nuclear@8
|
105 if(meshes[i]->name == std::string(name)) {
|
nuclear@8
|
106 return meshes[i];
|
nuclear@8
|
107 }
|
nuclear@8
|
108 }
|
nuclear@8
|
109 return 0;
|
nuclear@8
|
110 }
|
nuclear@8
|
111
|
nuclear@9
|
112 int Scene::get_mesh_count() const
|
nuclear@9
|
113 {
|
nuclear@9
|
114 return (int)meshes.size();
|
nuclear@9
|
115 }
|
nuclear@9
|
116
|
nuclear@9
|
117
|
nuclear@8
|
118 void Scene::add_light(Light *light)
|
nuclear@8
|
119 {
|
nuclear@8
|
120 lights.push_back(light);
|
nuclear@8
|
121 }
|
nuclear@8
|
122
|
nuclear@8
|
123 Light *Scene::get_light(int idx) const
|
nuclear@8
|
124 {
|
nuclear@8
|
125 return idx >= 0 && idx < (int)lights.size() ? lights[idx] : 0;
|
nuclear@8
|
126 }
|
nuclear@8
|
127
|
nuclear@8
|
128 Light *Scene::get_light(const char *name) const
|
nuclear@8
|
129 {
|
nuclear@8
|
130 for(size_t i=0; i<lights.size(); i++) {
|
nuclear@8
|
131 if(lights[i]->name == std::string(name)) {
|
nuclear@8
|
132 return lights[i];
|
nuclear@8
|
133 }
|
nuclear@8
|
134 }
|
nuclear@8
|
135 return 0;
|
nuclear@8
|
136 }
|
nuclear@8
|
137
|
nuclear@9
|
138 int Scene::get_light_count() const
|
nuclear@9
|
139 {
|
nuclear@9
|
140 return (int)lights.size();
|
nuclear@9
|
141 }
|
nuclear@9
|
142
|
nuclear@9
|
143
|
nuclear@8
|
144 void Scene::add_camera(Camera *cam)
|
nuclear@8
|
145 {
|
nuclear@8
|
146 cameras.push_back(cam);
|
nuclear@8
|
147 }
|
nuclear@8
|
148
|
nuclear@8
|
149 Camera *Scene::get_camera(int idx) const
|
nuclear@8
|
150 {
|
nuclear@8
|
151 return idx >= 0 && idx < (int)cameras.size() ? cameras[idx] : 0;
|
nuclear@8
|
152 }
|
nuclear@8
|
153
|
nuclear@8
|
154 Camera *Scene::get_camera(const char *name) const
|
nuclear@8
|
155 {
|
nuclear@8
|
156 for(size_t i=0; i<cameras.size(); i++) {
|
nuclear@8
|
157 if(cameras[i]->name == std::string(name)) {
|
nuclear@8
|
158 return cameras[i];
|
nuclear@8
|
159 }
|
nuclear@8
|
160 }
|
nuclear@8
|
161 return 0;
|
nuclear@8
|
162 }
|
nuclear@8
|
163
|
nuclear@9
|
164 int Scene::get_camera_count() const
|
nuclear@9
|
165 {
|
nuclear@9
|
166 return (int)cameras.size();
|
nuclear@9
|
167 }
|
nuclear@9
|
168
|
nuclear@9
|
169
|
nuclear@8
|
170 void Scene::add_node(Node *node)
|
nuclear@8
|
171 {
|
nuclear@8
|
172 nodes.push_back(node);
|
nuclear@8
|
173 }
|
nuclear@8
|
174
|
nuclear@8
|
175 Node *Scene::get_node(int idx) const
|
nuclear@8
|
176 {
|
nuclear@8
|
177 return idx >= 0 && idx < (int)nodes.size() ? nodes[idx] : 0;
|
nuclear@8
|
178 }
|
nuclear@8
|
179
|
nuclear@8
|
180 Node *Scene::get_node(const char *name) const
|
nuclear@8
|
181 {
|
nuclear@8
|
182 for(size_t i=0; i<nodes.size(); i++) {
|
nuclear@8
|
183 if(strcmp(nodes[i]->get_name(), name) == 0) {
|
nuclear@8
|
184 return nodes[i];
|
nuclear@8
|
185 }
|
nuclear@8
|
186 }
|
nuclear@8
|
187 return 0;
|
nuclear@8
|
188 }
|
nuclear@8
|
189
|
nuclear@9
|
190 int Scene::get_node_count() const
|
nuclear@9
|
191 {
|
nuclear@9
|
192 return (int)nodes.size();
|
nuclear@9
|
193 }
|
nuclear@9
|
194
|
nuclear@9
|
195
|
nuclear@8
|
196 bool Scene::load(goat3d_io *io)
|
nuclear@8
|
197 {
|
nuclear@8
|
198 return false;
|
nuclear@8
|
199 }
|
nuclear@8
|
200
|
nuclear@9
|
201 static long save_env(const Scene *scn, long offset, goat3d_io *io);
|
nuclear@9
|
202 static long save_materials(const Scene *scn, long offset, goat3d_io *io);
|
nuclear@9
|
203 static long save_material(const Material *mat, long offset, goat3d_io *io);
|
nuclear@9
|
204 static long save_mat_attrib(const char *name, const MaterialAttrib &attr, long offset, goat3d_io *io);
|
nuclear@9
|
205 static long save_meshes(const Scene *scn, long offset, goat3d_io *io);
|
nuclear@9
|
206 static long save_lights(const Scene *scn, long offset, goat3d_io *io);
|
nuclear@9
|
207 static long save_cameras(const Scene *scn, long offset, goat3d_io *io);
|
nuclear@9
|
208 static long save_nodes(const Scene *scn, long offset, goat3d_io *io);
|
nuclear@9
|
209
|
nuclear@9
|
210 static long write_chunk_float(int id, float val, long offs, goat3d_io *io);
|
nuclear@9
|
211 static long write_chunk_float3(int id, const Vector3 &vec, long offs, goat3d_io *io);
|
nuclear@9
|
212 static long write_chunk_float4(int id, const Vector4 &vec, long offs, goat3d_io *io);
|
nuclear@9
|
213
|
nuclear@8
|
214 bool Scene::save(goat3d_io *io) const
|
nuclear@8
|
215 {
|
nuclear@9
|
216 long res;
|
nuclear@9
|
217
|
nuclear@9
|
218 ChunkHeader hdr;
|
nuclear@9
|
219 hdr.id = CNK_SCENE;
|
nuclear@9
|
220 hdr.size = sizeof hdr;
|
nuclear@9
|
221
|
nuclear@9
|
222 if((res = save_env(this, hdr.size, io)) < 0) {
|
nuclear@9
|
223 return false;
|
nuclear@9
|
224 }
|
nuclear@9
|
225 hdr.size += res;
|
nuclear@9
|
226
|
nuclear@9
|
227 if((res = save_materials(this, hdr.size, io)) < 0) {
|
nuclear@9
|
228 return false;
|
nuclear@9
|
229 }
|
nuclear@9
|
230 hdr.size += res;
|
nuclear@9
|
231
|
nuclear@9
|
232 if((res = save_meshes(this, hdr.size, io)) < 0) {
|
nuclear@9
|
233 return false;
|
nuclear@9
|
234 }
|
nuclear@9
|
235 hdr.size += res;
|
nuclear@9
|
236
|
nuclear@9
|
237 if((res = save_lights(this, hdr.size, io)) < 0) {
|
nuclear@9
|
238 return false;
|
nuclear@9
|
239 }
|
nuclear@9
|
240 hdr.size += res;
|
nuclear@9
|
241
|
nuclear@9
|
242 if((res = save_cameras(this, hdr.size, io)) < 0) {
|
nuclear@9
|
243 return false;
|
nuclear@9
|
244 }
|
nuclear@9
|
245 hdr.size += res;
|
nuclear@9
|
246
|
nuclear@9
|
247 if((res = save_nodes(this, hdr.size, io)) < 0) {
|
nuclear@9
|
248 return false;
|
nuclear@9
|
249 }
|
nuclear@9
|
250 hdr.size += res;
|
nuclear@9
|
251
|
nuclear@9
|
252 // now go back and write the root chunk
|
nuclear@9
|
253 io->seek(0, SEEK_SET, io->cls);
|
nuclear@9
|
254 if(io->write(&hdr, sizeof hdr, io->cls) < (ssize_t)sizeof hdr) {
|
nuclear@9
|
255 return false;
|
nuclear@9
|
256 }
|
nuclear@9
|
257
|
nuclear@9
|
258 return true;
|
nuclear@8
|
259 }
|
nuclear@9
|
260
|
nuclear@9
|
261
|
nuclear@9
|
262 static long save_env(const Scene *scn, long offset, goat3d_io *io)
|
nuclear@9
|
263 {
|
nuclear@9
|
264 long res;
|
nuclear@9
|
265
|
nuclear@9
|
266 ChunkHeader hdr;
|
nuclear@9
|
267 hdr.id = CNK_ENV;
|
nuclear@9
|
268 hdr.size = sizeof hdr;
|
nuclear@9
|
269
|
nuclear@9
|
270 if((res = write_chunk_float3(CNK_ENV_AMBIENT, scn->get_ambient(), offset, io)) < 0) {
|
nuclear@9
|
271 return -1;
|
nuclear@9
|
272 }
|
nuclear@9
|
273 hdr.size += res;
|
nuclear@9
|
274
|
nuclear@9
|
275 // TODO add fog chunk
|
nuclear@9
|
276
|
nuclear@9
|
277 io->seek(offset, SEEK_SET, io->cls);
|
nuclear@9
|
278 if(io->write(&hdr, sizeof hdr, io->cls) < (ssize_t)sizeof hdr) {
|
nuclear@9
|
279 return -1;
|
nuclear@9
|
280 }
|
nuclear@9
|
281 return hdr.size;
|
nuclear@9
|
282 }
|
nuclear@9
|
283
|
nuclear@9
|
284 static long save_materials(const Scene *scn, long offset, goat3d_io *io)
|
nuclear@9
|
285 {
|
nuclear@9
|
286 long res;
|
nuclear@9
|
287
|
nuclear@9
|
288 ChunkHeader hdr;
|
nuclear@9
|
289 hdr.id = CNK_MTL_LIST;
|
nuclear@9
|
290 hdr.size = sizeof hdr;
|
nuclear@9
|
291
|
nuclear@9
|
292 for(int i=0; i<scn->get_material_count(); i++) {
|
nuclear@9
|
293 if((res = save_material(scn->get_material(i), offset + hdr.size, io)) < 0) {
|
nuclear@9
|
294 return -1;
|
nuclear@9
|
295 }
|
nuclear@9
|
296 hdr.size += res;
|
nuclear@9
|
297 }
|
nuclear@9
|
298
|
nuclear@9
|
299 io->seek(offset, SEEK_SET, io->cls);
|
nuclear@9
|
300 if(io->write(&hdr, hdr.size, io->cls) < hdr.size) {
|
nuclear@9
|
301 return -1;
|
nuclear@9
|
302 }
|
nuclear@9
|
303 return hdr.size;
|
nuclear@9
|
304 }
|
nuclear@9
|
305
|
nuclear@9
|
306 static long save_material(const Material *mat, long offset, goat3d_io *io)
|
nuclear@9
|
307 {
|
nuclear@9
|
308 long res;
|
nuclear@9
|
309
|
nuclear@9
|
310 ChunkHeader hdr;
|
nuclear@9
|
311 hdr.id = CNK_MTL;
|
nuclear@9
|
312 hdr.size = sizeof hdr;
|
nuclear@9
|
313
|
nuclear@9
|
314 for(int i=0; i<mat->get_attrib_count(); i++) {
|
nuclear@9
|
315 const char *name = mat->get_attrib_name(i);
|
nuclear@9
|
316 if((res = save_mat_attrib(name, (*mat)[i], offset + hdr.size, io)) < 0) {
|
nuclear@9
|
317 return -1;
|
nuclear@9
|
318 }
|
nuclear@9
|
319 hdr.size += res;
|
nuclear@9
|
320 }
|
nuclear@9
|
321
|
nuclear@9
|
322 io->seek(offset, SEEK_SET, io->cls);
|
nuclear@9
|
323 if(io->write(&hdr, hdr.size, io->cls) < hdr.size) {
|
nuclear@9
|
324 return -1;
|
nuclear@9
|
325 }
|
nuclear@9
|
326 return hdr.size;
|
nuclear@9
|
327 }
|
nuclear@9
|
328
|
nuclear@9
|
329 static long save_mat_attrib(const char *name, const MaterialAttrib &attr, long offset, goat3d_io *io)
|
nuclear@9
|
330 {
|
nuclear@9
|
331 long res;
|
nuclear@9
|
332
|
nuclear@9
|
333 ChunkHeader hdr;
|
nuclear@9
|
334 hdr.id = CNK_MTL_ATTR;
|
nuclear@9
|
335 hdr.size = sizeof hdr;
|
nuclear@9
|
336
|
nuclear@9
|
337 // TODO cont.
|
nuclear@9
|
338 return -1;
|
nuclear@9
|
339 }
|
nuclear@9
|
340
|
nuclear@9
|
341 static long save_meshes(const Scene *scn, long offset, goat3d_io *io)
|
nuclear@9
|
342 {
|
nuclear@9
|
343 return 0;
|
nuclear@9
|
344 }
|
nuclear@9
|
345
|
nuclear@9
|
346 static long save_lights(const Scene *scn, long offset, goat3d_io *io)
|
nuclear@9
|
347 {
|
nuclear@9
|
348 return 0;
|
nuclear@9
|
349 }
|
nuclear@9
|
350
|
nuclear@9
|
351 static long save_cameras(const Scene *scn, long offset, goat3d_io *io)
|
nuclear@9
|
352 {
|
nuclear@9
|
353 return 0;
|
nuclear@9
|
354 }
|
nuclear@9
|
355
|
nuclear@9
|
356 static long save_nodes(const Scene *scn, long offset, goat3d_io *io)
|
nuclear@9
|
357 {
|
nuclear@9
|
358 return 0;
|
nuclear@9
|
359 }
|
nuclear@9
|
360
|
nuclear@9
|
361 static long write_chunk_float(int id, float val, long offs, goat3d_io *io)
|
nuclear@9
|
362 {
|
nuclear@9
|
363 int size = sizeof(ChunkHeader) + sizeof val;
|
nuclear@9
|
364 char *buf = (char*)alloca(size);
|
nuclear@9
|
365
|
nuclear@9
|
366 Chunk *c = (Chunk*)buf;
|
nuclear@9
|
367 c->hdr.id = id;
|
nuclear@9
|
368 c->hdr.size = size;
|
nuclear@9
|
369 *(float*)c->data = val;
|
nuclear@9
|
370
|
nuclear@9
|
371 io->seek(offs, SEEK_SET, io->cls);
|
nuclear@9
|
372 if(io->write(buf, size, io->cls) < size) {
|
nuclear@9
|
373 return -1;
|
nuclear@9
|
374 }
|
nuclear@9
|
375 return size;
|
nuclear@9
|
376 }
|
nuclear@9
|
377
|
nuclear@9
|
378 static long write_chunk_float3(int id, const Vector3 &vec, long offs, goat3d_io *io)
|
nuclear@9
|
379 {
|
nuclear@9
|
380 int size = sizeof(ChunkHeader) + sizeof vec;
|
nuclear@9
|
381 char *buf = (char*)alloca(size);
|
nuclear@9
|
382
|
nuclear@9
|
383 Chunk *c = (Chunk*)buf;
|
nuclear@9
|
384 c->hdr.id = id;
|
nuclear@9
|
385 c->hdr.size = size;
|
nuclear@9
|
386 *(Vector3*)c->data = vec;
|
nuclear@9
|
387
|
nuclear@9
|
388 io->seek(offs, SEEK_SET, io->cls);
|
nuclear@9
|
389 if(io->write(buf, size, io->cls) < size) {
|
nuclear@9
|
390 return -1;
|
nuclear@9
|
391 }
|
nuclear@9
|
392 return size;
|
nuclear@9
|
393 }
|
nuclear@9
|
394
|
nuclear@9
|
395 static long write_chunk_float4(int id, const Vector4 &vec, long offs, goat3d_io *io)
|
nuclear@9
|
396 {
|
nuclear@9
|
397 int size = sizeof(ChunkHeader) + sizeof vec;
|
nuclear@9
|
398 char *buf = (char*)alloca(size);
|
nuclear@9
|
399
|
nuclear@9
|
400 Chunk *c = (Chunk*)buf;
|
nuclear@9
|
401 c->hdr.id = id;
|
nuclear@9
|
402 c->hdr.size = size;
|
nuclear@9
|
403 *(Vector4*)c->data = vec;
|
nuclear@9
|
404
|
nuclear@9
|
405 io->seek(offs, SEEK_SET, io->cls);
|
nuclear@9
|
406 if(io->write(buf, size, io->cls) < size) {
|
nuclear@9
|
407 return -1;
|
nuclear@9
|
408 }
|
nuclear@9
|
409 return size;
|
nuclear@9
|
410 }
|