goat3d

view src/mesh.cc @ 33:f43f4849c86a

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