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