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