vrheights
diff src/scenefile.cc @ 8:3f221bdc9bab
mesh loading
walk polys
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 03 Oct 2014 04:16:16 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/scenefile.cc Fri Oct 03 04:16:16 2014 +0300 1.3 @@ -0,0 +1,165 @@ 1.4 +#include <float.h> 1.5 +#include <assert.h> 1.6 +#include <string> 1.7 +#include <map> 1.8 +#include "scenefile.h" 1.9 +#include "goat3d.h" 1.10 +#include "texman.h" 1.11 + 1.12 +SceneFile::SceneFile() 1.13 +{ 1.14 +} 1.15 + 1.16 +SceneFile::~SceneFile() 1.17 +{ 1.18 +} 1.19 + 1.20 +bool SceneFile::load(const char *fname) 1.21 +{ 1.22 + std::map<struct goat3d_mesh*, Mesh*> meshmap; 1.23 + 1.24 + struct goat3d *g3d = goat3d_create(); 1.25 + if(!g3d) return false; 1.26 + 1.27 + if(goat3d_load(g3d, fname) == -1) { 1.28 + return false; 1.29 + } 1.30 + 1.31 + int nmeshes = goat3d_get_mesh_count(g3d); 1.32 + for(int i=0; i<nmeshes; i++) { 1.33 + struct goat3d_mesh *gm = goat3d_get_mesh(g3d, i); 1.34 + int nverts = goat3d_get_mesh_attrib_count(gm, GOAT3D_MESH_ATTR_VERTEX); 1.35 + 1.36 + Mesh *m = new Mesh; 1.37 + m->set_vertex_data(MESH_VERTEX, 3, nverts, (float*)goat3d_get_mesh_attribs(gm, GOAT3D_MESH_ATTR_VERTEX)); 1.38 + 1.39 + int nnorm = goat3d_get_mesh_attrib_count(gm, GOAT3D_MESH_ATTR_NORMAL); 1.40 + if(nnorm) { 1.41 + assert(nnorm == nverts); 1.42 + m->set_vertex_data(MESH_NORMAL, 3, nnorm, (float*)goat3d_get_mesh_attribs(gm, GOAT3D_MESH_ATTR_NORMAL)); 1.43 + } 1.44 + 1.45 + int ntex = goat3d_get_mesh_attrib_count(gm, GOAT3D_MESH_ATTR_TEXCOORD); 1.46 + if(ntex) { 1.47 + assert(ntex == nverts); 1.48 + m->set_vertex_data(MESH_TEXCOORD, 2, ntex, (float*)goat3d_get_mesh_attribs(gm, GOAT3D_MESH_ATTR_TEXCOORD)); 1.49 + } 1.50 + 1.51 + int ntang = goat3d_get_mesh_attrib_count(gm, GOAT3D_MESH_ATTR_TANGENT); 1.52 + if(ntang) { 1.53 + assert(ntang == nverts); 1.54 + m->set_vertex_data(MESH_TANGENT, 3, ntang, (float*)goat3d_get_mesh_attribs(gm, GOAT3D_MESH_ATTR_TANGENT)); 1.55 + } 1.56 + 1.57 + int nfaces = goat3d_get_mesh_face_count(gm); 1.58 + if(nfaces) { 1.59 + m->set_index_data(nfaces * 3, (unsigned int*)goat3d_get_mesh_faces(gm)); 1.60 + } 1.61 + 1.62 + mesh.push_back(m); 1.63 + meshmap[gm] = m; 1.64 + // TODO: do this after nodes are loaded per object to pre-transform if applicable 1.65 + colmesh.push_back(m); 1.66 + } 1.67 + 1.68 + /* iterate the nodes and create objects */ 1.69 + int nnodes = goat3d_get_node_count(g3d); 1.70 + for(int i=0; i<nnodes; i++) { 1.71 + struct goat3d_node *gn = goat3d_get_node(g3d, i); 1.72 + if(goat3d_get_node_type(gn) != GOAT3D_NODE_MESH) { 1.73 + continue; 1.74 + } 1.75 + struct goat3d_mesh *gm = (struct goat3d_mesh*)goat3d_get_node_object(gn); 1.76 + if(!gm) continue; 1.77 + Mesh *m = meshmap[gm]; 1.78 + if(!m) continue; 1.79 + 1.80 + Object *obj = new Object; 1.81 + obj->set_mesh(m); 1.82 + 1.83 + float mat[16]; 1.84 + goat3d_get_node_matrix(gn, mat, 0); 1.85 + for(int i=0; i<4; i++) { 1.86 + for(int j=0; j<4; j++) { 1.87 + obj->xform[i][j] = mat[i * 4 + j]; 1.88 + } 1.89 + } 1.90 + 1.91 + struct goat3d_material *gmtl = goat3d_get_mesh_mtl(gm); 1.92 + const float *col = goat3d_get_mtl_attrib(gmtl, GOAT3D_MAT_ATTR_DIFFUSE); 1.93 + if(col) { 1.94 + obj->mtl.diffuse = Vector3(col[0], col[1], col[2]); 1.95 + } 1.96 + if((col = goat3d_get_mtl_attrib(gmtl, GOAT3D_MAT_ATTR_SPECULAR))) { 1.97 + obj->mtl.specular = Vector3(col[0], col[1], col[2]); 1.98 + } 1.99 + if((col = goat3d_get_mtl_attrib(gmtl, GOAT3D_MAT_ATTR_ALPHA))) { 1.100 + obj->mtl.alpha = col[0]; 1.101 + } 1.102 + if((col = goat3d_get_mtl_attrib(gmtl, GOAT3D_MAT_ATTR_SHININESS))) { 1.103 + obj->mtl.shininess = col[0]; 1.104 + } 1.105 + const char *fname = goat3d_get_mtl_attrib_map(gmtl, GOAT3D_MAT_ATTR_DIFFUSE); 1.106 + if(fname) { 1.107 + obj->mtl.tex = get_texture(fname); 1.108 + } 1.109 + 1.110 + this->obj.push_back(obj); 1.111 + } 1.112 + 1.113 + goat3d_free(g3d); 1.114 + return true; 1.115 +} 1.116 + 1.117 +static Vector3 bary(const Vector3 &a, const Vector3 &b, const Vector3 &c, 1.118 + const Vector3 &p) 1.119 +{ 1.120 + float ctri = cross_product(b - a, c - a).length(); 1.121 + if(ctri == 0.0f) { 1.122 + return Vector3(2, 0, 0); 1.123 + } 1.124 + 1.125 + float ca = cross_product(b - p, c - p).length() / ctri; 1.126 + float cb = cross_product(a - p, c - p).length() / ctri; 1.127 + float cc = cross_product(a - p, b - p).length() / ctri; 1.128 + 1.129 + return Vector3(ca, cb, cc); 1.130 +} 1.131 + 1.132 +extern MeshFace dbg_walk_face; 1.133 + 1.134 +Vector3 SceneFile::find_walk_pos(const Vector3 &pos) const 1.135 +{ 1.136 + float max_y = -FLT_MAX; 1.137 + Vector3 pos_xz = Vector3(pos.x, 0, pos.z); 1.138 + 1.139 + for(size_t i=0; i<colmesh.size(); i++) { 1.140 + const Mesh *m = colmesh[i]; 1.141 + 1.142 + int num_faces = m->get_face_count(); 1.143 + for(int j=0; j<num_faces; j++) { 1.144 + MeshFace face = m->get_face(j); 1.145 + 1.146 + Vector3 v0_xz = Vector3(face.v[0].x, 0, face.v[0].z); 1.147 + Vector3 v1_xz = Vector3(face.v[1].x, 0, face.v[1].z); 1.148 + Vector3 v2_xz = Vector3(face.v[2].x, 0, face.v[2].z); 1.149 + 1.150 + Vector3 bc = bary(v0_xz, v1_xz, v2_xz, pos_xz); 1.151 + float bsum = bc.x + bc.y + bc.z; 1.152 + if(bsum > 1.000001) { 1.153 + continue; 1.154 + } 1.155 + 1.156 + float y = face.v[0].y * bc.x + face.v[1].y * bc.y + face.v[2].y * bc.z; 1.157 + if(y > max_y && y <= pos.y) { 1.158 + dbg_walk_face = face; 1.159 + max_y = y; 1.160 + } 1.161 + } 1.162 + } 1.163 + 1.164 + if(max_y == -FLT_MAX) { 1.165 + return pos; 1.166 + } 1.167 + return Vector3(pos.x, max_y, pos.z); 1.168 +}