goat3d
diff src/mesh.cc @ 19:b35427826b60
- added XML format reading support
- wrote a rudimentary version of goatview
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 27 Sep 2013 06:58:37 +0300 |
parents | f1b4c27382ce |
children | 0fe02696fb1e |
line diff
1.1 --- a/src/mesh.cc Fri Sep 27 03:17:36 2013 +0300 1.2 +++ b/src/mesh.cc Fri Sep 27 06:58:37 2013 +0300 1.3 @@ -1,10 +1,182 @@ 1.4 +#include "goat3d_impl.h" 1.5 #include "mesh.h" 1.6 +#include "openctm.h" 1.7 +#include "log.h" 1.8 1.9 Mesh::Mesh() 1.10 { 1.11 material = 0; 1.12 } 1.13 1.14 +bool Mesh::load(const char *fname) 1.15 +{ 1.16 + CTMcontext ctm = ctmNewContext(CTM_IMPORT); 1.17 + 1.18 + ctmLoad(ctm, fname); 1.19 + if(ctmGetError(ctm) != CTM_NONE) { 1.20 + logmsg(LOG_ERROR, "failed to load ctm mesh: %s\n", fname); 1.21 + ctmFreeContext(ctm); 1.22 + return false; 1.23 + } 1.24 + 1.25 + int vnum = ctmGetInteger(ctm, CTM_VERTEX_COUNT); 1.26 + int fnum = ctmGetInteger(ctm, CTM_TRIANGLE_COUNT); 1.27 + 1.28 + const CTMfloat *vertices = ctmGetFloatArray(ctm, CTM_VERTICES); 1.29 + if(!vertices) { 1.30 + logmsg(LOG_ERROR, "failed to load ctm mesh: %s: no vertices found!\n", fname); 1.31 + ctmFreeContext(ctm); 1.32 + return false; 1.33 + } 1.34 + 1.35 + const CTMuint *indices = ctmGetIntegerArray(ctm, CTM_INDICES); 1.36 + if(!indices) { 1.37 + logmsg(LOG_ERROR, "failed to load ctm mesh: %s: no faces found!\n", fname); 1.38 + ctmFreeContext(ctm); 1.39 + return false; 1.40 + } 1.41 + 1.42 + const CTMfloat *normals = ctmGetFloatArray(ctm, CTM_NORMALS); 1.43 + const CTMfloat *texcoords = ctmGetFloatArray(ctm, CTM_UV_MAP_1); 1.44 + 1.45 + CTMenum tangent_id = ctmGetNamedAttribMap(ctm, "tangent"); 1.46 + const CTMfloat *tangents = tangent_id ? ctmGetFloatArray(ctm, tangent_id) : 0; 1.47 + 1.48 + CTMenum skinweight_id = ctmGetNamedAttribMap(ctm, "skin_weight"); 1.49 + const CTMfloat *skinweights = skinweight_id ? ctmGetFloatArray(ctm, skinweight_id) : 0; 1.50 + 1.51 + CTMenum skinmat_id = ctmGetNamedAttribMap(ctm, "skin_matrix"); 1.52 + const CTMuint *skinmats = skinmat_id ? ctmGetIntegerArray(ctm, skinmat_id) : 0; 1.53 + 1.54 + CTMenum color_id = ctmGetNamedAttribMap(ctm, "color"); 1.55 + const CTMfloat *colors = color_id ? ctmGetFloatArray(ctm, color_id) : 0; 1.56 + 1.57 + // now put everything we found into our vectors 1.58 + this->vertices = VECDATA(Vector3, vertices, vnum); 1.59 + 1.60 + if(texcoords) { 1.61 + this->texcoords = VECDATA(Vector2, texcoords, vnum); 1.62 + } 1.63 + if(normals) { 1.64 + this->normals = VECDATA(Vector3, normals, vnum); 1.65 + } 1.66 + if(skinweights) { 1.67 + this->skin_weights = VECDATA(Vector4, skinweights, vnum); 1.68 + } 1.69 + if(colors) { 1.70 + this->colors = VECDATA(Vector4, colors, vnum); 1.71 + } 1.72 + 1.73 + // the rest need converting 1.74 + if(tangents) { 1.75 + this->tangents.clear(); 1.76 + this->tangents.resize(vnum); 1.77 + 1.78 + for(int i=0; i<vnum; i++) { 1.79 + for(int j=0; j<3; j++) { 1.80 + this->tangents[i][j] = tangents[j]; 1.81 + } 1.82 + tangents += 4; 1.83 + } 1.84 + } 1.85 + if(skinmats) { 1.86 + this->skin_matrices.clear(); 1.87 + this->skin_matrices.resize(vnum); 1.88 + 1.89 + for(int i=0; i<vnum; i++) { 1.90 + this->skin_matrices[i].x = skinmats[0]; 1.91 + this->skin_matrices[i].y = skinmats[1]; 1.92 + this->skin_matrices[i].z = skinmats[2]; 1.93 + this->skin_matrices[i].w = skinmats[3]; 1.94 + } 1.95 + } 1.96 + 1.97 + // grab the face data 1.98 + this->faces.clear(); 1.99 + this->faces.resize(fnum); 1.100 + 1.101 + for(int i=0; i<fnum; i++) { 1.102 + for(int j=0; j<3; j++) { 1.103 + this->faces[i].v[j] = indices[j]; 1.104 + } 1.105 + indices += 3; 1.106 + } 1.107 + 1.108 + 1.109 + ctmFreeContext(ctm); 1.110 + return true; 1.111 +} 1.112 + 1.113 +bool Mesh::save(const char *fname) const 1.114 +{ 1.115 + int vnum = (int)vertices.size(); 1.116 + 1.117 + CTMcontext ctm = ctmNewContext(CTM_EXPORT); 1.118 + 1.119 + // vertices, normals, and face-vertex indices 1.120 + ctmDefineMesh(ctm, &vertices[0].x, vnum, (CTMuint*)faces[0].v, faces.size(), 1.121 + normals.empty() ? 0 : &normals[0].x); 1.122 + 1.123 + // texture coordinates 1.124 + if(!texcoords.empty()) { 1.125 + ctmAddUVMap(ctm, &texcoords[0].x, "texcoord", 0); 1.126 + } 1.127 + 1.128 + // vertex colors 1.129 + if(!colors.empty()) { 1.130 + ctmAddAttribMap(ctm, &colors[0].x, "color"); 1.131 + } 1.132 + 1.133 + // skin weights 1.134 + if(!skin_weights.empty()) { 1.135 + ctmAddAttribMap(ctm, &skin_weights[0].x, "skin_weight"); 1.136 + } 1.137 + 1.138 + // if either of the non-float4 attributes are present we need to make a tmp array 1.139 + CTMfloat *attr_array = 0; 1.140 + if(!tangents.empty() || !skin_matrices.empty()) { 1.141 + attr_array = new CTMfloat[vnum * 4 * sizeof *attr_array]; 1.142 + } 1.143 + 1.144 + // tangents 1.145 + if(!tangents.empty()) { 1.146 + CTMfloat *ptr = attr_array; 1.147 + 1.148 + for(int i=0; i<vnum; i++) { 1.149 + *ptr++ = tangents[i].x; 1.150 + *ptr++ = tangents[i].y; 1.151 + *ptr++ = tangents[i].z; 1.152 + *ptr++ = 1.0; 1.153 + } 1.154 + ctmAddAttribMap(ctm, attr_array, "tangent"); 1.155 + } 1.156 + 1.157 + // skin matrix indices (4 per vertex) 1.158 + if(!skin_matrices.empty()) { 1.159 + CTMfloat *ptr = attr_array; 1.160 + 1.161 + for(int i=0; i<vnum; i++) { 1.162 + *ptr++ = (float)skin_matrices[i].x; 1.163 + *ptr++ = (float)skin_matrices[i].y; 1.164 + *ptr++ = (float)skin_matrices[i].z; 1.165 + *ptr++ = (float)skin_matrices[i].w; 1.166 + } 1.167 + ctmAddAttribMap(ctm, attr_array, "skin_matrix"); 1.168 + } 1.169 + 1.170 + delete [] attr_array; 1.171 + 1.172 + /* TODO find a way to specify the nodes participating in the skinning of this mesh 1.173 + * probably in the comment field? 1.174 + */ 1.175 + 1.176 + logmsg(LOG_INFO, "saving CTM mesh file: %s\n", fname); 1.177 + ctmSave(ctm, fname); 1.178 + 1.179 + ctmFreeContext(ctm); 1.180 + return true; 1.181 +} 1.182 + 1.183 void Mesh::set_material(Material *mat) 1.184 { 1.185 material = mat;