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 }
|