vrheights

annotate src/scenefile.cc @ 14:25cab9e20c9c

mesh vbos
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 09 Oct 2014 01:29:28 +0300
parents
children
rev   line source
nuclear@8 1 #include <float.h>
nuclear@8 2 #include <assert.h>
nuclear@8 3 #include <string>
nuclear@8 4 #include <map>
nuclear@8 5 #include "scenefile.h"
nuclear@8 6 #include "goat3d.h"
nuclear@8 7 #include "texman.h"
nuclear@8 8
nuclear@8 9 SceneFile::SceneFile()
nuclear@8 10 {
nuclear@8 11 }
nuclear@8 12
nuclear@8 13 SceneFile::~SceneFile()
nuclear@8 14 {
nuclear@8 15 }
nuclear@8 16
nuclear@8 17 bool SceneFile::load(const char *fname)
nuclear@8 18 {
nuclear@8 19 std::map<struct goat3d_mesh*, Mesh*> meshmap;
nuclear@8 20
nuclear@8 21 struct goat3d *g3d = goat3d_create();
nuclear@8 22 if(!g3d) return false;
nuclear@8 23
nuclear@8 24 if(goat3d_load(g3d, fname) == -1) {
nuclear@8 25 return false;
nuclear@8 26 }
nuclear@8 27
nuclear@8 28 int nmeshes = goat3d_get_mesh_count(g3d);
nuclear@8 29 for(int i=0; i<nmeshes; i++) {
nuclear@8 30 struct goat3d_mesh *gm = goat3d_get_mesh(g3d, i);
nuclear@8 31 int nverts = goat3d_get_mesh_attrib_count(gm, GOAT3D_MESH_ATTR_VERTEX);
nuclear@8 32
nuclear@8 33 Mesh *m = new Mesh;
nuclear@8 34 m->set_vertex_data(MESH_VERTEX, 3, nverts, (float*)goat3d_get_mesh_attribs(gm, GOAT3D_MESH_ATTR_VERTEX));
nuclear@8 35
nuclear@8 36 int nnorm = goat3d_get_mesh_attrib_count(gm, GOAT3D_MESH_ATTR_NORMAL);
nuclear@8 37 if(nnorm) {
nuclear@8 38 assert(nnorm == nverts);
nuclear@8 39 m->set_vertex_data(MESH_NORMAL, 3, nnorm, (float*)goat3d_get_mesh_attribs(gm, GOAT3D_MESH_ATTR_NORMAL));
nuclear@8 40 }
nuclear@8 41
nuclear@8 42 int ntex = goat3d_get_mesh_attrib_count(gm, GOAT3D_MESH_ATTR_TEXCOORD);
nuclear@8 43 if(ntex) {
nuclear@8 44 assert(ntex == nverts);
nuclear@8 45 m->set_vertex_data(MESH_TEXCOORD, 2, ntex, (float*)goat3d_get_mesh_attribs(gm, GOAT3D_MESH_ATTR_TEXCOORD));
nuclear@8 46 }
nuclear@8 47
nuclear@8 48 int ntang = goat3d_get_mesh_attrib_count(gm, GOAT3D_MESH_ATTR_TANGENT);
nuclear@8 49 if(ntang) {
nuclear@8 50 assert(ntang == nverts);
nuclear@8 51 m->set_vertex_data(MESH_TANGENT, 3, ntang, (float*)goat3d_get_mesh_attribs(gm, GOAT3D_MESH_ATTR_TANGENT));
nuclear@8 52 }
nuclear@8 53
nuclear@8 54 int nfaces = goat3d_get_mesh_face_count(gm);
nuclear@8 55 if(nfaces) {
nuclear@8 56 m->set_index_data(nfaces * 3, (unsigned int*)goat3d_get_mesh_faces(gm));
nuclear@8 57 }
nuclear@8 58
nuclear@8 59 mesh.push_back(m);
nuclear@8 60 meshmap[gm] = m;
nuclear@8 61 // TODO: do this after nodes are loaded per object to pre-transform if applicable
nuclear@8 62 colmesh.push_back(m);
nuclear@8 63 }
nuclear@8 64
nuclear@8 65 /* iterate the nodes and create objects */
nuclear@8 66 int nnodes = goat3d_get_node_count(g3d);
nuclear@8 67 for(int i=0; i<nnodes; i++) {
nuclear@8 68 struct goat3d_node *gn = goat3d_get_node(g3d, i);
nuclear@8 69 if(goat3d_get_node_type(gn) != GOAT3D_NODE_MESH) {
nuclear@8 70 continue;
nuclear@8 71 }
nuclear@8 72 struct goat3d_mesh *gm = (struct goat3d_mesh*)goat3d_get_node_object(gn);
nuclear@8 73 if(!gm) continue;
nuclear@8 74 Mesh *m = meshmap[gm];
nuclear@8 75 if(!m) continue;
nuclear@8 76
nuclear@8 77 Object *obj = new Object;
nuclear@8 78 obj->set_mesh(m);
nuclear@8 79
nuclear@8 80 float mat[16];
nuclear@8 81 goat3d_get_node_matrix(gn, mat, 0);
nuclear@8 82 for(int i=0; i<4; i++) {
nuclear@8 83 for(int j=0; j<4; j++) {
nuclear@8 84 obj->xform[i][j] = mat[i * 4 + j];
nuclear@8 85 }
nuclear@8 86 }
nuclear@8 87
nuclear@8 88 struct goat3d_material *gmtl = goat3d_get_mesh_mtl(gm);
nuclear@8 89 const float *col = goat3d_get_mtl_attrib(gmtl, GOAT3D_MAT_ATTR_DIFFUSE);
nuclear@8 90 if(col) {
nuclear@8 91 obj->mtl.diffuse = Vector3(col[0], col[1], col[2]);
nuclear@8 92 }
nuclear@8 93 if((col = goat3d_get_mtl_attrib(gmtl, GOAT3D_MAT_ATTR_SPECULAR))) {
nuclear@8 94 obj->mtl.specular = Vector3(col[0], col[1], col[2]);
nuclear@8 95 }
nuclear@8 96 if((col = goat3d_get_mtl_attrib(gmtl, GOAT3D_MAT_ATTR_ALPHA))) {
nuclear@8 97 obj->mtl.alpha = col[0];
nuclear@8 98 }
nuclear@8 99 if((col = goat3d_get_mtl_attrib(gmtl, GOAT3D_MAT_ATTR_SHININESS))) {
nuclear@8 100 obj->mtl.shininess = col[0];
nuclear@8 101 }
nuclear@8 102 const char *fname = goat3d_get_mtl_attrib_map(gmtl, GOAT3D_MAT_ATTR_DIFFUSE);
nuclear@8 103 if(fname) {
nuclear@8 104 obj->mtl.tex = get_texture(fname);
nuclear@8 105 }
nuclear@8 106
nuclear@8 107 this->obj.push_back(obj);
nuclear@8 108 }
nuclear@8 109
nuclear@8 110 goat3d_free(g3d);
nuclear@8 111 return true;
nuclear@8 112 }
nuclear@8 113
nuclear@8 114 static Vector3 bary(const Vector3 &a, const Vector3 &b, const Vector3 &c,
nuclear@8 115 const Vector3 &p)
nuclear@8 116 {
nuclear@8 117 float ctri = cross_product(b - a, c - a).length();
nuclear@8 118 if(ctri == 0.0f) {
nuclear@8 119 return Vector3(2, 0, 0);
nuclear@8 120 }
nuclear@8 121
nuclear@8 122 float ca = cross_product(b - p, c - p).length() / ctri;
nuclear@8 123 float cb = cross_product(a - p, c - p).length() / ctri;
nuclear@8 124 float cc = cross_product(a - p, b - p).length() / ctri;
nuclear@8 125
nuclear@8 126 return Vector3(ca, cb, cc);
nuclear@8 127 }
nuclear@8 128
nuclear@8 129 extern MeshFace dbg_walk_face;
nuclear@8 130
nuclear@8 131 Vector3 SceneFile::find_walk_pos(const Vector3 &pos) const
nuclear@8 132 {
nuclear@8 133 float max_y = -FLT_MAX;
nuclear@8 134 Vector3 pos_xz = Vector3(pos.x, 0, pos.z);
nuclear@8 135
nuclear@8 136 for(size_t i=0; i<colmesh.size(); i++) {
nuclear@8 137 const Mesh *m = colmesh[i];
nuclear@8 138
nuclear@8 139 int num_faces = m->get_face_count();
nuclear@8 140 for(int j=0; j<num_faces; j++) {
nuclear@8 141 MeshFace face = m->get_face(j);
nuclear@8 142
nuclear@8 143 Vector3 v0_xz = Vector3(face.v[0].x, 0, face.v[0].z);
nuclear@8 144 Vector3 v1_xz = Vector3(face.v[1].x, 0, face.v[1].z);
nuclear@8 145 Vector3 v2_xz = Vector3(face.v[2].x, 0, face.v[2].z);
nuclear@8 146
nuclear@8 147 Vector3 bc = bary(v0_xz, v1_xz, v2_xz, pos_xz);
nuclear@8 148 float bsum = bc.x + bc.y + bc.z;
nuclear@8 149 if(bsum > 1.000001) {
nuclear@8 150 continue;
nuclear@8 151 }
nuclear@8 152
nuclear@8 153 float y = face.v[0].y * bc.x + face.v[1].y * bc.y + face.v[2].y * bc.z;
nuclear@8 154 if(y > max_y && y <= pos.y) {
nuclear@8 155 dbg_walk_face = face;
nuclear@8 156 max_y = y;
nuclear@8 157 }
nuclear@8 158 }
nuclear@8 159 }
nuclear@8 160
nuclear@8 161 if(max_y == -FLT_MAX) {
nuclear@8 162 return pos;
nuclear@8 163 }
nuclear@8 164 return Vector3(pos.x, max_y, pos.z);
nuclear@8 165 }