vrheights

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