goat3d
view src/scene.cc @ 78:53ea5b25426e
progress
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 08 May 2014 16:25:04 +0300 |
parents | ab66cdabf6f2 |
children |
line source
1 /*
2 goat3d - 3D scene, character, and animation file format library.
3 Copyright (C) 2013-2014 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include <stdarg.h>
19 #include "goat3d.h"
20 #include "goat3d_impl.h"
21 #include "chunk.h"
23 using namespace g3dimpl;
25 Scene::Scene()
26 : name("unnamed"), ambient(0.05, 0.05, 0.05)
27 {
28 goat = 0;
29 bbox_valid = false;
30 }
32 Scene::~Scene()
33 {
34 clear();
35 }
37 void Scene::clear()
38 {
39 for(size_t i=0; i<materials.size(); i++) {
40 delete materials[i];
41 }
42 materials.clear();
44 for(size_t i=0; i<meshes.size(); i++) {
45 delete meshes[i];
46 }
47 meshes.clear();
49 for(size_t i=0; i<lights.size(); i++) {
50 delete lights[i];
51 }
52 lights.clear();
54 for(size_t i=0; i<cameras.size(); i++) {
55 delete cameras[i];
56 }
57 cameras.clear();
59 for(size_t i=0; i<nodes.size(); i++) {
60 delete nodes[i];
61 }
62 nodes.clear();
64 name = "unnamed";
65 bbox_valid = false;
66 }
68 void Scene::set_name(const char *name)
69 {
70 this->name = name;
71 }
73 const char *Scene::get_name() const
74 {
75 return name.c_str();
76 }
78 void Scene::set_ambient(const Vector3 &amb)
79 {
80 ambient = amb;
81 }
83 const Vector3 &Scene::get_ambient() const
84 {
85 return ambient;
86 }
88 void Scene::add_material(Material *mat)
89 {
90 if(mat->name.empty()) {
91 char buf[64];
92 sprintf(buf, "material%04d", (int)materials.size());
93 mat->name = std::string(buf);
94 }
95 materials.push_back(mat);
96 }
98 Material *Scene::get_material(int idx) const
99 {
100 return idx >=0 && idx < (int)materials.size() ? materials[idx] : 0;
101 }
103 Material *Scene::get_material(const char *name) const
104 {
105 for(size_t i=0; i<materials.size(); i++) {
106 if(materials[i]->name == std::string(name)) {
107 return materials[i];
108 }
109 }
110 return 0;
111 }
113 int Scene::get_material_count() const
114 {
115 return (int)materials.size();
116 }
119 void Scene::add_mesh(Mesh *mesh)
120 {
121 if(mesh->name.empty()) {
122 char buf[64];
123 sprintf(buf, "mesh%04d", (int)meshes.size());
124 mesh->name = std::string(buf);
125 }
126 meshes.push_back(mesh);
127 }
129 Mesh *Scene::get_mesh(int idx) const
130 {
131 return idx >= 0 && idx < (int)meshes.size() ? meshes[idx] : 0;
132 }
134 Mesh *Scene::get_mesh(const char *name) const
135 {
136 for(size_t i=0; i<meshes.size(); i++) {
137 if(meshes[i]->name == std::string(name)) {
138 return meshes[i];
139 }
140 }
141 return 0;
142 }
144 int Scene::get_mesh_count() const
145 {
146 return (int)meshes.size();
147 }
150 void Scene::add_light(Light *light)
151 {
152 lights.push_back(light);
153 }
155 Light *Scene::get_light(int idx) const
156 {
157 return idx >= 0 && idx < (int)lights.size() ? lights[idx] : 0;
158 }
160 Light *Scene::get_light(const char *name) const
161 {
162 for(size_t i=0; i<lights.size(); i++) {
163 if(lights[i]->name == std::string(name)) {
164 return lights[i];
165 }
166 }
167 return 0;
168 }
170 int Scene::get_light_count() const
171 {
172 return (int)lights.size();
173 }
176 void Scene::add_camera(Camera *cam)
177 {
178 cameras.push_back(cam);
179 }
181 Camera *Scene::get_camera(int idx) const
182 {
183 return idx >= 0 && idx < (int)cameras.size() ? cameras[idx] : 0;
184 }
186 Camera *Scene::get_camera(const char *name) const
187 {
188 for(size_t i=0; i<cameras.size(); i++) {
189 if(cameras[i]->name == std::string(name)) {
190 return cameras[i];
191 }
192 }
193 return 0;
194 }
196 int Scene::get_camera_count() const
197 {
198 return (int)cameras.size();
199 }
202 void Scene::add_node(Node *node)
203 {
204 nodes.push_back(node);
205 }
207 Node *Scene::get_node(int idx) const
208 {
209 return idx >= 0 && idx < (int)nodes.size() ? nodes[idx] : 0;
210 }
212 Node *Scene::get_node(const char *name) const
213 {
214 for(size_t i=0; i<nodes.size(); i++) {
215 if(strcmp(nodes[i]->get_name(), name) == 0) {
216 return nodes[i];
217 }
218 }
219 return 0;
220 }
222 int Scene::get_node_count() const
223 {
224 return (int)nodes.size();
225 }
227 const AABox &Scene::get_bounds() const
228 {
229 if(!bbox_valid) {
230 bbox = AABox();
232 for(size_t i=0; i<nodes.size(); i++) {
233 if(nodes[i]->get_parent()) {
234 continue;
235 }
237 bbox = aabox_union(bbox, nodes[i]->get_bounds());
238 }
239 bbox_valid = true;
240 }
242 return bbox;
243 }
245 // Scene::load is defined in goat3d_read.cc
246 // Scene::loadxml is defined in goat3d_readxml.cc
247 // Scene::save is defined in goat3d_write.cc
248 // Scene::savexml is defined in goat3d_writexml.cc
251 void g3dimpl::io_fprintf(goat3d_io *io, const char *fmt, ...)
252 {
253 va_list ap;
255 va_start(ap, fmt);
256 io_vfprintf(io, fmt, ap);
257 va_end(ap);
258 }
261 void g3dimpl::io_vfprintf(goat3d_io *io, const char *fmt, va_list ap)
262 {
263 char smallbuf[256];
264 char *buf = smallbuf;
265 int sz = sizeof smallbuf;
267 int retsz = vsnprintf(buf, sz - 1, fmt, ap);
269 if(retsz >= sz) {
270 /* C99 mandates that snprintf with a short count should return the
271 * number of characters that *would* be printed.
272 */
273 buf = new char[retsz + 1];
275 vsnprintf(buf, retsz, fmt, ap);
277 } else if(retsz <= 0) {
278 /* SUSv2 and microsoft specify that snprintf with a short count
279 * returns an arbitrary value <= 0. So let's try allocating
280 * bigger and bigger arrays until we find the correct size.
281 */
282 sz = sizeof smallbuf;
283 do {
284 sz *= 2;
285 if(buf != smallbuf) {
286 delete [] buf;
287 }
288 buf = new char[sz + 1];
290 retsz = vsnprintf(buf, sz, fmt, ap);
291 } while(retsz <= 0);
292 }
294 io->write(buf, retsz, io->cls);
296 if(buf != smallbuf) {
297 delete [] buf;
298 }
300 }