goat3d

annotate src/mesh.cc @ 47:498ca7ac7047

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