-void cmesh_invalidate_attrib(struct cmesh *cm, int attr);
-void cmesh_invalidate_index(struct cmesh *cm);
-
-int cmesh_append(struct cmesh *cmdest, struct cmesh *cmsrc);
-
-/* immediate-mode style mesh construction interface */
-int cmesh_vertex(struct cmesh *cm, float x, float y, float z);
-int cmesh_normal(struct cmesh *cm, float nx, float ny, float nz);
-int cmesh_tangent(struct cmesh *cm, float tx, float ty, float tz);
-int cmesh_texcoord(struct cmesh *cm, float u, float v, float w);
-int cmesh_boneweights(struct cmesh *cm, float w1, float w2, float w3, float w4);
-int cmesh_boneidx(struct cmesh *cm, int idx1, int idx2, int idx3, int idx4);
+void cmesh_invalidate_vbo(struct cmesh *cm, int attr)
+{
+ int i;
+
+ if(attr >= CMESH_NUM_ATTR) {
+ return;
+ }
+
+ if(attr < 0) {
+ for(i=0; i<CMESH_NUM_ATTR; i++) {
+ cm->vattr[i].vbo_valid = 0;
+ }
+ } else {
+ cm->vattr[attr].vbo_valid = 0;
+ }
+}
+
+void cmesh_invalidate_index(struct cmesh *cm)
+{
+ cm->ibo_valid = 0;
+}
+
+int cmesh_append(struct cmesh *cmdest, struct cmesh *cmsrc)
+{
+ int i, nelem, nidx, newsz, origsz;
+ float *vptr;
+ unsigned int *iptr;
+ unsigned int idxoffs;
+
+ if(!cmdest->nverts) {
+ return cmesh_clone(cmdest, cmsrc);
+ }
+
+ for(i=0; i<CMESH_NUM_ATTR; i++) {
+ if(cmesh_has_attrib(cmdest) && cmesh_has_attrib(cmsrc)) {
+ /* force validation of the data arrays */
+ cmesh_attrib(cmdest, i);
+ cmesh_attrib_ro(cmsrc, id);
+
+ assert(cmdest->vattr[i].nelem == cmsrc->vattr[i].nelem);
+ nelem = cmdest->vattr[i].nelem;
+ origsz = cmdest->nverts * nelem;
+ newsz = cmdest->nverts + cmsrc->nverts * nelem;
+
+ if(!(vptr = dynarr_resize(cmdest->vattr[i].data, newsz))) {
+ return -1;
+ }
+ memcpy(vptr + origsz, cmsrc->vattr[i].data, cmsrc->nverts * nelem * sizeof(float));
+ cmdest->vattr[i].data = vptr;
+ }
+ }
+
+ if(cmesh_indexed(cmdest)) {
+ assert(cmesh_indexed(cmsrc));
+ /* force validation ... */
+ cmesh_index(cmdest);
+ cmesh_index_ro(cmsrc);
+
+ idxoff = cmdest->nverts;
+ origsz = dynarr_size(cmdest->idata);
+ srcsz = dynarr_size(cmsrc->idata);
+ newsz = origsz + srcsz;
+
+ if(!(iptr = dynarr_resize(cmdest->idata, newsz))) {
+ return -1;
+ }
+ cmdest->idata = iptr;
+
+ /* copy and fixup all the new indices */
+ iptr += origsz;
+ for(i=0; i<srcsz; i++) {
+ *iptr++ = cmsrc->idata[i] + idxoffs;
+ }
+ }
+
+ cmdest->wire_ibo_valid = 0;
+ cmdest->aabb_valid = 0;
+ cmdest->bsph_valid = 0;
+}
+
+/* assemble a complete vertex by adding all the useful attributes */
+int cmesh_vertex(struct cmesh *cm, float x, float y, float z)
+{
+ int i, j;
+
+ cgm_wcons(cm->cur_val + CMESH_ATTR_VERTEX, x, y, z, 1.0f);
+ cm->vattr[CMESH_ATTR_VERTEX].data_valid = 1;
+ cm->vattr[CMESH_ATTR_VERTEX].nelem = 3;
+
+ for(i=0; i<CMESH_ATTR_VERTEX; i++) {
+ if(cm->vattr[i].data_valid) {
+ for(j=0; j<cm->vattr[CMESH_ATTR_VERTEX].nelem; j++) {
+ float *tmp = dynarr_push(cm->vattr[i].data, cur_val[i] + j);
+ if(!tmp) return -1;
+ cm->vattr[i].data = tmp;
+ }
+ }
+ cm->vattr[i].vbo_valid = 0;
+ cm->vattr[i].data_valid = 1;
+ }
+
+ if(cm->idata_valid) {
+ cm->idata = dynarr_clear(cm->idata);
+ }
+ cm->ibo_valid = cm->idata_valid = 0;
+ return 0;
+}
+
+void cmesh_normal(struct cmesh *cm, float nx, float ny, float nz)
+{
+ cgm_wcons(cm->cur_val + CMESH_ATTR_NORMAL, nx, ny, nz, 1.0f);
+ cm->vattr[CMESH_ATTR_NORMAL].nelem = 3;
+}
+
+void cmesh_tangent(struct cmesh *cm, float tx, float ty, float tz)
+{
+ cgm_wcons(cm->cur_val + CMESH_ATTR_TANGENT, tx, ty, tz, 1.0f);
+ cm->vattr[CMESH_ATTR_TANGENT].nelem = 3;
+}
+
+void cmesh_texcoord(struct cmesh *cm, float u, float v, float w)
+{
+ cgm_wcons(cm->cur_val + CMESH_ATTR_TEXCOORD, u, v, w, 1.0f);
+ cm->vattr[CMESH_ATTR_TEXCOORD].nelem = 3;
+}
+
+void cmesh_boneweights(struct cmesh *cm, float w1, float w2, float w3, float w4)
+{
+ cgm_wcons(cm->cur_val + CMESH_ATTR_BONEWEIGHTS, w1, w2, w3, w4);
+ cm->vattr[CMESH_ATTR_BONEWEIGHTS].nelem = 4;
+}
+
+void cmesh_boneidx(struct cmesh *cm, int idx1, int idx2, int idx3, int idx4)
+{
+ cgm_wcons(cm->cur_val + CMESH_ATTR_BONEIDX, idx1, idx2, idx3, idx4);
+ cm->vattr[CMESH_ATTR_BONEIDX].nelem = 4;
+}