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;