goat3d

view src/mesh.cc @ 57:76d0f55f9d5f

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