parg_mesh* parg_mesh_from_shape(struct par_shapes_mesh_s const* src) { parg_mesh* dst = calloc(sizeof(struct parg_mesh_s), 1); dst->coords = parg_buffer_alloc(4 * 3 * src->npoints, PARG_GPU_ARRAY); float* pcoords = (float*) parg_buffer_lock(dst->coords, PARG_WRITE); memcpy(pcoords, src->points, 4 * 3 * src->npoints); parg_buffer_unlock(dst->coords); if (src->tcoords) { dst->uvs = parg_buffer_alloc(4 * 2 * src->npoints, PARG_GPU_ARRAY); float* puvs = (float*) parg_buffer_lock(dst->uvs, PARG_WRITE); memcpy(puvs, src->tcoords, 4 * 2 * src->npoints); parg_buffer_unlock(dst->uvs); } if (src->normals) { dst->normals = parg_buffer_alloc(4 * 3 * src->npoints, PARG_GPU_ARRAY); float* pnorms = (float*) parg_buffer_lock(dst->normals, PARG_WRITE); memcpy(pnorms, src->normals, 4 * 3 * src->npoints); parg_buffer_unlock(dst->normals); } dst->indices = parg_buffer_alloc(2 * 3 * src->ntriangles, PARG_GPU_ELEMENTS); uint16_t* ptris = (uint16_t*) parg_buffer_lock(dst->indices, PARG_WRITE); memcpy(ptris, src->triangles, 2 * 3 * src->ntriangles); parg_buffer_unlock(dst->indices); dst->ntriangles = src->ntriangles; return dst; }
parg_mesh* parg_mesh_aar(parg_aar rect) { parg_mesh* surf = malloc(sizeof(struct parg_mesh_s)); surf->normals = 0; surf->indices = 0; surf->ntriangles = 2; int vertexCount = 4; int vertexStride = sizeof(float) * 2; surf->coords = parg_buffer_alloc(vertexCount * vertexStride, PARG_GPU_ARRAY); float* position = (float*) parg_buffer_lock(surf->coords, PARG_WRITE); *position++ = rect.left; *position++ = rect.bottom; *position++ = rect.right; *position++ = rect.bottom; *position++ = rect.left; *position++ = rect.top; *position++ = rect.right; *position = rect.top; parg_buffer_unlock(surf->coords); surf->uvs = parg_buffer_alloc(vertexCount * vertexStride, PARG_GPU_ARRAY); float* texcoord = (float*) parg_buffer_lock(surf->uvs, PARG_WRITE); *texcoord++ = 0; *texcoord++ = 0; *texcoord++ = 1; *texcoord++ = 0; *texcoord++ = 0; *texcoord++ = 1; *texcoord++ = 1; *texcoord = 1; parg_buffer_unlock(surf->uvs); return surf; }
parg_mesh* parg_mesh_knot(int slices, int stacks, float major, float minor) { parg_mesh* surf = malloc(sizeof(struct parg_mesh_s)); float ds = 1.0f / slices; float dt = 1.0f / stacks; int vertexCount = slices * stacks * 3; int vertexStride = sizeof(float) * 3; surf->coords = parg_buffer_alloc(vertexCount * vertexStride, PARG_GPU_ARRAY); surf->normals = parg_buffer_alloc(vertexCount * vertexStride, PARG_GPU_ARRAY); surf->uvs = 0; Point3* position = (Point3*) parg_buffer_lock(surf->coords, PARG_WRITE); Vector3* normal = (Vector3*) parg_buffer_lock(surf->normals, PARG_WRITE); for (float s = 0; s < 1 - ds / 2; s += ds) { for (float t = 0; t < 1 - dt / 2; t += dt) { const float E = 0.01f; Point3 p = knot_fn(s, t); Vector3 u = P3Sub(knot_fn(s + E, t), p); Vector3 v = P3Sub(knot_fn(s, t + E), p); Vector3 n = V3Normalize(V3Cross(u, v)); *position++ = p; *normal++ = n; } } parg_buffer_unlock(surf->coords); parg_buffer_unlock(surf->normals); surf->ntriangles = slices * stacks * 2; int indexCount = surf->ntriangles * 3; surf->indices = parg_buffer_alloc(indexCount * 2, PARG_GPU_ELEMENTS); uint16_t* index = (uint16_t*) parg_buffer_lock(surf->indices, PARG_WRITE); int v = 0; for (int i = 0; i < slices - 1; i++) { for (int j = 0; j < stacks; j++) { int next = (j + 1) % stacks; *index++ = v + next + stacks; *index++ = v + next; *index++ = v + j; *index++ = v + j; *index++ = v + j + stacks; *index++ = v + next + stacks; } v += stacks; } for (int j = 0; j < stacks; j++) { int next = (j + 1) % stacks; *index++ = next; *index++ = v + next; *index++ = v + j; *index++ = v + j; *index++ = j; *index++ = next; } parg_buffer_unlock(surf->indices); return surf; }
parg_buffer* parg_buffer_dup(parg_buffer* srcbuf, parg_buffer_type memtype) { int nbytes = parg_buffer_length(srcbuf); parg_buffer* dstbuf = parg_buffer_alloc(nbytes, memtype); void* src = parg_buffer_lock(srcbuf, PARG_READ); void* dst = parg_buffer_lock(dstbuf, PARG_WRITE); memcpy(dst, src, nbytes); parg_buffer_unlock(dstbuf); parg_buffer_unlock(srcbuf); return dstbuf; }
parg_buffer* parg_buffer_from_file(const char* filepath) { FILE* f = fopen(filepath, "rb"); parg_verify(f, "Unable to open file", filepath); fseek(f, 0, SEEK_END); long fsize = ftell(f); fseek(f, 0, SEEK_SET); parg_buffer* retval = parg_buffer_alloc(fsize + 1, PARG_CPU); char* contents = parg_buffer_lock(retval, PARG_WRITE); fread(contents, fsize, 1, f); fclose(f); contents[fsize] = 0; parg_buffer_unlock(retval); return retval; }
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; }
parg_mesh* parg_mesh_torus(int slices, int stacks, float major, float minor) { parg_mesh* surf = malloc(sizeof(struct parg_mesh_s)); float dphi = PARG_TWOPI / stacks; float dtheta = PARG_TWOPI / slices; int vertexCount = slices * stacks * 3; int vertexStride = sizeof(float) * 3; surf->coords = parg_buffer_alloc(vertexCount * vertexStride, PARG_GPU_ARRAY); surf->uvs = 0; Point3* position = (Point3*) parg_buffer_lock(surf->coords, PARG_WRITE); for (int slice = 0; slice < slices; slice++) { float theta = slice * dtheta; for (int stack = 0; stack < stacks; stack++) { float phi = stack * dphi; *position++ = torus_fn(major, minor, phi, theta); } } parg_buffer_unlock(surf->coords); surf->normals = parg_buffer_alloc(vertexCount * vertexStride, PARG_GPU_ARRAY); Vector3* normal = (Vector3*) parg_buffer_lock(surf->normals, PARG_WRITE); for (int slice = 0; slice < slices; slice++) { float theta = slice * dtheta; for (int stack = 0; stack < stacks; stack++) { float phi = stack * dphi; Point3 p = torus_fn(major, minor, phi, theta); Point3 p1 = torus_fn(major, minor, phi, theta + 0.01); Point3 p2 = torus_fn(major, minor, phi + 0.01, theta); Vector3 du = P3Sub(p2, p); Vector3 dv = P3Sub(p1, p); *normal = V3Normalize(V3Cross(du, dv)); ++normal; } } parg_buffer_unlock(surf->normals); surf->ntriangles = slices * stacks * 2; int indexCount = surf->ntriangles * 3; surf->indices = parg_buffer_alloc(indexCount * 2, PARG_GPU_ELEMENTS); uint16_t* index = (uint16_t*) parg_buffer_lock(surf->indices, PARG_WRITE); int v = 0; for (int i = 0; i < slices - 1; i++) { for (int j = 0; j < stacks; j++) { int next = (j + 1) % stacks; *index++ = v + next + stacks; *index++ = v + next; *index++ = v + j; *index++ = v + j; *index++ = v + j + stacks; *index++ = v + next + stacks; } v += stacks; } for (int j = 0; j < stacks; j++) { int next = (j + 1) % stacks; *index++ = next; *index++ = v + next; *index++ = v + j; *index++ = v + j; *index++ = j; *index++ = next; } parg_buffer_unlock(surf->indices); return surf; }