goat3d
changeset 1:e46529a5d057
some progress
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 17 Aug 2013 23:51:24 +0300 |
parents | 2918358f5e6d |
children | f358b482d286 |
files | Makefile src/chunk.h src/goat3d_impl.h src/material.h src/mesh.cc src/mesh.h src/opengl.cc src/opengl.h src/vmath.h src/xform_node.cc src/xform_node.h |
diffstat | 11 files changed, 1887 insertions(+), 33 deletions(-) [+] |
line diff
1.1 --- a/Makefile Sat Aug 17 16:10:26 2013 +0300 1.2 +++ b/Makefile Sat Aug 17 23:51:24 2013 +0300 1.3 @@ -27,6 +27,7 @@ 1.4 endif 1.5 1.6 CXXFLAGS = -pedantic -Wall $(dbg) $(opt) $(pic) 1.7 +LDFLAGS = -lvmath -lanim 1.8 1.9 .PHONY: all 1.10 all: $(lib_so) $(lib_a)
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/chunk.h Sat Aug 17 23:51:24 2013 +0300 2.3 @@ -0,0 +1,64 @@ 2.4 +#ifndef CHUNK_H_ 2.5 +#define CHUNK_H_ 2.6 + 2.7 +enum { 2.8 + CNK_INVALID, // this shouldn't appear in files 2.9 + CNK_SCENE, // the root chunk 2.10 + 2.11 + // general purpose chunks 2.12 + CNK_INT, 2.13 + CNK_UINT, 2.14 + CNK_FLOAT, 2.15 + CNK_VEC3, 2.16 + CNK_VEC4, 2.17 + CNK_STRING, 2.18 + 2.19 + // --- first level chunks --- 2.20 + // children of CNK_SCENE 2.21 + CNK_ENV, // environmental parameters 2.22 + CNK_MTL_LIST, // material library 2.23 + CNK_MESH_LIST, // all the meshes hang under this chunk 2.24 + CNK_LIGHT_LIST, // likewise for lights 2.25 + CNK_CAMERA_LIST, // likewise for cameras 2.26 + CNK_NODE_LIST, // likewise for nodes 2.27 + CNK_ANIM_LIST, // all animations 2.28 + 2.29 + // --- second level chunks --- 2.30 + // children of CNK_ENV 2.31 + CNK_ENV_AMBIENT, // ambient color, contains a single CNK_VEC3 2.32 + CNK_ENV_FOG, 2.33 + 2.34 + // children of CNK_*_LIST 2.35 + CNK_MTL, 2.36 + CNK_MESH, 2.37 + CNK_LIGHT, 2.38 + CNK_CAMERA, 2.39 + CNK_NODE, 2.40 + 2.41 + // --- third level chunks --- 2.42 + // children of CNK_FOG 2.43 + CNK_FOG_COLOR, // fog color, contains a single CNK_VEC3 2.44 + CNK_FOG_EXP, // fog exponent, contains a single CNK_REAL 2.45 + 2.46 + // children of CNK_MTL 2.47 + CNK_MTL_ATTR, // material attribute, has a CNK_STRING for its name, 2.48 + // a CNK_MTL_ATTR_VAL, and optionally a CNK_MTL_ATTR_MAP 2.49 + // children of CNK_MTL_ATTR 2.50 + CNK_MTL_ATTR_VAL, // can have a single CNK_FLOAT, CNK_VEC3, or CNK_VEC4 2.51 + CNK_MTL_ATTR_MAP, // has a single CNK_STRING 2.52 + 2.53 + // children of CNK_MESH 2.54 + // TODO... 2.55 +}; 2.56 + 2.57 +struct ChunkHeader { 2.58 + uint32_t id; 2.59 + uint32_t size; 2.60 +}; 2.61 + 2.62 +struct Chunk { 2.63 + ChunkHeader hdr; 2.64 + char data[1]; 2.65 +}; 2.66 + 2.67 +#endif // CHUNK_H_
3.1 --- a/src/goat3d_impl.h Sat Aug 17 16:10:26 2013 +0300 3.2 +++ b/src/goat3d_impl.h Sat Aug 17 23:51:24 2013 +0300 3.3 @@ -2,8 +2,8 @@ 3.4 #define GOAT3D_IMPL_H_ 3.5 3.6 #include <string> 3.7 +#include <vmath/vmath.h> 3.8 #include "goat3d.h" 3.9 -#include "vmath.h" 3.10 #include "mesh.h" 3.11 #include "light.h" 3.12 #include "camera.h"
4.1 --- a/src/material.h Sat Aug 17 16:10:26 2013 +0300 4.2 +++ b/src/material.h Sat Aug 17 23:51:24 2013 +0300 4.3 @@ -1,8 +1,44 @@ 4.4 #ifndef MATERIAL_H_ 4.5 #define MATERIAL_H_ 4.6 4.7 +#include <string> 4.8 +#include <map> 4.9 +#include <vmath/vmath.h> 4.10 + 4.11 +struct MaterialAttrib { 4.12 + Vector4 value; 4.13 + std::string map; 4.14 +}; 4.15 + 4.16 +#define MAT_ATTR_DIFFUSE "diffuse" 4.17 +#define MAT_ATTR_SPECULAR "specular" 4.18 +#define MAT_ATTR_SHININESS "shininess" 4.19 +#define MAT_ATTR_NORMAL "normal" 4.20 +#define MAT_ATTR_BUMP "bump" 4.21 +#define MAT_ATTR_REFLECTION "reflection" 4.22 +#define MAT_ATTR_TRANSMISSION "transmission" 4.23 +#define MAT_ATTR_IOR "ior" 4.24 + 4.25 class Material { 4.26 - // TODO 4.27 +private: 4.28 + static MaterialAttrib def_attr; 4.29 + 4.30 + std::map<std::string, MaterialAttrib> attrib; 4.31 + 4.32 +public: 4.33 + MaterialAttrib &operator [](const std::string &name) 4.34 + { 4.35 + return attrib[name]; 4.36 + } 4.37 + 4.38 + const MaterialAttrib &operator [](const std::string &name) const 4.39 + { 4.40 + std::map<std::string, MaterialAttrib>::const_iterator it; 4.41 + if((it = attrib.find(name)) != attrib.end()) { 4.42 + return it->second; 4.43 + } 4.44 + return def_attr; 4.45 + } 4.46 }; 4.47 4.48 #endif // MATERIAL_H_
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/mesh.cc Sat Aug 17 23:51:24 2013 +0300 5.3 @@ -0,0 +1,973 @@ 5.4 +#include <stdio.h> 5.5 +#include <stdlib.h> 5.6 +#include <float.h> 5.7 +#include <assert.h> 5.8 +#include "opengl.h" 5.9 +#include "mesh.h" 5.10 +#include "xform_node.h" 5.11 +//#include "logger.h" 5.12 + 5.13 +int Mesh::global_sdr_loc[NUM_MESH_ATTR] = { 0, 1, 2, 3, 4, 5 }; 5.14 +unsigned int Mesh::intersect_mode = ISECT_DEFAULT; 5.15 +float Mesh::vertex_sel_dist = 0.01; 5.16 +float Mesh::vis_vecsize = 1.0; 5.17 + 5.18 +Mesh::Mesh() 5.19 +{ 5.20 + clear(); 5.21 + 5.22 + glGenBuffers(NUM_MESH_ATTR + 1, buffer_objects); 5.23 + 5.24 + for(int i=0; i<NUM_MESH_ATTR; i++) { 5.25 + vattr[i].vbo = buffer_objects[i]; 5.26 + } 5.27 + ibo = buffer_objects[NUM_MESH_ATTR]; 5.28 + wire_ibo = 0; 5.29 +} 5.30 + 5.31 +Mesh::~Mesh() 5.32 +{ 5.33 + glDeleteBuffers(NUM_MESH_ATTR + 1, buffer_objects); 5.34 + 5.35 + if(wire_ibo) { 5.36 + glDeleteBuffers(1, &wire_ibo); 5.37 + } 5.38 +} 5.39 + 5.40 +void Mesh::set_name(const char *name) 5.41 +{ 5.42 + this->name = name; 5.43 +} 5.44 + 5.45 +const char *Mesh::get_name() const 5.46 +{ 5.47 + return name.c_str(); 5.48 +} 5.49 + 5.50 +bool Mesh::has_attrib(int attr) const 5.51 +{ 5.52 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 5.53 + return false; 5.54 + } 5.55 + 5.56 + // if neither of these is valid, then nobody has set this attribute 5.57 + return vattr[attr].vbo_valid || vattr[attr].data_valid; 5.58 +} 5.59 + 5.60 +void Mesh::clear() 5.61 +{ 5.62 + bones.clear(); 5.63 + 5.64 + for(int i=0; i<NUM_MESH_ATTR; i++) { 5.65 + vattr[i].nelem = 0; 5.66 + vattr[i].vbo_valid = false; 5.67 + vattr[i].data_valid = false; 5.68 + //vattr[i].sdr_loc = -1; 5.69 + vattr[i].data.clear(); 5.70 + } 5.71 + ibo_valid = false; 5.72 + idata.clear(); 5.73 + 5.74 + wire_ibo_valid = false; 5.75 + 5.76 + nverts = nfaces = 0; 5.77 + 5.78 + /*bsph_valid = false; 5.79 + aabb_valid = false;*/ 5.80 +} 5.81 + 5.82 +float *Mesh::set_attrib_data(int attrib, int nelem, unsigned int num, const float *data) 5.83 +{ 5.84 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 5.85 + fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib); 5.86 + return 0; 5.87 + } 5.88 + 5.89 + if(nverts && num != nverts) { 5.90 + fprintf(stderr, "%s: attribute count missmatch (%d instead of %d)\n", __FUNCTION__, num, nverts); 5.91 + return 0; 5.92 + } 5.93 + nverts = num; 5.94 + 5.95 + vattr[attrib].data.clear(); 5.96 + vattr[attrib].nelem = nelem; 5.97 + vattr[attrib].data.resize(num * nelem); 5.98 + 5.99 + if(data) { 5.100 + memcpy(&vattr[attrib].data[0], data, num * nelem * sizeof *data); 5.101 + } 5.102 + 5.103 + vattr[attrib].data_valid = true; 5.104 + vattr[attrib].vbo_valid = false; 5.105 + return &vattr[attrib].data[0]; 5.106 +} 5.107 + 5.108 +float *Mesh::get_attrib_data(int attrib) 5.109 +{ 5.110 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 5.111 + fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib); 5.112 + return 0; 5.113 + } 5.114 + 5.115 + vattr[attrib].vbo_valid = false; 5.116 + return (float*)((const Mesh*)this)->get_attrib_data(attrib); 5.117 +} 5.118 + 5.119 +const float *Mesh::get_attrib_data(int attrib) const 5.120 +{ 5.121 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 5.122 + fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib); 5.123 + return 0; 5.124 + } 5.125 + 5.126 + if(!vattr[attrib].data_valid) { 5.127 +#if GL_ES_VERSION_2_0 5.128 + fprintf(stderr, "%s: can't read back attrib data on CrippledGL ES\n", __FUNCTION__); 5.129 + return 0; 5.130 +#else 5.131 + if(!vattr[attrib].vbo_valid) { 5.132 + fprintf(stderr, "%s: unavailable attrib: %d\n", __FUNCTION__, attrib); 5.133 + return 0; 5.134 + } 5.135 + 5.136 + // local data copy is unavailable, grab the data from the vbo 5.137 + Mesh *m = (Mesh*)this; 5.138 + m->vattr[attrib].data.resize(nverts * vattr[attrib].nelem); 5.139 + 5.140 + glBindBuffer(GL_ARRAY_BUFFER, vattr[attrib].vbo); 5.141 + void *data = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); 5.142 + memcpy(&m->vattr[attrib].data[0], data, nverts * vattr[attrib].nelem * sizeof(float)); 5.143 + glUnmapBuffer(GL_ARRAY_BUFFER); 5.144 + 5.145 + vattr[attrib].data_valid = true; 5.146 +#endif 5.147 + } 5.148 + 5.149 + return &vattr[attrib].data[0]; 5.150 +} 5.151 + 5.152 +void Mesh::set_attrib(int attrib, int idx, const Vector4 &v) 5.153 +{ 5.154 + float *data = get_attrib_data(attrib); 5.155 + if(data) { 5.156 + data += idx * vattr[attrib].nelem; 5.157 + for(int i=0; i<vattr[attrib].nelem; i++) { 5.158 + data[i] = v[i]; 5.159 + } 5.160 + } 5.161 +} 5.162 + 5.163 +Vector4 Mesh::get_attrib(int attrib, int idx) const 5.164 +{ 5.165 + Vector4 v(0.0, 0.0, 0.0, 1.0); 5.166 + const float *data = get_attrib_data(attrib); 5.167 + if(data) { 5.168 + data += idx * vattr[attrib].nelem; 5.169 + for(int i=0; i<vattr[attrib].nelem; i++) { 5.170 + v[i] = data[i]; 5.171 + } 5.172 + } 5.173 + return v; 5.174 +} 5.175 + 5.176 +unsigned int *Mesh::set_index_data(int num, const unsigned int *indices) 5.177 +{ 5.178 + int nidx = nfaces * 3; 5.179 + if(nidx && num != nidx) { 5.180 + fprintf(stderr, "%s: index count missmatch (%d instead of %d)\n", __FUNCTION__, num, nidx); 5.181 + return 0; 5.182 + } 5.183 + nfaces = num / 3; 5.184 + 5.185 + idata.clear(); 5.186 + idata.resize(num); 5.187 + 5.188 + if(indices) { 5.189 + memcpy(&idata[0], indices, num * sizeof *indices); 5.190 + } 5.191 + 5.192 + idata_valid = true; 5.193 + ibo_valid = false; 5.194 + 5.195 + return &idata[0]; 5.196 +} 5.197 + 5.198 +unsigned int *Mesh::get_index_data() 5.199 +{ 5.200 + ibo_valid = false; 5.201 + return (unsigned int*)((const Mesh*)this)->get_index_data(); 5.202 +} 5.203 + 5.204 +const unsigned int *Mesh::get_index_data() const 5.205 +{ 5.206 + if(!idata_valid) { 5.207 +#if GL_ES_VERSION_2_0 5.208 + fprintf(stderr, "%s: can't read back index data in CrippledGL ES\n", __FUNCTION__); 5.209 + return 0; 5.210 +#else 5.211 + if(!ibo_valid) { 5.212 + fprintf(stderr, "%s: indices unavailable\n", __FUNCTION__); 5.213 + return 0; 5.214 + } 5.215 + 5.216 + // local data copy is unavailable, gram the data from the ibo 5.217 + Mesh *m = (Mesh*)this; 5.218 + int nidx = nfaces * 3; 5.219 + m->idata.resize(nidx); 5.220 + 5.221 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 5.222 + void *data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY); 5.223 + memcpy(&m->idata[0], data, nidx * sizeof(unsigned int)); 5.224 + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); 5.225 + 5.226 + idata_valid = true; 5.227 +#endif 5.228 + } 5.229 + 5.230 + return &idata[0]; 5.231 +} 5.232 + 5.233 +void Mesh::append(const Mesh &mesh) 5.234 +{ 5.235 + unsigned int idxoffs = nverts; 5.236 + 5.237 + nverts += mesh.nverts; 5.238 + nfaces += mesh.nfaces; 5.239 + 5.240 + for(int i=0; i<NUM_MESH_ATTR; i++) { 5.241 + if(has_attrib(i) && mesh.has_attrib(i)) { 5.242 + // force validating the data arrays 5.243 + get_attrib_data(i); 5.244 + mesh.get_attrib_data(i); 5.245 + 5.246 + // append the mesh data 5.247 + vattr[i].data.insert(vattr[i].data.end(), mesh.vattr[i].data.begin(), mesh.vattr[i].data.end()); 5.248 + } 5.249 + } 5.250 + 5.251 + if(ibo_valid || idata_valid) { 5.252 + // make index arrays valid 5.253 + get_index_data(); 5.254 + mesh.get_index_data(); 5.255 + 5.256 + size_t orig_sz = idata.size(); 5.257 + 5.258 + idata.insert(idata.end(), mesh.idata.begin(), mesh.idata.end()); 5.259 + 5.260 + // fixup all the new indices 5.261 + for(size_t i=orig_sz; i<idata.size(); i++) { 5.262 + idata[i] += idxoffs; 5.263 + } 5.264 + } 5.265 + 5.266 + // fuck everything 5.267 + wire_ibo_valid = false; 5.268 + /*aabb_valid = false; 5.269 + bsph_valid = false;*/ 5.270 +} 5.271 + 5.272 +// assemble a complete vertex by adding all the useful attributes 5.273 +void Mesh::vertex(float x, float y, float z) 5.274 +{ 5.275 + cur_val[MESH_ATTR_VERTEX] = Vector4(x, y, z, 1.0f); 5.276 + vattr[MESH_ATTR_VERTEX].data_valid = true; 5.277 + vattr[MESH_ATTR_VERTEX].nelem = 3; 5.278 + 5.279 + for(int i=0; i<NUM_MESH_ATTR; i++) { 5.280 + if(vattr[i].data_valid) { 5.281 + for(int j=0; j<vattr[MESH_ATTR_VERTEX].nelem; j++) { 5.282 + vattr[i].data.push_back(cur_val[i][j]); 5.283 + } 5.284 + } 5.285 + vattr[i].vbo_valid = false; 5.286 + } 5.287 + 5.288 + if(idata_valid) { 5.289 + idata.clear(); 5.290 + } 5.291 + ibo_valid = idata_valid = false; 5.292 +} 5.293 + 5.294 +void Mesh::normal(float nx, float ny, float nz) 5.295 +{ 5.296 + cur_val[MESH_ATTR_NORMAL] = Vector4(nx, ny, nz, 1.0f); 5.297 + vattr[MESH_ATTR_NORMAL].data_valid = true; 5.298 + vattr[MESH_ATTR_NORMAL].nelem = 3; 5.299 +} 5.300 + 5.301 +void Mesh::tangent(float tx, float ty, float tz) 5.302 +{ 5.303 + cur_val[MESH_ATTR_TANGENT] = Vector4(tx, ty, tz, 1.0f); 5.304 + vattr[MESH_ATTR_TANGENT].data_valid = true; 5.305 + vattr[MESH_ATTR_TANGENT].nelem = 3; 5.306 +} 5.307 + 5.308 +void Mesh::texcoord(float u, float v, float w) 5.309 +{ 5.310 + cur_val[MESH_ATTR_TEXCOORD] = Vector4(u, v, w, 1.0f); 5.311 + vattr[MESH_ATTR_TEXCOORD].data_valid = true; 5.312 + vattr[MESH_ATTR_TEXCOORD].nelem = 3; 5.313 +} 5.314 + 5.315 +void Mesh::boneweights(float w1, float w2, float w3, float w4) 5.316 +{ 5.317 + cur_val[MESH_ATTR_BONEWEIGHTS] = Vector4(w1, w2, w3, w4); 5.318 + vattr[MESH_ATTR_BONEWEIGHTS].data_valid = true; 5.319 + vattr[MESH_ATTR_BONEWEIGHTS].nelem = 4; 5.320 +} 5.321 + 5.322 +void Mesh::boneidx(int idx1, int idx2, int idx3, int idx4) 5.323 +{ 5.324 + cur_val[MESH_ATTR_BONEIDX] = Vector4(idx1, idx2, idx3, idx4); 5.325 + vattr[MESH_ATTR_BONEIDX].data_valid = true; 5.326 + vattr[MESH_ATTR_BONEIDX].nelem = 4; 5.327 +} 5.328 + 5.329 +/// static function 5.330 +void Mesh::set_attrib_location(int attr, int loc) 5.331 +{ 5.332 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 5.333 + return; 5.334 + } 5.335 + Mesh::global_sdr_loc[attr] = loc; 5.336 +} 5.337 + 5.338 +/// static function 5.339 +int Mesh::get_attrib_location(int attr) 5.340 +{ 5.341 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 5.342 + return -1; 5.343 + } 5.344 + return Mesh::global_sdr_loc[attr]; 5.345 +} 5.346 + 5.347 +/// static function 5.348 +void Mesh::clear_attrib_locations() 5.349 +{ 5.350 + for(int i=0; i<NUM_MESH_ATTR; i++) { 5.351 + Mesh::global_sdr_loc[i] = -1; 5.352 + } 5.353 +} 5.354 + 5.355 +/// static function 5.356 +void Mesh::set_vis_vecsize(float sz) 5.357 +{ 5.358 + Mesh::vis_vecsize = sz; 5.359 +} 5.360 + 5.361 +float Mesh::get_vis_vecsize() 5.362 +{ 5.363 + return Mesh::vis_vecsize; 5.364 +} 5.365 + 5.366 +void Mesh::apply_xform(const Matrix4x4 &xform) 5.367 +{ 5.368 + Matrix4x4 dir_xform = xform; 5.369 + dir_xform[0][3] = dir_xform[1][3] = dir_xform[2][3] = 0.0f; 5.370 + dir_xform[3][0] = dir_xform[3][1] = dir_xform[3][2] = 0.0f; 5.371 + dir_xform[3][3] = 1.0f; 5.372 + 5.373 + apply_xform(xform, dir_xform); 5.374 +} 5.375 + 5.376 +void Mesh::apply_xform(const Matrix4x4 &xform, const Matrix4x4 &dir_xform) 5.377 +{ 5.378 + for(unsigned int i=0; i<nverts; i++) { 5.379 + Vector4 v = get_attrib(MESH_ATTR_VERTEX, i); 5.380 + set_attrib(MESH_ATTR_VERTEX, i, v.transformed(xform)); 5.381 + 5.382 + if(has_attrib(MESH_ATTR_NORMAL)) { 5.383 + Vector3 n = get_attrib(MESH_ATTR_NORMAL, i); 5.384 + set_attrib(MESH_ATTR_NORMAL, i, n.transformed(dir_xform)); 5.385 + } 5.386 + if(has_attrib(MESH_ATTR_TANGENT)) { 5.387 + Vector3 t = get_attrib(MESH_ATTR_TANGENT, i); 5.388 + set_attrib(MESH_ATTR_TANGENT, i, t.transformed(dir_xform)); 5.389 + } 5.390 + } 5.391 +} 5.392 + 5.393 +int Mesh::add_bone(XFormNode *bone) 5.394 +{ 5.395 + int idx = bones.size(); 5.396 + bones.push_back(bone); 5.397 + return idx; 5.398 +} 5.399 + 5.400 +const XFormNode *Mesh::get_bone(int idx) const 5.401 +{ 5.402 + if(idx < 0 || idx >= (int)bones.size()) { 5.403 + return 0; 5.404 + } 5.405 + return bones[idx]; 5.406 +} 5.407 + 5.408 +int Mesh::get_bones_count() const 5.409 +{ 5.410 + return (int)bones.size(); 5.411 +} 5.412 + 5.413 +void Mesh::draw() const 5.414 +{ 5.415 + ((Mesh*)this)->update_buffers(); 5.416 + 5.417 + if(!vattr[MESH_ATTR_VERTEX].vbo_valid) { 5.418 + fprintf(stderr, "%s: invalid vertex buffer\n", __FUNCTION__); 5.419 + return; 5.420 + } 5.421 + if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) { 5.422 + fprintf(stderr, "%s: shader attribute location for vertices unset\n", __FUNCTION__); 5.423 + return; 5.424 + } 5.425 + 5.426 + for(int i=0; i<NUM_MESH_ATTR; i++) { 5.427 + int loc = global_sdr_loc[i]; 5.428 + if(loc >= 0 && vattr[i].vbo_valid) { 5.429 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 5.430 + glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0); 5.431 + glEnableVertexAttribArray(loc); 5.432 + } 5.433 + } 5.434 + glBindBuffer(GL_ARRAY_BUFFER, 0); 5.435 + 5.436 + if(ibo_valid) { 5.437 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 5.438 + glDrawElements(GL_TRIANGLES, nfaces * 3, GL_UNSIGNED_INT, 0); 5.439 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 5.440 + } else { 5.441 + glDrawArrays(GL_TRIANGLES, 0, nverts); 5.442 + } 5.443 + 5.444 + for(int i=0; i<NUM_MESH_ATTR; i++) { 5.445 + int loc = global_sdr_loc[i]; 5.446 + if(loc >= 0 && vattr[i].vbo_valid) { 5.447 + glDisableVertexAttribArray(loc); 5.448 + } 5.449 + } 5.450 +} 5.451 + 5.452 +void Mesh::draw_wire() const 5.453 +{ 5.454 + ((Mesh*)this)->update_wire_ibo(); 5.455 + 5.456 + if(!vattr[MESH_ATTR_VERTEX].vbo_valid || !wire_ibo_valid) { 5.457 + fprintf(stderr, "%s: invalid vertex buffer\n", __FUNCTION__); 5.458 + return; 5.459 + } 5.460 + if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) { 5.461 + fprintf(stderr, "%s: shader attribute location for vertices unset\n", __FUNCTION__); 5.462 + return; 5.463 + } 5.464 + 5.465 + for(int i=0; i<NUM_MESH_ATTR; i++) { 5.466 + int loc = global_sdr_loc[i]; 5.467 + if(loc >= 0 && vattr[i].vbo_valid) { 5.468 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 5.469 + glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0); 5.470 + glEnableVertexAttribArray(loc); 5.471 + } 5.472 + } 5.473 + glBindBuffer(GL_ARRAY_BUFFER, 0); 5.474 + 5.475 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wire_ibo); 5.476 + glDrawElements(GL_LINES, nfaces * 6, GL_UNSIGNED_INT, 0); 5.477 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 5.478 + 5.479 + for(int i=0; i<NUM_MESH_ATTR; i++) { 5.480 + int loc = global_sdr_loc[i]; 5.481 + if(loc >= 0 && vattr[i].vbo_valid) { 5.482 + glDisableVertexAttribArray(loc); 5.483 + } 5.484 + } 5.485 +} 5.486 + 5.487 +void Mesh::draw_vertices() const 5.488 +{ 5.489 + ((Mesh*)this)->update_buffers(); 5.490 + 5.491 + if(!vattr[MESH_ATTR_VERTEX].vbo_valid) { 5.492 + fprintf(stderr, "%s: invalid vertex buffer\n", __FUNCTION__); 5.493 + return; 5.494 + } 5.495 + if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) { 5.496 + fprintf(stderr, "%s: shader attribute location for vertices unset\n", __FUNCTION__); 5.497 + return; 5.498 + } 5.499 + 5.500 + for(int i=0; i<NUM_MESH_ATTR; i++) { 5.501 + int loc = global_sdr_loc[i]; 5.502 + if(loc >= 0 && vattr[i].vbo_valid) { 5.503 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 5.504 + glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0); 5.505 + glEnableVertexAttribArray(loc); 5.506 + } 5.507 + } 5.508 + glBindBuffer(GL_ARRAY_BUFFER, 0); 5.509 + 5.510 + glDrawArrays(GL_POINTS, 0, nverts); 5.511 + 5.512 + for(int i=0; i<NUM_MESH_ATTR; i++) { 5.513 + int loc = global_sdr_loc[i]; 5.514 + if(loc >= 0 && vattr[i].vbo_valid) { 5.515 + glDisableVertexAttribArray(loc); 5.516 + } 5.517 + } 5.518 +} 5.519 + 5.520 +void Mesh::draw_normals() const 5.521 +{ 5.522 +#ifdef USE_OLDGL 5.523 + int vert_loc = global_sdr_loc[MESH_ATTR_VERTEX]; 5.524 + Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 5.525 + Vector3 *norm = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL); 5.526 + 5.527 + if(!varr || !norm || vert_loc < 0) { 5.528 + return; 5.529 + } 5.530 + 5.531 + glBegin(GL_LINES); 5.532 + for(size_t i=0; i<nverts; i++) { 5.533 + glVertexAttrib3f(vert_loc, varr[i].x, varr[i].y, varr[i].z); 5.534 + Vector3 end = varr[i] + norm[i] * vis_vecsize; 5.535 + glVertexAttrib3f(vert_loc, end.x, end.y, end.z); 5.536 + } 5.537 + glEnd(); 5.538 + 5.539 +#endif // USE_OLDGL 5.540 +} 5.541 + 5.542 +void Mesh::draw_tangents() const 5.543 +{ 5.544 +#ifdef USE_OLDGL 5.545 + int vert_loc = global_sdr_loc[MESH_ATTR_VERTEX]; 5.546 + Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 5.547 + Vector3 *tang = (Vector3*)get_attrib_data(MESH_ATTR_TANGENT); 5.548 + 5.549 + if(!varr || !tang || vert_loc < 0) { 5.550 + return; 5.551 + } 5.552 + 5.553 + glBegin(GL_LINES); 5.554 + for(size_t i=0; i<nverts; i++) { 5.555 + glVertexAttrib3f(vert_loc, varr[i].x, varr[i].y, varr[i].z); 5.556 + Vector3 end = varr[i] + tang[i] * vis_vecsize; 5.557 + glVertexAttrib3f(vert_loc, end.x, end.y, end.z); 5.558 + } 5.559 + glEnd(); 5.560 + 5.561 +#endif // USE_OLDGL 5.562 +} 5.563 + 5.564 +#if 0 5.565 +void Mesh::get_aabbox(Vector3 *vmin, Vector3 *vmax) const 5.566 +{ 5.567 + if(!aabb_valid) { 5.568 + ((Mesh*)this)->calc_aabb(); 5.569 + } 5.570 + *vmin = aabb.min; 5.571 + *vmax = aabb.max; 5.572 +} 5.573 + 5.574 +const AABox &Mesh::get_aabbox() const 5.575 +{ 5.576 + if(!aabb_valid) { 5.577 + ((Mesh*)this)->calc_aabb(); 5.578 + } 5.579 + return aabb; 5.580 +} 5.581 + 5.582 +float Mesh::get_bsphere(Vector3 *center, float *rad) const 5.583 +{ 5.584 + if(!bsph_valid) { 5.585 + ((Mesh*)this)->calc_bsph(); 5.586 + } 5.587 + *center = bsph.center; 5.588 + *rad = bsph.radius; 5.589 + return bsph.radius; 5.590 +} 5.591 + 5.592 +const Sphere &Mesh::get_bsphere() const 5.593 +{ 5.594 + if(!bsph_valid) { 5.595 + ((Mesh*)this)->calc_bsph(); 5.596 + } 5.597 + return bsph; 5.598 +} 5.599 + 5.600 +/// static function 5.601 +void Mesh::set_intersect_mode(unsigned int mode) 5.602 +{ 5.603 + Mesh::intersect_mode = mode; 5.604 +} 5.605 + 5.606 +/// static function 5.607 +unsigned int Mesh::get_intersect_mode() 5.608 +{ 5.609 + return Mesh::intersect_mode; 5.610 +} 5.611 + 5.612 +/// static function 5.613 +void Mesh::set_vertex_select_distance(float dist) 5.614 +{ 5.615 + Mesh::vertex_sel_dist = dist; 5.616 +} 5.617 + 5.618 +/// static function 5.619 +float Mesh::get_vertex_select_distance() 5.620 +{ 5.621 + return Mesh::vertex_sel_dist; 5.622 +} 5.623 + 5.624 +/*bool Mesh::intersect(const Ray &ray, HitPoint *hit) const 5.625 +{ 5.626 + assert((Mesh::intersect_mode & (ISECT_VERTICES | ISECT_FACE)) != (ISECT_VERTICES | ISECT_FACE)); 5.627 + 5.628 + const Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 5.629 + const Vector3 *narr = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL); 5.630 + if(!varr) { 5.631 + return false; 5.632 + } 5.633 + const unsigned int *idxarr = get_index_data(); 5.634 + 5.635 + // first test with the bounding box 5.636 + AABox box; 5.637 + get_aabbox(&box.min, &box.max); 5.638 + if(!box.intersect(ray)) { 5.639 + return false; 5.640 + } 5.641 + 5.642 + HitPoint nearest_hit; 5.643 + nearest_hit.dist = FLT_MAX; 5.644 + nearest_hit.obj = 0; 5.645 + 5.646 + if(Mesh::intersect_mode & ISECT_VERTICES) { 5.647 + // we asked for "intersections" with the vertices of the mesh 5.648 + long nearest_vidx = -1; 5.649 + float thres_sq = Mesh::vertex_sel_dist * Mesh::vertex_sel_dist; 5.650 + 5.651 + for(unsigned int i=0; i<nverts; i++) { 5.652 + 5.653 + if((Mesh::intersect_mode & ISECT_FRONT) && dot_product(narr[i], ray.dir) > 0) { 5.654 + continue; 5.655 + } 5.656 + 5.657 + // project the vertex onto the ray line 5.658 + float t = dot_product(varr[i] - ray.origin, ray.dir); 5.659 + Vector3 vproj = ray.origin + ray.dir * t; 5.660 + 5.661 + float dist_sq = (vproj - varr[i]).length_sq(); 5.662 + if(dist_sq < thres_sq) { 5.663 + if(!hit) { 5.664 + return true; 5.665 + } 5.666 + if(t < nearest_hit.dist) { 5.667 + nearest_hit.dist = t; 5.668 + nearest_vidx = i; 5.669 + } 5.670 + } 5.671 + } 5.672 + 5.673 + if(nearest_vidx != -1) { 5.674 + hitvert = varr[nearest_vidx]; 5.675 + nearest_hit.obj = &hitvert; 5.676 + } 5.677 + 5.678 + } else { 5.679 + // regular intersection test with polygons 5.680 + 5.681 + for(unsigned int i=0; i<nfaces; i++) { 5.682 + Triangle face(i, varr, idxarr); 5.683 + 5.684 + // ignore back-facing polygons if the mode flags include ISECT_FRONT 5.685 + if((Mesh::intersect_mode & ISECT_FRONT) && dot_product(face.get_normal(), ray.dir) > 0) { 5.686 + continue; 5.687 + } 5.688 + 5.689 + HitPoint fhit; 5.690 + if(face.intersect(ray, hit ? &fhit : 0)) { 5.691 + if(!hit) { 5.692 + return true; 5.693 + } 5.694 + if(fhit.dist < nearest_hit.dist) { 5.695 + nearest_hit = fhit; 5.696 + hitface = face; 5.697 + } 5.698 + } 5.699 + } 5.700 + } 5.701 + 5.702 + if(nearest_hit.obj) { 5.703 + if(hit) { 5.704 + *hit = nearest_hit; 5.705 + 5.706 + // if we are interested in the mesh and not the faces set obj to this 5.707 + if(Mesh::intersect_mode & ISECT_FACE) { 5.708 + hit->obj = &hitface; 5.709 + } else if(Mesh::intersect_mode & ISECT_VERTICES) { 5.710 + hit->obj = &hitvert; 5.711 + } else { 5.712 + hit->obj = this; 5.713 + } 5.714 + } 5.715 + return true; 5.716 + } 5.717 + return false; 5.718 +}*/ 5.719 + 5.720 + 5.721 +// ------ private member functions ------ 5.722 + 5.723 +void Mesh::calc_aabb() 5.724 +{ 5.725 + // the cast is to force calling the const version which doesn't invalidate 5.726 + if(!((const Mesh*)this)->get_attrib_data(MESH_ATTR_VERTEX)) { 5.727 + return; 5.728 + } 5.729 + 5.730 + aabb.min = Vector3(FLT_MAX, FLT_MAX, FLT_MAX); 5.731 + aabb.max = -aabb.min; 5.732 + 5.733 + for(unsigned int i=0; i<nverts; i++) { 5.734 + Vector4 v = get_attrib(MESH_ATTR_VERTEX, i); 5.735 + for(int j=0; j<3; j++) { 5.736 + if(v[j] < aabb.min[j]) { 5.737 + aabb.min[j] = v[j]; 5.738 + } 5.739 + if(v[j] > aabb.max[j]) { 5.740 + aabb.max[j] = v[j]; 5.741 + } 5.742 + } 5.743 + } 5.744 + aabb_valid = true; 5.745 +} 5.746 + 5.747 +void Mesh::calc_bsph() 5.748 +{ 5.749 + // the cast is to force calling the const version which doesn't invalidate 5.750 + if(!((const Mesh*)this)->get_attrib_data(MESH_ATTR_VERTEX)) { 5.751 + return; 5.752 + } 5.753 + 5.754 + Vector3 v; 5.755 + bsph.center = Vector3(0, 0, 0); 5.756 + 5.757 + // first find the center 5.758 + for(unsigned int i=0; i<nverts; i++) { 5.759 + v = get_attrib(MESH_ATTR_VERTEX, i); 5.760 + bsph.center += v; 5.761 + } 5.762 + bsph.center /= (float)nverts; 5.763 + 5.764 + bsph.radius = 0.0f; 5.765 + for(unsigned int i=0; i<nverts; i++) { 5.766 + v = get_attrib(MESH_ATTR_VERTEX, i); 5.767 + float dist_sq = (v - bsph.center).length_sq(); 5.768 + if(dist_sq > bsph.radius) { 5.769 + bsph.radius = dist_sq; 5.770 + } 5.771 + } 5.772 + bsph.radius = sqrt(bsph.radius); 5.773 + 5.774 + bsph_valid = true; 5.775 +} 5.776 +#endif 5.777 + 5.778 +void Mesh::update_buffers() 5.779 +{ 5.780 + for(int i=0; i<NUM_MESH_ATTR; i++) { 5.781 + if(has_attrib(i) && !vattr[i].vbo_valid) { 5.782 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 5.783 + glBufferData(GL_ARRAY_BUFFER, nverts * vattr[i].nelem * sizeof(float), &vattr[i].data[0], GL_STATIC_DRAW); 5.784 + vattr[i].vbo_valid = true; 5.785 + } 5.786 + } 5.787 + glBindBuffer(GL_ARRAY_BUFFER, 0); 5.788 + 5.789 + if(idata_valid && !ibo_valid) { 5.790 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 5.791 + glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 3 * sizeof(unsigned int), &idata[0], GL_STATIC_DRAW); 5.792 + ibo_valid = true; 5.793 + } 5.794 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 5.795 +} 5.796 + 5.797 +void Mesh::update_wire_ibo() 5.798 +{ 5.799 + update_buffers(); 5.800 + 5.801 + if(wire_ibo_valid) { 5.802 + return; 5.803 + } 5.804 + 5.805 + if(!wire_ibo) { 5.806 + glGenBuffers(1, &wire_ibo); 5.807 + } 5.808 + 5.809 + unsigned int *wire_idxarr = new unsigned int[nfaces * 6]; 5.810 + unsigned int *dest = wire_idxarr; 5.811 + 5.812 + if(ibo_valid) { 5.813 + // we're dealing with an indexed mesh 5.814 + const unsigned int *idxarr = ((const Mesh*)this)->get_index_data(); 5.815 + 5.816 + for(unsigned int i=0; i<nfaces; i++) { 5.817 + *dest++ = idxarr[0]; 5.818 + *dest++ = idxarr[1]; 5.819 + *dest++ = idxarr[1]; 5.820 + *dest++ = idxarr[2]; 5.821 + *dest++ = idxarr[2]; 5.822 + *dest++ = idxarr[0]; 5.823 + idxarr += 3; 5.824 + } 5.825 + } else { 5.826 + // not an indexed mesh ... 5.827 + for(unsigned int i=0; i<nfaces; i++) { 5.828 + int vidx = i * 3; 5.829 + *dest++ = vidx; 5.830 + *dest++ = vidx + 1; 5.831 + *dest++ = vidx + 1; 5.832 + *dest++ = vidx + 2; 5.833 + *dest++ = vidx + 2; 5.834 + *dest++ = vidx; 5.835 + } 5.836 + } 5.837 + 5.838 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wire_ibo); 5.839 + glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 6 * sizeof(unsigned int), wire_idxarr, GL_STATIC_DRAW); 5.840 + delete [] wire_idxarr; 5.841 + wire_ibo_valid = true; 5.842 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 5.843 +} 5.844 + 5.845 + 5.846 +// ------ class Triangle ------ 5.847 +Triangle::Triangle() 5.848 +{ 5.849 + normal_valid = false; 5.850 + id = -1; 5.851 +} 5.852 + 5.853 +Triangle::Triangle(const Vector3 &v0, const Vector3 &v1, const Vector3 &v2) 5.854 +{ 5.855 + v[0] = v0; 5.856 + v[1] = v1; 5.857 + v[2] = v2; 5.858 + normal_valid = false; 5.859 + id = -1; 5.860 +} 5.861 + 5.862 +Triangle::Triangle(int n, const Vector3 *varr, const unsigned int *idxarr) 5.863 +{ 5.864 + if(idxarr) { 5.865 + v[0] = varr[idxarr[n * 3]]; 5.866 + v[1] = varr[idxarr[n * 3 + 1]]; 5.867 + v[2] = varr[idxarr[n * 3 + 2]]; 5.868 + } else { 5.869 + v[0] = varr[n * 3]; 5.870 + v[1] = varr[n * 3 + 1]; 5.871 + v[2] = varr[n * 3 + 2]; 5.872 + } 5.873 + normal_valid = false; 5.874 + id = n; 5.875 +} 5.876 + 5.877 +void Triangle::calc_normal() 5.878 +{ 5.879 + normal = cross_product(v[1] - v[0], v[2] - v[0]).normalized(); 5.880 + normal_valid = true; 5.881 +} 5.882 + 5.883 +const Vector3 &Triangle::get_normal() const 5.884 +{ 5.885 + if(!normal_valid) { 5.886 + ((Triangle*)this)->calc_normal(); 5.887 + } 5.888 + return normal; 5.889 +} 5.890 + 5.891 +void Triangle::transform(const Matrix4x4 &xform) 5.892 +{ 5.893 + v[0].transform(xform); 5.894 + v[1].transform(xform); 5.895 + v[2].transform(xform); 5.896 + normal_valid = false; 5.897 +} 5.898 + 5.899 +void Triangle::draw() const 5.900 +{ 5.901 + Vector3 n[3]; 5.902 + n[0] = get_normal(); 5.903 + n[1] = get_normal(); 5.904 + n[2] = get_normal(); 5.905 + 5.906 + int vloc = Mesh::get_attrib_location(MESH_ATTR_VERTEX); 5.907 + int nloc = Mesh::get_attrib_location(MESH_ATTR_NORMAL); 5.908 + 5.909 + glEnableVertexAttribArray(vloc); 5.910 + glVertexAttribPointer(vloc, 3, GL_FLOAT, GL_FALSE, 0, &v[0].x); 5.911 + glVertexAttribPointer(nloc, 3, GL_FLOAT, GL_FALSE, 0, &n[0].x); 5.912 + 5.913 + glDrawArrays(GL_TRIANGLES, 0, 3); 5.914 + 5.915 + glDisableVertexAttribArray(vloc); 5.916 + glDisableVertexAttribArray(nloc); 5.917 + CHECKGLERR; 5.918 +} 5.919 + 5.920 +void Triangle::draw_wire() const 5.921 +{ 5.922 + static const int idxarr[] = {0, 1, 1, 2, 2, 0}; 5.923 + int vloc = Mesh::get_attrib_location(MESH_ATTR_VERTEX); 5.924 + 5.925 + glEnableVertexAttribArray(vloc); 5.926 + glVertexAttribPointer(vloc, 3, GL_FLOAT, GL_FALSE, 0, &v[0].x); 5.927 + 5.928 + glDrawElements(GL_LINES, 6, GL_UNSIGNED_INT, idxarr); 5.929 + 5.930 + glDisableVertexAttribArray(vloc); 5.931 + CHECKGLERR; 5.932 +} 5.933 + 5.934 +Vector3 Triangle::calc_barycentric(const Vector3 &pos) const 5.935 +{ 5.936 + Vector3 norm = get_normal(); 5.937 + 5.938 + float area_sq = fabs(dot_product(cross_product(v[1] - v[0], v[2] - v[0]), norm)); 5.939 + if(area_sq < 1e-5) { 5.940 + return Vector3(0, 0, 0); 5.941 + } 5.942 + 5.943 + float asq0 = fabs(dot_product(cross_product(v[1] - pos, v[2] - pos), norm)); 5.944 + float asq1 = fabs(dot_product(cross_product(v[2] - pos, v[0] - pos), norm)); 5.945 + float asq2 = fabs(dot_product(cross_product(v[0] - pos, v[1] - pos), norm)); 5.946 + 5.947 + return Vector3(asq0 / area_sq, asq1 / area_sq, asq2 / area_sq); 5.948 +} 5.949 + 5.950 +/*bool Triangle::intersect(const Ray &ray, HitPoint *hit) const 5.951 +{ 5.952 + Vector3 normal = get_normal(); 5.953 + 5.954 + float ndotdir = dot_product(ray.dir, normal); 5.955 + if(fabs(ndotdir) < 1e-4) { 5.956 + return false; 5.957 + } 5.958 + 5.959 + Vector3 vertdir = v[0] - ray.origin; 5.960 + float t = dot_product(normal, vertdir) / ndotdir; 5.961 + 5.962 + Vector3 pos = ray.origin + ray.dir * t; 5.963 + Vector3 bary = calc_barycentric(pos); 5.964 + 5.965 + if(bary.x + bary.y + bary.z > 1.00001) { 5.966 + return false; 5.967 + } 5.968 + 5.969 + if(hit) { 5.970 + hit->dist = t; 5.971 + hit->pos = ray.origin + ray.dir * t; 5.972 + hit->normal = normal; 5.973 + hit->obj = this; 5.974 + } 5.975 + return true; 5.976 +}*/
6.1 --- a/src/mesh.h Sat Aug 17 16:10:26 2013 +0300 6.2 +++ b/src/mesh.h Sat Aug 17 23:51:24 2013 +0300 6.3 @@ -1,8 +1,213 @@ 6.4 #ifndef MESH_H_ 6.5 #define MESH_H_ 6.6 6.7 -class Mesh { 6.8 - // TODO 6.9 +#include <string> 6.10 +#include <vector> 6.11 +#include <vmath/vmath.h> 6.12 +//#include "geom.h" 6.13 + 6.14 +enum { 6.15 + MESH_ATTR_VERTEX, 6.16 + MESH_ATTR_NORMAL, 6.17 + MESH_ATTR_TANGENT, 6.18 + MESH_ATTR_TEXCOORD, 6.19 + MESH_ATTR_COLOR, 6.20 + MESH_ATTR_BONEWEIGHTS, 6.21 + MESH_ATTR_BONEIDX, 6.22 + 6.23 + NUM_MESH_ATTR 6.24 }; 6.25 6.26 +// intersection mode flags 6.27 +enum { 6.28 + ISECT_DEFAULT = 0, // default (whole mesh, all intersections) 6.29 + ISECT_FRONT = 1, // front-faces only 6.30 + ISECT_FACE = 2, // return intersected face pointer instead of mesh 6.31 + ISECT_VERTICES = 4 // return (?) TODO 6.32 +}; 6.33 + 6.34 +class XFormNode; 6.35 + 6.36 + 6.37 +class Triangle { 6.38 +public: 6.39 + Vector3 v[3]; 6.40 + Vector3 normal; 6.41 + bool normal_valid; 6.42 + int id; 6.43 + 6.44 + Triangle(); 6.45 + Triangle(const Vector3 &v0, const Vector3 &v1, const Vector3 &v2); 6.46 + Triangle(int n, const Vector3 *varr, const unsigned int *idxarr = 0); 6.47 + 6.48 + /// calculate normal (quite expensive) 6.49 + void calc_normal(); 6.50 + const Vector3 &get_normal() const; 6.51 + 6.52 + void transform(const Matrix4x4 &xform); 6.53 + 6.54 + void draw() const; 6.55 + void draw_wire() const; 6.56 + 6.57 + /// calculate barycentric coordinates of a point 6.58 + Vector3 calc_barycentric(const Vector3 &pos) const; 6.59 + 6.60 + //bool intersect(const Ray &ray, HitPoint *hit = 0) const; 6.61 +}; 6.62 + 6.63 + 6.64 +class Mesh { 6.65 +private: 6.66 + std::string name; 6.67 + unsigned int nverts, nfaces; 6.68 + 6.69 + // current value for each attribute for the immedate mode 6.70 + // interface. 6.71 + Vector4 cur_val[NUM_MESH_ATTR]; 6.72 + 6.73 + unsigned int buffer_objects[NUM_MESH_ATTR + 1]; 6.74 + 6.75 + // vertex attribute data and buffer objects 6.76 + struct { 6.77 + int nelem; // number of elements per attribute range: [1, 4] 6.78 + std::vector<float> data; 6.79 + unsigned int vbo; 6.80 + mutable bool vbo_valid; // if this is false, the vbo needs updating from the data 6.81 + mutable bool data_valid; // if this is false, the data needs to be pulled from the vbo 6.82 + //int sdr_loc; 6.83 + } vattr[NUM_MESH_ATTR]; 6.84 + 6.85 + static int global_sdr_loc[NUM_MESH_ATTR]; 6.86 + 6.87 + std::vector<XFormNode*> bones; // bones affecting this mesh 6.88 + 6.89 + // index data and buffer object 6.90 + std::vector<unsigned int> idata; 6.91 + unsigned int ibo; 6.92 + mutable bool ibo_valid; 6.93 + mutable bool idata_valid; 6.94 + 6.95 + // index buffer object for wireframe rendering (constructed on demand) 6.96 + unsigned int wire_ibo; 6.97 + mutable bool wire_ibo_valid; 6.98 + 6.99 + // axis-aligned bounding box 6.100 + /*mutable AABox aabb; 6.101 + mutable bool aabb_valid; 6.102 + 6.103 + // bounding sphere 6.104 + mutable Sphere bsph; 6.105 + mutable bool bsph_valid;*/ 6.106 + 6.107 + // keeps the last intersected face 6.108 + mutable Triangle hitface; 6.109 + // keeps the last intersected vertex position 6.110 + mutable Vector3 hitvert; 6.111 + 6.112 + void calc_aabb(); 6.113 + void calc_bsph(); 6.114 + 6.115 + static unsigned int intersect_mode; 6.116 + static float vertex_sel_dist; 6.117 + 6.118 + static float vis_vecsize; 6.119 + 6.120 + /// update the VBOs after data has changed (invalid vbo/ibo) 6.121 + void update_buffers(); 6.122 + /// construct/update the wireframe index buffer (called from draw_wire). 6.123 + void update_wire_ibo(); 6.124 + 6.125 + 6.126 +public: 6.127 + Mesh(); 6.128 + ~Mesh(); 6.129 + 6.130 + void set_name(const char *name); 6.131 + const char *get_name() const; 6.132 + 6.133 + bool has_attrib(int attr) const; 6.134 + 6.135 + // clears everything about this mesh, and returns to the newly constructed state 6.136 + void clear(); 6.137 + 6.138 + // access the vertex attribute data 6.139 + // if vdata == 0, space is just allocated 6.140 + float *set_attrib_data(int attrib, int nelem, unsigned int num, const float *vdata = 0); // invalidates vbo 6.141 + float *get_attrib_data(int attrib); // invalidates vbo 6.142 + const float *get_attrib_data(int attrib) const; 6.143 + 6.144 + // simple access to any particular attribute 6.145 + void set_attrib(int attrib, int idx, const Vector4 &v); // invalidates vbo 6.146 + Vector4 get_attrib(int attrib, int idx) const; 6.147 + 6.148 + // ... same for index data 6.149 + unsigned int *set_index_data(int num, const unsigned int *indices = 0); // invalidates ibo 6.150 + unsigned int *get_index_data(); // invalidates ibo 6.151 + const unsigned int *get_index_data() const; 6.152 + 6.153 + void append(const Mesh &mesh); 6.154 + 6.155 + // immediate-mode style mesh construction interface 6.156 + void vertex(float x, float y, float z); 6.157 + void normal(float nx, float ny, float nz); 6.158 + void tangent(float tx, float ty, float tz); 6.159 + void texcoord(float u, float v, float w); 6.160 + void boneweights(float w1, float w2, float w3, float w4); 6.161 + void boneidx(int idx1, int idx2, int idx3, int idx4); 6.162 + 6.163 + /* apply a transformation to the vertices and its inverse-transpose 6.164 + * to the normals and tangents. 6.165 + */ 6.166 + void apply_xform(const Matrix4x4 &xform); 6.167 + void apply_xform(const Matrix4x4 &xform, const Matrix4x4 &dir_xform); 6.168 + 6.169 + // adds a bone and returns its index 6.170 + int add_bone(XFormNode *bone); 6.171 + const XFormNode *get_bone(int idx) const; 6.172 + int get_bones_count() const; 6.173 + 6.174 + // access the shader attribute locations 6.175 + static void set_attrib_location(int attr, int loc); 6.176 + static int get_attrib_location(int attr); 6.177 + static void clear_attrib_locations(); 6.178 + 6.179 + static void set_vis_vecsize(float sz); 6.180 + static float get_vis_vecsize(); 6.181 + 6.182 + void draw() const; 6.183 + void draw_wire() const; 6.184 + void draw_vertices() const; 6.185 + void draw_normals() const; 6.186 + void draw_tangents() const; 6.187 + 6.188 +#if 0 6.189 + /** get the bounding box in local space. The result will be cached, and subsequent 6.190 + * calls will return the same box. The cache gets invalidated by any functions that can affect 6.191 + * the vertex data (non-const variant of get_attrib_data(MESH_ATTR_VERTEX, ...) included). 6.192 + * @{ */ 6.193 + void get_aabbox(Vector3 *vmin, Vector3 *vmax) const; 6.194 + const AABox &get_aabbox() const; 6.195 + /// @} 6.196 + 6.197 + /** get the bounding sphere in local space. The result will be cached, and subsequent 6.198 + * calls will return the same box. The cache gets invalidated by any functions that can affect 6.199 + * the vertex data (non-const variant of get_attrib_data(MESH_ATTR_VERTEX, ...) included). 6.200 + * @{ */ 6.201 + float get_bsphere(Vector3 *center, float *rad) const; 6.202 + const Sphere &get_bsphere() const; 6.203 + 6.204 + static void set_intersect_mode(unsigned int mode); 6.205 + static unsigned int get_intersect_mode(); 6.206 + static void set_vertex_select_distance(float dist); 6.207 + static float get_vertex_select_distance(); 6.208 + 6.209 + /** Find the intersection between the mesh and a ray. 6.210 + * XXX Brute force at the moment, not intended to be used for anything other than picking in tools. 6.211 + * If you intend to use it in a speed-critical part of the code, you'll *have* to optimize it! 6.212 + */ 6.213 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 6.214 +#endif 6.215 +}; 6.216 + 6.217 + 6.218 #endif // MESH_H_
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/opengl.cc Sat Aug 17 23:51:24 2013 +0300 7.3 @@ -0,0 +1,29 @@ 7.4 +#include "opengl.h" 7.5 + 7.6 +void init_opengl() 7.7 +{ 7.8 +#ifdef __GLEW_H__ 7.9 + glewInit(); 7.10 +#endif 7.11 +} 7.12 + 7.13 +const char *strglerr(int err) 7.14 +{ 7.15 + static const char *errnames[] = { 7.16 + "GL_INVALID_ENUM", 7.17 + "GL_INVALID_VALUE", 7.18 + "GL_INVALID_OPERATION", 7.19 + "GL_STACK_OVERFLOW", 7.20 + "GL_STACK_UNDERFLOW", 7.21 + "GL_OUT_OF_MEMORY", 7.22 + "GL_INVALID_FRAMEBUFFER_OPERATION" 7.23 + }; 7.24 + 7.25 + if(!err) { 7.26 + return "GL_NO_ERROR"; 7.27 + } 7.28 + if(err < GL_INVALID_ENUM || err > GL_OUT_OF_MEMORY) { 7.29 + return "<invalid gl error>"; 7.30 + } 7.31 + return errnames[err - GL_INVALID_ENUM]; 7.32 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/opengl.h Sat Aug 17 23:51:24 2013 +0300 8.3 @@ -0,0 +1,71 @@ 8.4 +#ifndef OPENGL_H_ 8.5 +#define OPENGL_H_ 8.6 + 8.7 +#include <stdlib.h> 8.8 + 8.9 +#ifdef __APPLE__ 8.10 +#include "TargetConditionals.h" 8.11 + 8.12 +#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR 8.13 +/* iOS */ 8.14 +#include <OpenGLES/ES2/gl.h> 8.15 +#include <OpenGLES/ES2/glext.h> 8.16 + 8.17 +#define GL_CLAMP GL_CLAMP_TO_EDGE 8.18 +#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES 8.19 + 8.20 +#undef USE_OLDGL 8.21 + 8.22 +#define GL_WRITE_ONLY GL_WRITE_ONLY_OES 8.23 +#define glMapBuffer glMapBufferOES 8.24 +#define glUnmapBuffer glUnmapBufferOES 8.25 + 8.26 +#else 8.27 +/* MacOS X */ 8.28 +#include <GL/glew.h> 8.29 +#include <GLUT/glut.h> 8.30 + 8.31 +#define USE_OLDGL 8.32 +#endif 8.33 + 8.34 +#else 8.35 +/* UNIX or Windows */ 8.36 +#include <GL/glew.h> 8.37 +#include <GL/glut.h> 8.38 + 8.39 +#define USE_OLDGL 8.40 +#endif 8.41 + 8.42 +#ifndef GL_RGB16F 8.43 +#define GL_RGB16F 0x881b 8.44 +#endif 8.45 +#ifndef GL_RGBA16F 8.46 +#define GL_RGBA16F 0x881a 8.47 +#endif 8.48 +#ifndef GL_RGB32F 8.49 +#define GL_RGB32F 0x8815 8.50 +#endif 8.51 +#ifndef GL_RGBA32F 8.52 +#define GL_RGBA32F 0x8814 8.53 +#endif 8.54 +#ifndef GL_LUMINANCE16F 8.55 +#define GL_LUMINANCE16F 0x881e 8.56 +#endif 8.57 +#ifndef GL_LUMINANCE32F 8.58 +#define GL_LUMINANCE32F 0x8818 8.59 +#endif 8.60 + 8.61 +#define CHECKGLERR \ 8.62 + do { \ 8.63 + int err = glGetError(); \ 8.64 + if(err) { \ 8.65 + fprintf(stderr, "%s:%d: OpenGL error 0x%x: %s\n", __FILE__, __LINE__, err, strglerr(err)); \ 8.66 + abort(); \ 8.67 + } \ 8.68 + } while(0) 8.69 + 8.70 +void init_opengl(); 8.71 + 8.72 +const char *strglerr(int err); 8.73 + 8.74 +#endif // OPENGL_H_
9.1 --- a/src/vmath.h Sat Aug 17 16:10:26 2013 +0300 9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 9.3 @@ -1,29 +0,0 @@ 9.4 -#ifndef VMATH_H_ 9.5 -#define VMATH_H_ 9.6 - 9.7 -class Vector3 { 9.8 -public: 9.9 - float x, y, z; 9.10 - 9.11 - Vector3() : x(0), y(0), z(0) {} 9.12 - Vector3(float x, float y, float z) { 9.13 - this->x = x; 9.14 - this->y = y; 9.15 - this->z = z; 9.16 - } 9.17 -}; 9.18 - 9.19 -class Vector4 { 9.20 -public: 9.21 - float x, y, z, w; 9.22 - 9.23 - Vector4() : x(0), y(0), z(0), w(1) {} 9.24 - Vector4(float x, float y, float z, float w) { 9.25 - this->x = x; 9.26 - this->y = y; 9.27 - this->z = z; 9.28 - this->w = w; 9.29 - } 9.30 -}; 9.31 - 9.32 -#endif // VMATH_H_
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/src/xform_node.cc Sat Aug 17 23:51:24 2013 +0300 10.3 @@ -0,0 +1,370 @@ 10.4 +#include <assert.h> 10.5 +#include <algorithm> 10.6 +#include "xform_node.h" 10.7 +#include "anim/anim.h" 10.8 +#include "anim/track.h" 10.9 + 10.10 +static inline anm_interpolator track_interpolator(Interp in); 10.11 +static inline anm_extrapolator track_extrapolator(Extrap ex); 10.12 + 10.13 +XFormNode::XFormNode() 10.14 +{ 10.15 + anm = new anm_node; 10.16 + anm_init_node(anm); 10.17 +} 10.18 + 10.19 +XFormNode::~XFormNode() 10.20 +{ 10.21 + anm_destroy_node(anm); 10.22 + delete anm; 10.23 +} 10.24 + 10.25 +void XFormNode::set_name(const char *name) 10.26 +{ 10.27 + anm_set_node_name(anm, name); 10.28 +} 10.29 + 10.30 +const char *XFormNode::get_name() const 10.31 +{ 10.32 + return anm_get_node_name(anm); 10.33 +} 10.34 + 10.35 +void XFormNode::set_interpolator(Interp in) 10.36 +{ 10.37 + anm_set_interpolator(anm, track_interpolator(in)); 10.38 + interp = in; 10.39 +} 10.40 + 10.41 +Interp XFormNode::get_interpolator() const 10.42 +{ 10.43 + return interp; 10.44 +} 10.45 + 10.46 +void XFormNode::set_extrapolator(Extrap ex) 10.47 +{ 10.48 + anm_set_extrapolator(anm, track_extrapolator(ex)); 10.49 + extrap = ex; 10.50 +} 10.51 + 10.52 +Extrap XFormNode::get_extrapolator() const 10.53 +{ 10.54 + return extrap; 10.55 +} 10.56 + 10.57 +void XFormNode::add_child(XFormNode *child) 10.58 +{ 10.59 + children.push_back(child); 10.60 + anm_link_node(anm, child->anm); 10.61 +} 10.62 + 10.63 +void XFormNode::remove_child(XFormNode *child) 10.64 +{ 10.65 + std::vector<XFormNode*>::iterator it; 10.66 + it = std::find(children.begin(), children.end(), child); 10.67 + if(it != children.end()) { 10.68 + children.erase(it); 10.69 + anm_unlink_node(anm, child->anm); 10.70 + } 10.71 +} 10.72 + 10.73 +int XFormNode::get_children_count() const 10.74 +{ 10.75 + return (int)children.size(); 10.76 +} 10.77 + 10.78 +XFormNode *XFormNode::get_child(int idx) 10.79 +{ 10.80 + if(idx >= 0 && idx < get_children_count()) { 10.81 + return children[idx]; 10.82 + } 10.83 + return 0; 10.84 +} 10.85 + 10.86 +const XFormNode *XFormNode::get_child(int idx) const 10.87 +{ 10.88 + if(idx >= 0 && idx < get_children_count()) { 10.89 + return children[idx]; 10.90 + } 10.91 + return 0; 10.92 +} 10.93 + 10.94 +void XFormNode::set_position(const Vector3 &pos, long tmsec) 10.95 +{ 10.96 + anm_set_position(anm, v3_cons(pos.x, pos.y, pos.z), ANM_MSEC2TM(tmsec)); 10.97 +} 10.98 + 10.99 +Vector3 XFormNode::get_node_position(long tmsec) const 10.100 +{ 10.101 + vec3_t p = anm_get_node_position(anm, ANM_MSEC2TM(tmsec)); 10.102 + return Vector3(p.x, p.y, p.z); 10.103 +} 10.104 + 10.105 +void XFormNode::set_rotation(const Quaternion &quat, long tmsec) 10.106 +{ 10.107 + anm_set_rotation(anm, quat_cons(quat.s, quat.v.x, quat.v.y, quat.v.z), ANM_MSEC2TM(tmsec)); 10.108 +} 10.109 + 10.110 +Quaternion XFormNode::get_node_rotation(long tmsec) const 10.111 +{ 10.112 + quat_t q = anm_get_node_rotation(anm, ANM_MSEC2TM(tmsec)); 10.113 + return Quaternion(q.w, q.x, q.y, q.z); 10.114 +} 10.115 + 10.116 +void XFormNode::set_scaling(const Vector3 &pos, long tmsec) 10.117 +{ 10.118 + anm_set_scaling(anm, v3_cons(pos.x, pos.y, pos.z), ANM_MSEC2TM(tmsec)); 10.119 +} 10.120 + 10.121 +Vector3 XFormNode::get_node_scaling(long tmsec) const 10.122 +{ 10.123 + vec3_t s = anm_get_node_scaling(anm, ANM_MSEC2TM(tmsec)); 10.124 + return Vector3(s.x, s.y, s.z); 10.125 +} 10.126 + 10.127 +// these take hierarchy into account 10.128 +Vector3 XFormNode::get_position(long tmsec) const 10.129 +{ 10.130 + vec3_t v = anm_get_position(anm, ANM_MSEC2TM(tmsec)); 10.131 + return Vector3(v.x, v.y, v.z); 10.132 +} 10.133 + 10.134 +Quaternion XFormNode::get_rotation(long tmsec) const 10.135 +{ 10.136 + quat_t q = anm_get_rotation(anm, tmsec); 10.137 + return Quaternion(q.w, q.x, q.y, q.z); 10.138 +} 10.139 + 10.140 +Vector3 XFormNode::get_scaling(long tmsec) const 10.141 +{ 10.142 + vec3_t v = anm_get_scaling(anm, ANM_MSEC2TM(tmsec)); 10.143 + return Vector3(v.x, v.y, v.z); 10.144 +} 10.145 + 10.146 +void XFormNode::set_pivot(const Vector3 &pivot) 10.147 +{ 10.148 + anm_set_pivot(anm, v3_cons(pivot.x, pivot.y, pivot.z)); 10.149 +} 10.150 + 10.151 +Vector3 XFormNode::get_pivot() const 10.152 +{ 10.153 + vec3_t p = anm_get_pivot(anm); 10.154 + return Vector3(p.x, p.y, p.z); 10.155 +} 10.156 + 10.157 +void XFormNode::set_local_matrix(const Matrix4x4 &mat) 10.158 +{ 10.159 + local_matrix = mat; 10.160 +} 10.161 + 10.162 +const Matrix4x4 &XFormNode::get_local_matrix() const 10.163 +{ 10.164 + return local_matrix; 10.165 +} 10.166 + 10.167 +void XFormNode::set_bone_matrix(const Matrix4x4 &bmat) 10.168 +{ 10.169 + bone_matrix = bmat; 10.170 +} 10.171 + 10.172 +const Matrix4x4 &XFormNode::get_bone_matrix() const 10.173 +{ 10.174 + return bone_matrix; 10.175 +} 10.176 + 10.177 +#define FOO 10.178 + 10.179 +void XFormNode::get_node_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat) const 10.180 +{ 10.181 + anm_time_t tm = ANM_MSEC2TM(tmsec); 10.182 + 10.183 + if(mat) { 10.184 + anm_get_node_matrix(anm, (scalar_t(*)[4])mat, tm); 10.185 +#ifdef FOO 10.186 + *mat = local_matrix * *mat; 10.187 +#else 10.188 + *mat = *mat * local_matrix; 10.189 +#endif 10.190 + } 10.191 + if(inv_mat) { 10.192 + anm_get_inv_matrix(anm, (scalar_t(*)[4])inv_mat, tm); 10.193 + } 10.194 +} 10.195 + 10.196 +void XFormNode::get_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat) const 10.197 +{ 10.198 + anm_time_t tm = ANM_MSEC2TM(tmsec); 10.199 + 10.200 + if(mat) { 10.201 + anm_get_matrix(anm, (scalar_t(*)[4])mat, tm); 10.202 +#ifdef FOO 10.203 + *mat = local_matrix * *mat; 10.204 +#else 10.205 + *mat = *mat * local_matrix; 10.206 +#endif 10.207 + } 10.208 + if(inv_mat) { 10.209 + anm_get_inv_matrix(anm, (scalar_t(*)[4])inv_mat, tm); 10.210 + } 10.211 +} 10.212 + 10.213 + 10.214 +// ---- Track ---- 10.215 + 10.216 +Track::Track() 10.217 +{ 10.218 + trk = new anm_track; 10.219 + anm_init_track(trk); 10.220 +} 10.221 + 10.222 +Track::~Track() 10.223 +{ 10.224 + anm_destroy_track(trk); 10.225 + delete trk; 10.226 +} 10.227 + 10.228 +Track::Track(const Track &rhs) 10.229 +{ 10.230 + trk = new anm_track; 10.231 + anm_init_track(trk); 10.232 + anm_copy_track(trk, rhs.trk); 10.233 + interp = rhs.interp; 10.234 + extrap = rhs.extrap; 10.235 +} 10.236 + 10.237 +Track &Track::operator =(const Track &rhs) 10.238 +{ 10.239 + if(&rhs == this) { 10.240 + return *this; 10.241 + } 10.242 + 10.243 + anm_copy_track(trk, rhs.trk); 10.244 + interp = rhs.interp; 10.245 + extrap = rhs.extrap; 10.246 + return *this; 10.247 +} 10.248 + 10.249 + 10.250 +void Track::set_interpolator(Interp in) 10.251 +{ 10.252 + anm_set_track_interpolator(trk, track_interpolator(in)); 10.253 + interp = in; 10.254 +} 10.255 + 10.256 +Interp Track::get_interpolator() const 10.257 +{ 10.258 + return interp; 10.259 +} 10.260 + 10.261 +void Track::set_extrapolator(Extrap ex) 10.262 +{ 10.263 + anm_set_track_extrapolator(trk, track_extrapolator(ex)); 10.264 + extrap = ex; 10.265 +} 10.266 + 10.267 +Extrap Track::get_extrapolator() const 10.268 +{ 10.269 + return extrap; 10.270 +} 10.271 + 10.272 +void Track::set_default(double def) 10.273 +{ 10.274 + anm_set_track_default(trk, def); 10.275 +} 10.276 + 10.277 +void Track::set_value(float val, long tmsec) 10.278 +{ 10.279 + anm_set_value(trk, ANM_MSEC2TM(tmsec), val); 10.280 +} 10.281 + 10.282 +float Track::get_value(long tmsec) const 10.283 +{ 10.284 + return anm_get_value(trk, ANM_MSEC2TM(tmsec)); 10.285 +} 10.286 + 10.287 +float Track::operator ()(long tmsec) const 10.288 +{ 10.289 + return anm_get_value(trk, ANM_MSEC2TM(tmsec)); 10.290 +} 10.291 + 10.292 + 10.293 +// ---- Track3 ---- 10.294 + 10.295 +void Track3::set_interpolator(Interp in) 10.296 +{ 10.297 + for(int i=0; i<3; i++) { 10.298 + track[i].set_interpolator(in); 10.299 + } 10.300 +} 10.301 + 10.302 +Interp Track3::get_interpolator() const 10.303 +{ 10.304 + return track[0].get_interpolator(); 10.305 +} 10.306 + 10.307 +void Track3::set_extrapolator(Extrap ex) 10.308 +{ 10.309 + for(int i=0; i<3; i++) { 10.310 + track[i].set_extrapolator(ex); 10.311 + } 10.312 +} 10.313 + 10.314 +Extrap Track3::get_extrapolator() const 10.315 +{ 10.316 + return track[0].get_extrapolator(); 10.317 +} 10.318 + 10.319 +void Track3::set_default(const Vector3 &def) 10.320 +{ 10.321 + for(int i=0; i<3; i++) { 10.322 + track[i].set_default(def[i]); 10.323 + } 10.324 +} 10.325 + 10.326 +void Track3::set_value(const Vector3 &val, long tmsec) 10.327 +{ 10.328 + for(int i=0; i<3; i++) { 10.329 + track[i].set_value(val[i], tmsec); 10.330 + } 10.331 +} 10.332 + 10.333 +Vector3 Track3::get_value(long tmsec) const 10.334 +{ 10.335 + return Vector3(track[0](tmsec), track[1](tmsec), track[2](tmsec)); 10.336 +} 10.337 + 10.338 +Vector3 Track3::operator ()(long tmsec) const 10.339 +{ 10.340 + return Vector3(track[0](tmsec), track[1](tmsec), track[2](tmsec)); 10.341 +} 10.342 + 10.343 + 10.344 +static inline anm_interpolator track_interpolator(Interp in) 10.345 +{ 10.346 + switch(in) { 10.347 + case INTERP_STEP: 10.348 + return ANM_INTERP_STEP; 10.349 + case INTERP_LINEAR: 10.350 + return ANM_INTERP_LINEAR; 10.351 + case INTERP_CUBIC: 10.352 + return ANM_INTERP_CUBIC; 10.353 + } 10.354 + 10.355 + assert(0); 10.356 + return ANM_INTERP_STEP; 10.357 +} 10.358 + 10.359 +static inline anm_extrapolator track_extrapolator(Extrap ex) 10.360 +{ 10.361 + switch(ex) { 10.362 + case EXTRAP_EXTEND: 10.363 + return ANM_EXTRAP_EXTEND; 10.364 + case EXTRAP_CLAMP: 10.365 + return ANM_EXTRAP_CLAMP; 10.366 + case EXTRAP_REPEAT: 10.367 + return ANM_EXTRAP_REPEAT; 10.368 + } 10.369 + 10.370 + assert(0); 10.371 + return ANM_EXTRAP_EXTEND; 10.372 +} 10.373 +
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/src/xform_node.h Sat Aug 17 23:51:24 2013 +0300 11.3 @@ -0,0 +1,134 @@ 11.4 +/* 11.5 +TODO: add multiple animations per node in libanim (i.e. multiple sets of tracks) 11.6 +*/ 11.7 +#ifndef XFORM_NODE_H_ 11.8 +#define XFORM_NODE_H_ 11.9 + 11.10 +#include <vector> 11.11 +#include "vmath/vector.h" 11.12 +#include "vmath/quat.h" 11.13 +#include "vmath/matrix.h" 11.14 + 11.15 +enum Interp { INTERP_STEP, INTERP_LINEAR, INTERP_CUBIC }; 11.16 +enum Extrap { EXTRAP_EXTEND, EXTRAP_CLAMP, EXTRAP_REPEAT }; 11.17 + 11.18 +struct anm_node; 11.19 +struct anm_track; 11.20 + 11.21 +// XXX all time arguments are milliseconds 11.22 + 11.23 +class XFormNode { 11.24 +private: 11.25 + struct anm_node *anm; 11.26 + std::vector<XFormNode*> children; 11.27 + 11.28 + Interp interp; 11.29 + Extrap extrap; 11.30 + 11.31 + Matrix4x4 local_matrix; 11.32 + Matrix4x4 bone_matrix; 11.33 + 11.34 + XFormNode(const XFormNode &node) {} 11.35 + XFormNode &operator =(const XFormNode &node) { return *this; } 11.36 + 11.37 +public: 11.38 + XFormNode(); 11.39 + virtual ~XFormNode(); 11.40 + 11.41 + void set_name(const char *name); 11.42 + const char *get_name() const; 11.43 + 11.44 + void set_interpolator(Interp in); 11.45 + Interp get_interpolator() const; 11.46 + void set_extrapolator(Extrap ex); 11.47 + Extrap get_extrapolator() const; 11.48 + 11.49 + // children management 11.50 + void add_child(XFormNode *child); 11.51 + void remove_child(XFormNode *child); 11.52 + 11.53 + int get_children_count() const; 11.54 + XFormNode *get_child(int idx); 11.55 + const XFormNode *get_child(int idx) const; 11.56 + 11.57 + 11.58 + void set_position(const Vector3 &pos, long tmsec = 0); 11.59 + Vector3 get_node_position(long tmsec = 0) const; 11.60 + 11.61 + void set_rotation(const Quaternion &quat, long tmsec = 0); 11.62 + Quaternion get_node_rotation(long tmsec = 0) const; 11.63 + 11.64 + void set_scaling(const Vector3 &pos, long tmsec = 0); 11.65 + Vector3 get_node_scaling(long tmsec = 0) const; 11.66 + 11.67 + // these take hierarchy into account 11.68 + Vector3 get_position(long tmsec = 0) const; 11.69 + Quaternion get_rotation(long tmsec = 0) const; 11.70 + Vector3 get_scaling(long tmsec = 0) const; 11.71 + 11.72 + void set_pivot(const Vector3 &pivot); 11.73 + Vector3 get_pivot() const; 11.74 + 11.75 + // the local matrix is concatenated with the regular node/anim matrix 11.76 + void set_local_matrix(const Matrix4x4 &mat); 11.77 + const Matrix4x4 &get_local_matrix() const; 11.78 + 11.79 + // for bone nodes, the transformation of the bone in bind position 11.80 + void set_bone_matrix(const Matrix4x4 &bmat); 11.81 + const Matrix4x4 &get_bone_matrix() const; 11.82 + 11.83 + // node transformation alone 11.84 + void get_node_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat = 0) const; 11.85 + 11.86 + // node transformation taking hierarchy into account 11.87 + void get_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat = 0) const; 11.88 +}; 11.89 + 11.90 + 11.91 +class Track { 11.92 +private: 11.93 + struct anm_track *trk; 11.94 + Interp interp; 11.95 + Extrap extrap; 11.96 + 11.97 +public: 11.98 + Track(); 11.99 + ~Track(); 11.100 + 11.101 + Track(const Track &trk); 11.102 + Track &operator =(const Track &trk); 11.103 + 11.104 + void set_interpolator(Interp in); 11.105 + Interp get_interpolator() const; 11.106 + void set_extrapolator(Extrap ex); 11.107 + Extrap get_extrapolator() const; 11.108 + 11.109 + void set_default(double def); 11.110 + 11.111 + void set_value(float val, long tmsec = 0); 11.112 + float get_value(long tmsec = 0) const; 11.113 + 11.114 + // the same as get_value 11.115 + float operator ()(long tmsec = 0) const; 11.116 +}; 11.117 + 11.118 +class Track3 { 11.119 +private: 11.120 + Track track[3]; 11.121 + 11.122 +public: 11.123 + void set_interpolator(Interp in); 11.124 + Interp get_interpolator() const; 11.125 + void set_extrapolator(Extrap ex); 11.126 + Extrap get_extrapolator() const; 11.127 + 11.128 + void set_default(const Vector3 &def); 11.129 + 11.130 + void set_value(const Vector3 &val, long tmsec = 0); 11.131 + Vector3 get_value(long tmsec = 0) const; 11.132 + 11.133 + // the same as get_value 11.134 + Vector3 operator ()(long tmsec = 0) const; 11.135 +}; 11.136 + 11.137 +#endif /* XFORM_NODE_H_ */