rev |
line source |
nuclear@19
|
1 #include "goat3d_impl.h"
|
nuclear@1
|
2 #include "mesh.h"
|
nuclear@19
|
3 #include "openctm.h"
|
nuclear@19
|
4 #include "log.h"
|
nuclear@1
|
5
|
nuclear@1
|
6 Mesh::Mesh()
|
nuclear@1
|
7 {
|
nuclear@8
|
8 material = 0;
|
nuclear@1
|
9 }
|
nuclear@1
|
10
|
nuclear@19
|
11 bool Mesh::load(const char *fname)
|
nuclear@19
|
12 {
|
nuclear@19
|
13 CTMcontext ctm = ctmNewContext(CTM_IMPORT);
|
nuclear@19
|
14
|
nuclear@19
|
15 ctmLoad(ctm, fname);
|
nuclear@19
|
16 if(ctmGetError(ctm) != CTM_NONE) {
|
nuclear@19
|
17 logmsg(LOG_ERROR, "failed to load ctm mesh: %s\n", fname);
|
nuclear@19
|
18 ctmFreeContext(ctm);
|
nuclear@19
|
19 return false;
|
nuclear@19
|
20 }
|
nuclear@19
|
21
|
nuclear@19
|
22 int vnum = ctmGetInteger(ctm, CTM_VERTEX_COUNT);
|
nuclear@19
|
23 int fnum = ctmGetInteger(ctm, CTM_TRIANGLE_COUNT);
|
nuclear@19
|
24
|
nuclear@19
|
25 const CTMfloat *vertices = ctmGetFloatArray(ctm, CTM_VERTICES);
|
nuclear@19
|
26 if(!vertices) {
|
nuclear@19
|
27 logmsg(LOG_ERROR, "failed to load ctm mesh: %s: no vertices found!\n", fname);
|
nuclear@19
|
28 ctmFreeContext(ctm);
|
nuclear@19
|
29 return false;
|
nuclear@19
|
30 }
|
nuclear@19
|
31
|
nuclear@19
|
32 const CTMuint *indices = ctmGetIntegerArray(ctm, CTM_INDICES);
|
nuclear@19
|
33 if(!indices) {
|
nuclear@19
|
34 logmsg(LOG_ERROR, "failed to load ctm mesh: %s: no faces found!\n", fname);
|
nuclear@19
|
35 ctmFreeContext(ctm);
|
nuclear@19
|
36 return false;
|
nuclear@19
|
37 }
|
nuclear@19
|
38
|
nuclear@19
|
39 const CTMfloat *normals = ctmGetFloatArray(ctm, CTM_NORMALS);
|
nuclear@19
|
40 const CTMfloat *texcoords = ctmGetFloatArray(ctm, CTM_UV_MAP_1);
|
nuclear@19
|
41
|
nuclear@19
|
42 CTMenum tangent_id = ctmGetNamedAttribMap(ctm, "tangent");
|
nuclear@19
|
43 const CTMfloat *tangents = tangent_id ? ctmGetFloatArray(ctm, tangent_id) : 0;
|
nuclear@19
|
44
|
nuclear@19
|
45 CTMenum skinweight_id = ctmGetNamedAttribMap(ctm, "skin_weight");
|
nuclear@19
|
46 const CTMfloat *skinweights = skinweight_id ? ctmGetFloatArray(ctm, skinweight_id) : 0;
|
nuclear@19
|
47
|
nuclear@19
|
48 CTMenum skinmat_id = ctmGetNamedAttribMap(ctm, "skin_matrix");
|
nuclear@19
|
49 const CTMuint *skinmats = skinmat_id ? ctmGetIntegerArray(ctm, skinmat_id) : 0;
|
nuclear@19
|
50
|
nuclear@19
|
51 CTMenum color_id = ctmGetNamedAttribMap(ctm, "color");
|
nuclear@19
|
52 const CTMfloat *colors = color_id ? ctmGetFloatArray(ctm, color_id) : 0;
|
nuclear@19
|
53
|
nuclear@19
|
54 // now put everything we found into our vectors
|
nuclear@19
|
55 this->vertices = VECDATA(Vector3, vertices, vnum);
|
nuclear@19
|
56
|
nuclear@19
|
57 if(texcoords) {
|
nuclear@19
|
58 this->texcoords = VECDATA(Vector2, texcoords, vnum);
|
nuclear@19
|
59 }
|
nuclear@19
|
60 if(normals) {
|
nuclear@19
|
61 this->normals = VECDATA(Vector3, normals, vnum);
|
nuclear@19
|
62 }
|
nuclear@19
|
63 if(skinweights) {
|
nuclear@19
|
64 this->skin_weights = VECDATA(Vector4, skinweights, vnum);
|
nuclear@19
|
65 }
|
nuclear@19
|
66 if(colors) {
|
nuclear@19
|
67 this->colors = VECDATA(Vector4, colors, vnum);
|
nuclear@19
|
68 }
|
nuclear@19
|
69
|
nuclear@19
|
70 // the rest need converting
|
nuclear@19
|
71 if(tangents) {
|
nuclear@19
|
72 this->tangents.clear();
|
nuclear@19
|
73 this->tangents.resize(vnum);
|
nuclear@19
|
74
|
nuclear@19
|
75 for(int i=0; i<vnum; i++) {
|
nuclear@19
|
76 for(int j=0; j<3; j++) {
|
nuclear@19
|
77 this->tangents[i][j] = tangents[j];
|
nuclear@19
|
78 }
|
nuclear@19
|
79 tangents += 4;
|
nuclear@19
|
80 }
|
nuclear@19
|
81 }
|
nuclear@19
|
82 if(skinmats) {
|
nuclear@19
|
83 this->skin_matrices.clear();
|
nuclear@19
|
84 this->skin_matrices.resize(vnum);
|
nuclear@19
|
85
|
nuclear@19
|
86 for(int i=0; i<vnum; i++) {
|
nuclear@19
|
87 this->skin_matrices[i].x = skinmats[0];
|
nuclear@19
|
88 this->skin_matrices[i].y = skinmats[1];
|
nuclear@19
|
89 this->skin_matrices[i].z = skinmats[2];
|
nuclear@19
|
90 this->skin_matrices[i].w = skinmats[3];
|
nuclear@19
|
91 }
|
nuclear@19
|
92 }
|
nuclear@19
|
93
|
nuclear@19
|
94 // grab the face data
|
nuclear@19
|
95 this->faces.clear();
|
nuclear@19
|
96 this->faces.resize(fnum);
|
nuclear@19
|
97
|
nuclear@19
|
98 for(int i=0; i<fnum; i++) {
|
nuclear@19
|
99 for(int j=0; j<3; j++) {
|
nuclear@19
|
100 this->faces[i].v[j] = indices[j];
|
nuclear@19
|
101 }
|
nuclear@19
|
102 indices += 3;
|
nuclear@19
|
103 }
|
nuclear@19
|
104
|
nuclear@19
|
105
|
nuclear@19
|
106 ctmFreeContext(ctm);
|
nuclear@19
|
107 return true;
|
nuclear@19
|
108 }
|
nuclear@19
|
109
|
nuclear@19
|
110 bool Mesh::save(const char *fname) const
|
nuclear@19
|
111 {
|
nuclear@19
|
112 int vnum = (int)vertices.size();
|
nuclear@30
|
113 int fnum = (int)faces.size();
|
nuclear@30
|
114
|
nuclear@30
|
115 if(!vnum || !fnum) {
|
nuclear@30
|
116 return false;
|
nuclear@30
|
117 }
|
nuclear@19
|
118
|
nuclear@19
|
119 CTMcontext ctm = ctmNewContext(CTM_EXPORT);
|
nuclear@19
|
120
|
nuclear@19
|
121 // vertices, normals, and face-vertex indices
|
nuclear@30
|
122 ctmDefineMesh(ctm, &vertices[0].x, vnum, (CTMuint*)faces[0].v, fnum,
|
nuclear@19
|
123 normals.empty() ? 0 : &normals[0].x);
|
nuclear@19
|
124
|
nuclear@19
|
125 // texture coordinates
|
nuclear@19
|
126 if(!texcoords.empty()) {
|
nuclear@19
|
127 ctmAddUVMap(ctm, &texcoords[0].x, "texcoord", 0);
|
nuclear@19
|
128 }
|
nuclear@19
|
129
|
nuclear@19
|
130 // vertex colors
|
nuclear@19
|
131 if(!colors.empty()) {
|
nuclear@19
|
132 ctmAddAttribMap(ctm, &colors[0].x, "color");
|
nuclear@19
|
133 }
|
nuclear@19
|
134
|
nuclear@19
|
135 // skin weights
|
nuclear@19
|
136 if(!skin_weights.empty()) {
|
nuclear@19
|
137 ctmAddAttribMap(ctm, &skin_weights[0].x, "skin_weight");
|
nuclear@19
|
138 }
|
nuclear@19
|
139
|
nuclear@19
|
140 // if either of the non-float4 attributes are present we need to make a tmp array
|
nuclear@19
|
141 CTMfloat *attr_array = 0;
|
nuclear@19
|
142 if(!tangents.empty() || !skin_matrices.empty()) {
|
nuclear@19
|
143 attr_array = new CTMfloat[vnum * 4 * sizeof *attr_array];
|
nuclear@19
|
144 }
|
nuclear@19
|
145
|
nuclear@19
|
146 // tangents
|
nuclear@19
|
147 if(!tangents.empty()) {
|
nuclear@19
|
148 CTMfloat *ptr = attr_array;
|
nuclear@19
|
149
|
nuclear@19
|
150 for(int i=0; i<vnum; i++) {
|
nuclear@19
|
151 *ptr++ = tangents[i].x;
|
nuclear@19
|
152 *ptr++ = tangents[i].y;
|
nuclear@19
|
153 *ptr++ = tangents[i].z;
|
nuclear@19
|
154 *ptr++ = 1.0;
|
nuclear@19
|
155 }
|
nuclear@19
|
156 ctmAddAttribMap(ctm, attr_array, "tangent");
|
nuclear@19
|
157 }
|
nuclear@19
|
158
|
nuclear@19
|
159 // skin matrix indices (4 per vertex)
|
nuclear@19
|
160 if(!skin_matrices.empty()) {
|
nuclear@19
|
161 CTMfloat *ptr = attr_array;
|
nuclear@19
|
162
|
nuclear@19
|
163 for(int i=0; i<vnum; i++) {
|
nuclear@19
|
164 *ptr++ = (float)skin_matrices[i].x;
|
nuclear@19
|
165 *ptr++ = (float)skin_matrices[i].y;
|
nuclear@19
|
166 *ptr++ = (float)skin_matrices[i].z;
|
nuclear@19
|
167 *ptr++ = (float)skin_matrices[i].w;
|
nuclear@19
|
168 }
|
nuclear@19
|
169 ctmAddAttribMap(ctm, attr_array, "skin_matrix");
|
nuclear@19
|
170 }
|
nuclear@19
|
171
|
nuclear@19
|
172 delete [] attr_array;
|
nuclear@19
|
173
|
nuclear@19
|
174 /* TODO find a way to specify the nodes participating in the skinning of this mesh
|
nuclear@19
|
175 * probably in the comment field?
|
nuclear@19
|
176 */
|
nuclear@19
|
177
|
nuclear@19
|
178 logmsg(LOG_INFO, "saving CTM mesh file: %s\n", fname);
|
nuclear@19
|
179 ctmSave(ctm, fname);
|
nuclear@19
|
180
|
nuclear@19
|
181 ctmFreeContext(ctm);
|
nuclear@19
|
182 return true;
|
nuclear@19
|
183 }
|
nuclear@19
|
184
|
nuclear@8
|
185 void Mesh::set_material(Material *mat)
|
nuclear@1
|
186 {
|
nuclear@8
|
187 material = mat;
|
nuclear@1
|
188 }
|
nuclear@1
|
189
|
nuclear@8
|
190 Material *Mesh::get_material()
|
nuclear@1
|
191 {
|
nuclear@8
|
192 return material;
|
nuclear@1
|
193 }
|
nuclear@1
|
194
|
nuclear@8
|
195 const Material *Mesh::get_material() const
|
nuclear@1
|
196 {
|
nuclear@8
|
197 return material;
|
nuclear@1
|
198 }
|