goat3d

annotate src/scene.cc @ 103:45a9d493e98c

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