void parg_mesh_free(parg_mesh* m) { if (!m) { return; } parg_buffer_free(m->coords); parg_buffer_free(m->indices); parg_buffer_free(m->normals); parg_buffer_free(m->uvs); free(m); }
parg_mesh* parg_mesh_from_file(const char* filepath) { parg_mesh* surf = calloc(sizeof(struct parg_mesh_s), 1); int* rawdata; parg_buffer* objbuf = parg_buffer_from_file(filepath); parg_load_obj(surf, objbuf); parg_buffer_free(objbuf); return surf; }
parg_mesh* parg_mesh_from_asset(parg_token id) { parg_mesh* surf = calloc(sizeof(struct parg_mesh_s), 1); int* rawdata; parg_buffer* objbuf = parg_buffer_slurp_asset(id, (void*) &rawdata); parg_load_obj(surf, objbuf); parg_buffer_free(objbuf); return surf; }
void parg_mesh_send_to_gpu(parg_mesh* mesh) { parg_buffer* coords = parg_buffer_to_gpu(mesh->coords, PARG_GPU_ARRAY); parg_buffer_free(mesh->coords); mesh->coords = coords; parg_buffer* indices = parg_buffer_to_gpu(mesh->indices, PARG_GPU_ELEMENTS); parg_buffer_free(mesh->indices); mesh->indices = indices; if (mesh->uvs) { parg_buffer* uvs = parg_buffer_to_gpu(mesh->uvs, PARG_GPU_ARRAY); parg_buffer_free(mesh->uvs); mesh->uvs = uvs; } if (mesh->normals) { parg_buffer* normals = parg_buffer_to_gpu(mesh->normals, PARG_GPU_ARRAY); parg_buffer_free(mesh->normals); mesh->normals = normals; } }
void parg_asset_preload(parg_token id) { if (!_pngsuffix) { _pngsuffix = sdsnew(".png"); } sds filename = parg_token_to_sds(id); parg_buffer* buf = parg_buffer_from_path(filename); parg_assert(buf, "Unable to load asset"); if (sdslen(filename) > 4) { sds suffix = sdsdup(filename); sdsrange(suffix, -4, -1); if (!sdscmp(suffix, _pngsuffix)) { unsigned char* decoded; unsigned dims[3] = {0, 0, 4}; unsigned char* filedata = parg_buffer_lock(buf, PARG_READ); unsigned err = lodepng_decode_memory(&decoded, &dims[0], &dims[1], filedata, parg_buffer_length(buf), LCT_RGBA, 8); parg_assert(err == 0, "PNG decoding error"); parg_buffer_free(buf); int nbytes = dims[0] * dims[1] * dims[2]; buf = parg_buffer_alloc(nbytes + 12, PARG_CPU); int* ptr = parg_buffer_lock(buf, PARG_WRITE); *ptr++ = dims[0]; *ptr++ = dims[1]; *ptr++ = dims[2]; memcpy(ptr, decoded, nbytes); free(decoded); parg_buffer_unlock(buf); } sdsfree(suffix); } if (!_asset_registry) { _asset_registry = kh_init(assmap); } int ret; int iter = kh_put(assmap, _asset_registry, id, &ret); kh_value(_asset_registry, iter) = buf; }
parg_mesh* parg_mesh_sierpinski(float width, int depth) { parg_mesh* surf = malloc(sizeof(struct parg_mesh_s)); surf->normals = 0; surf->indices = 0; surf->uvs = 0; surf->ntriangles = pow(3, depth); int vstride = sizeof(float) * 2; int ntriangles = 1; int nverts = ntriangles * 3; float height = width * sqrt(0.75); parg_buffer* src = parg_buffer_alloc(nverts * vstride, PARG_CPU); float* psrc = (float*) parg_buffer_lock(src, PARG_WRITE); *psrc++ = 0; *psrc++ = height * 0.5; *psrc++ = width * 0.5; *psrc++ = -height * 0.5; *psrc++ = -width * 0.5; *psrc++ = -height * 0.5; parg_buffer_unlock(src); #define WRITE_TRIANGLE(a, b, c) \ *pdst++ = x[a]; \ *pdst++ = y[a]; \ *pdst++ = x[b]; \ *pdst++ = y[b]; \ *pdst++ = x[c]; \ *pdst++ = y[c] float x[6]; float y[6]; while (depth--) { ntriangles *= 3; nverts = ntriangles * 3; parg_buffer* dst = parg_buffer_alloc(nverts * vstride, PARG_CPU); float* pdst = parg_buffer_lock(dst, PARG_WRITE); const float* psrc = parg_buffer_lock(src, PARG_READ); for (int i = 0; i < ntriangles / 3; i++) { x[0] = *psrc++; y[0] = *psrc++; x[1] = *psrc++; y[1] = *psrc++; x[2] = *psrc++; y[2] = *psrc++; x[3] = 0.5 * (x[0] + x[1]); y[3] = 0.5 * (y[0] + y[1]); x[4] = 0.5 * (x[1] + x[2]); y[4] = 0.5 * (y[1] + y[2]); x[5] = 0.5 * (x[0] + x[2]); y[5] = 0.5 * (y[0] + y[2]); WRITE_TRIANGLE(0, 3, 5); WRITE_TRIANGLE(3, 1, 4); WRITE_TRIANGLE(5, 4, 2); } parg_buffer_unlock(src); parg_buffer_unlock(dst); parg_buffer_free(src); src = dst; } assert(surf->ntriangles == ntriangles); surf->coords = parg_buffer_alloc(nverts * vstride, PARG_GPU_ARRAY); float* pdst = parg_buffer_lock(surf->coords, PARG_WRITE); psrc = parg_buffer_lock(src, PARG_READ); memcpy(pdst, psrc, nverts * vstride); parg_buffer_unlock(src); parg_buffer_unlock(surf->coords); parg_buffer_free(src); return surf; }