remove assimp dependency
This commit is contained in:
@@ -73,7 +73,6 @@ deps += dependency('qjs-layout',static:true)
|
||||
deps += dependency('qjs-nota',static:true)
|
||||
deps += dependency('qjs-miniz',static:true)
|
||||
deps += dependency('qjs-soloud',static:true)
|
||||
deps += dependency('assimp')
|
||||
deps += dependency('physfs')
|
||||
|
||||
#deps += dependency('opencv4')
|
||||
|
||||
@@ -275,7 +275,7 @@ function make_pipeline(pipeline) {
|
||||
pipeline.gpu = render._main.make_pipeline(pipeline);
|
||||
}
|
||||
|
||||
var shader_type = "msl";
|
||||
var shader_type;
|
||||
|
||||
function make_shader(sh_file) {
|
||||
var file = `shaders/${shader_type}/${sh_file}.${shader_type}`
|
||||
@@ -492,6 +492,10 @@ pipeline_model.fragment = "model.frag"
|
||||
var quad_model;
|
||||
|
||||
render.init = function () {
|
||||
shader_type = render._main.shader_format()[0];
|
||||
console.log(render._main.shader_format())
|
||||
console.log(`shader format ${shader_type}`)
|
||||
|
||||
std_sampler = render._main.make_sampler({
|
||||
min_filter: "nearest",
|
||||
mag_filter: "nearest",
|
||||
@@ -1194,7 +1198,7 @@ try{
|
||||
}
|
||||
};
|
||||
|
||||
if (dmon) dmon.watch('.');
|
||||
//if (dmon) dmon.watch('.');
|
||||
|
||||
function dmon_cb(e)
|
||||
{
|
||||
|
||||
@@ -8,26 +8,26 @@ mkdir -p reflection
|
||||
# Vertex shaders
|
||||
for filename in *.vert.hlsl; do
|
||||
if [ -f "$filename" ]; then echo "compiling ${filename}"
|
||||
dxc -spirv -T vs_6_0 -Fo "spirv/${filename/.hlsl/.spv}" "$filename"
|
||||
spirv-cross "spirv/${filename/.hlsl/.spv}" --msl > "msl/${filename/.hlsl/.msl}"
|
||||
spirv-cross "spirv/${filename/.hlsl/.spv}" --reflect > "reflection/${filename/.hlsl/.json}"
|
||||
dxc -spirv -T vs_6_0 -Fo "spv/${filename/.hlsl/.spv}" "$filename"
|
||||
spirv-cross "spv/${filename/.hlsl/.spv}" --msl > "msl/${filename/.hlsl/.msl}"
|
||||
spirv-cross "spv/${filename/.hlsl/.spv}" --reflect > "reflection/${filename/.hlsl/.json}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Fragment shaders
|
||||
for filename in *.frag.hlsl; do
|
||||
if [ -f "$filename" ]; then echo "compiling ${filename}"
|
||||
dxc -spirv -T ps_6_0 -Fo "spirv/${filename/.hlsl/.spv}" "$filename"
|
||||
spirv-cross "spirv/${filename/.hlsl/.spv}" --msl > "msl/${filename/.hlsl/.msl}"
|
||||
spirv-cross "spirv/${filename/.hlsl/.spv}" --reflect > "reflection/${filename/.hlsl/.json}"
|
||||
dxc -spirv -T ps_6_0 -Fo "spv/${filename/.hlsl/.spv}" "$filename"
|
||||
spirv-cross "spv/${filename/.hlsl/.spv}" --msl > "msl/${filename/.hlsl/.msl}"
|
||||
spirv-cross "spv/${filename/.hlsl/.spv}" --reflect > "reflection/${filename/.hlsl/.json}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Compute shaders
|
||||
for filename in *.comp.hlsl; do
|
||||
if [ -f "$filename" ]; then echo "compiling ${filename}"
|
||||
dxc -spirv -T cs_6_0 -Fo "spirv/${filename/.hlsl/.spv}" "$filename"
|
||||
spirv-cross "spirv/${filename/.hlsl/.spv}" --msl > "msl/${filename/.hlsl/.msl}"
|
||||
spirv-cross "spirv/${filename/.hlsl/.spv}" --reflect > "reflection/${filename/.hlsl/.json}"
|
||||
dxc -spirv -T cs_6_0 -Fo "spv/${filename/.hlsl/.spv}" "$filename"
|
||||
spirv-cross "spv/${filename/.hlsl/.spv}" --msl > "msl/${filename/.hlsl/.msl}"
|
||||
spirv-cross "spv/${filename/.hlsl/.spv}" --reflect > "reflection/${filename/.hlsl/.json}"
|
||||
fi
|
||||
done
|
||||
|
||||
407
source/jsffi.c
407
source/jsffi.c
@@ -30,10 +30,6 @@
|
||||
#include "cgltf.h"
|
||||
#include "physfs.h"
|
||||
|
||||
#include <assimp/cimport.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/postprocess.h>
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_gpu.h>
|
||||
#include <SDL3/SDL_error.h>
|
||||
@@ -2010,7 +2006,7 @@ JSC_SCALL(SDL_Window_make_renderer,
|
||||
|
||||
JSC_SCALL(SDL_Window_make_gpu,
|
||||
SDL_Window *win = js2SDL_Window(js,self);
|
||||
SDL_GPUDevice *gpu = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_MSL, 1, NULL);
|
||||
SDL_GPUDevice *gpu = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_MSL, 1, NULL);
|
||||
global_gpu = gpu;
|
||||
|
||||
return SDL_GPUDevice2js(js,gpu);
|
||||
@@ -2472,12 +2468,6 @@ JSC_CCALL(renderer_target,
|
||||
}
|
||||
)
|
||||
|
||||
#include "cgltf.h"
|
||||
#include <math.h>
|
||||
|
||||
#include "cgltf.h"
|
||||
#include <math.h>
|
||||
|
||||
static void generate_normals(float* positions, size_t vertex_count, uint16_t* indices, size_t index_count, int16_t* normal_data) {
|
||||
// Initialize normals to zero
|
||||
float* temp_normals = malloc(sizeof(float)*3*vertex_count);
|
||||
@@ -4427,11 +4417,11 @@ JSC_CCALL(gpu_shader_format,
|
||||
JSValue arr = JS_NewArray(js);
|
||||
int i = 0;
|
||||
if (fmt & SDL_GPU_SHADERFORMAT_PRIVATE) JS_SetPropertyUint32(js, arr, i++, JS_NewString(js, ".private"));
|
||||
if (fmt & SDL_GPU_SHADERFORMAT_SPIRV) JS_SetPropertyUint32(js, arr, i++, JS_NewString(js, ".spv"));
|
||||
if (fmt & SDL_GPU_SHADERFORMAT_DXBC) JS_SetPropertyUint32(js, arr, i++, JS_NewString(js, ".dxbc"));
|
||||
if (fmt & SDL_GPU_SHADERFORMAT_DXIL) JS_SetPropertyUint32(js, arr, i++, JS_NewString(js, ".dxil"));
|
||||
if (fmt & SDL_GPU_SHADERFORMAT_MSL) JS_SetPropertyUint32(js, arr, i++, JS_NewString(js, ".msl"));
|
||||
if (fmt & SDL_GPU_SHADERFORMAT_METALLIB) JS_SetPropertyUint32(js, arr, i++, JS_NewString(js, ".metallib"));
|
||||
if (fmt & SDL_GPU_SHADERFORMAT_SPIRV) JS_SetPropertyUint32(js, arr, i++, JS_NewString(js, "spv"));
|
||||
if (fmt & SDL_GPU_SHADERFORMAT_DXBC) JS_SetPropertyUint32(js, arr, i++, JS_NewString(js, "dxbc"));
|
||||
if (fmt & SDL_GPU_SHADERFORMAT_DXIL) JS_SetPropertyUint32(js, arr, i++, JS_NewString(js, "dxil"));
|
||||
if (fmt & SDL_GPU_SHADERFORMAT_MSL) JS_SetPropertyUint32(js, arr, i++, JS_NewString(js, "msl"));
|
||||
if (fmt & SDL_GPU_SHADERFORMAT_METALLIB) JS_SetPropertyUint32(js, arr, i++, JS_NewString(js, "metallib"));
|
||||
return arr;
|
||||
)
|
||||
|
||||
@@ -5940,183 +5930,242 @@ JSC_SCALL(os_system, return number2js(js,system(str)); )
|
||||
|
||||
JSC_SCALL(os_model_buffer,
|
||||
int mesh_idx = 0;
|
||||
const struct aiScene *scene = aiImportFile(
|
||||
str,
|
||||
aiProcess_Triangulate |
|
||||
aiProcess_GenNormals |
|
||||
aiProcess_GenUVCoords |
|
||||
aiProcess_FlipUVs |
|
||||
aiProcess_OptimizeMeshes |
|
||||
aiProcess_JoinIdenticalVertices
|
||||
);
|
||||
|
||||
if (!scene) {
|
||||
JS_ThrowInternalError(js, "Failed to load model: %s", aiGetErrorString());
|
||||
// Configure cgltf
|
||||
cgltf_options options;
|
||||
memset(&options, 0, sizeof(options));
|
||||
|
||||
// Parse the file
|
||||
cgltf_data* data = NULL;
|
||||
cgltf_result result = cgltf_parse_file(&options, str, &data);
|
||||
if (result != cgltf_result_success) {
|
||||
JS_ThrowInternalError(js, "Failed to load glTF model: parse error");
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
if (mesh_idx < 0 || mesh_idx >= (int)scene->mNumMeshes) {
|
||||
// Load any external buffers (bin files, images)
|
||||
result = cgltf_load_buffers(&options, data, str);
|
||||
if (result != cgltf_result_success) {
|
||||
cgltf_free(data);
|
||||
JS_ThrowInternalError(js, "Failed to load glTF model: buffer load error");
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
// We only check for mesh_idx vs. the count of cgltf_data->meshes
|
||||
// (though note that glTF organizes data in scenes, nodes, etc.,
|
||||
// so you might want to handle multiple nodes or node->mesh references)
|
||||
if (mesh_idx < 0 || mesh_idx >= (int)data->meshes_count) {
|
||||
cgltf_free(data);
|
||||
JS_ThrowInternalError(js, "Invalid mesh index");
|
||||
aiReleaseImport(scene);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
JSValue materials[scene->mNumMaterials];
|
||||
for (int i = 0; i < scene->mNumMaterials; i++) {
|
||||
/*
|
||||
Build an array of JS material objects, similar to your old code with Assimp.
|
||||
For each cgltf_material in data->materials, we store something in materials[i].
|
||||
This example only sets the "diffuse" property from the PBR base color texture.
|
||||
More properties (metallic, roughness, etc.) can be added similarly.
|
||||
*/
|
||||
JSValue materials[data->materials_count];
|
||||
for (int i = 0; i < (int)data->materials_count; i++) {
|
||||
JSValue mat = JS_NewObject(js);
|
||||
materials[i] = mat;
|
||||
struct aiMaterial *aimat = scene->mMaterials[i];
|
||||
struct aiString texPath;
|
||||
if (aiGetMaterialTexture(aimat, aiTextureType_DIFFUSE, 0, &texPath,NULL,NULL,NULL,NULL,NULL,NULL) == AI_SUCCESS) {
|
||||
if (texPath.data[0] != '*') {
|
||||
JS_SetPropertyStr(js,mat,"diffuse", JS_NewString(js,texPath.data));
|
||||
} else {
|
||||
struct aiTexture *tex = scene->mTextures[atoi(texPath.data+1)];
|
||||
if (tex->mHeight == 0) {
|
||||
void *data = tex->pcData;
|
||||
size_t size = tex->mWidth;
|
||||
JS_SetPropertyStr(js,mat,"diffuse", JS_NewArrayBufferCopy(js,data,size));
|
||||
} else {
|
||||
size_t size = tex->mWidth*tex->mHeight*4;
|
||||
void *data = tex->pcData;
|
||||
JS_SetPropertyStr(js,mat,"diffuse", JS_NewArrayBufferCopy(js,data,size));
|
||||
}
|
||||
cgltf_material *cgmat = &data->materials[i];
|
||||
|
||||
// Grab the base color texture if it exists
|
||||
cgltf_texture_view *bc_view = &cgmat->pbr_metallic_roughness.base_color_texture;
|
||||
if (bc_view->texture && bc_view->texture->image) {
|
||||
cgltf_image *img = bc_view->texture->image;
|
||||
// If the image is an external URI
|
||||
if (img->uri) {
|
||||
// For glTF 2.0, this often points to a .png/.jpg
|
||||
JS_SetPropertyStr(js, mat, "diffuse", JS_NewString(js, img->uri));
|
||||
}
|
||||
// If it's an embedded buffer view (e.g., "data:" or bufferView-based image)
|
||||
else if (img->buffer_view) {
|
||||
size_t size = img->buffer_view->size;
|
||||
uint8_t *ptr = (uint8_t*)img->buffer_view->buffer->data + img->buffer_view->offset;
|
||||
JS_SetPropertyStr(js, mat, "diffuse", JS_NewArrayBufferCopy(js, ptr, size));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create an array to hold all the models
|
||||
JSValue ret_arr = JS_NewArray(js);
|
||||
|
||||
// Loop over all meshes
|
||||
for (unsigned int m = 0; m < scene->mNumMeshes; m++) {
|
||||
struct aiMesh *mesh = scene->mMeshes[m];
|
||||
if (!mesh->mVertices) {
|
||||
JS_ThrowInternalError(js, "Mesh %u has no vertices", m);
|
||||
aiReleaseImport(scene);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
size_t num_verts = mesh->mNumVertices;
|
||||
float *posdata = NULL;
|
||||
float *normdata = NULL;
|
||||
float *uvdata = NULL;
|
||||
float *colordata = NULL;
|
||||
Uint16 *indicesdata = NULL;
|
||||
|
||||
// Positions (float3)
|
||||
posdata = malloc(sizeof(float)*3*num_verts);
|
||||
for (size_t i = 0; i < num_verts; i++) {
|
||||
posdata[i*3+0] = mesh->mVertices[i].x;
|
||||
posdata[i*3+1] = mesh->mVertices[i].y;
|
||||
posdata[i*3+2] = mesh->mVertices[i].z;
|
||||
}
|
||||
|
||||
// Normals (float3)
|
||||
if (mesh->mNormals) {
|
||||
normdata = malloc(sizeof(float)*3*num_verts);
|
||||
for (size_t i = 0; i < num_verts; i++) {
|
||||
normdata[i*3+0] = mesh->mNormals[i].x;
|
||||
normdata[i*3+1] = mesh->mNormals[i].y;
|
||||
normdata[i*3+2] = mesh->mNormals[i].z;
|
||||
}
|
||||
} else {
|
||||
normdata = malloc(sizeof(float)*3*num_verts);
|
||||
for (size_t i = 0; i < num_verts; i++) {
|
||||
normdata[i*3+0] = 0.0f;
|
||||
normdata[i*3+1] = 0.0f;
|
||||
normdata[i*3+2] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// UVs (float2)
|
||||
if (mesh->mTextureCoords[0]) {
|
||||
uvdata = malloc(sizeof(float)*2*num_verts);
|
||||
for (size_t i = 0; i < num_verts; i++) {
|
||||
uvdata[i*2+0] = mesh->mTextureCoords[0][i].x;
|
||||
uvdata[i*2+1] = mesh->mTextureCoords[0][i].y;
|
||||
}
|
||||
} else {
|
||||
uvdata = malloc(sizeof(float)*2*num_verts);
|
||||
for (size_t i = 0; i < num_verts; i++) {
|
||||
uvdata[i*2+0] = 0.0f;
|
||||
uvdata[i*2+1] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Colors (float4)
|
||||
if (mesh->mColors[0]) {
|
||||
colordata = malloc(sizeof(float)*4*num_verts);
|
||||
for (size_t i = 0; i < num_verts; i++) {
|
||||
colordata[i*4+0] = mesh->mColors[0][i].r;
|
||||
colordata[i*4+1] = mesh->mColors[0][i].g;
|
||||
colordata[i*4+2] = mesh->mColors[0][i].b;
|
||||
colordata[i*4+3] = mesh->mColors[0][i].a;
|
||||
}
|
||||
} else {
|
||||
colordata = malloc(sizeof(float)*4*num_verts);
|
||||
for (size_t i = 0; i < num_verts; i++) {
|
||||
colordata[i*4+0] = 1.0f;
|
||||
colordata[i*4+1] = 1.0f;
|
||||
colordata[i*4+2] = 1.0f;
|
||||
colordata[i*4+3] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Indices
|
||||
size_t num_faces = mesh->mNumFaces;
|
||||
size_t index_count = num_faces * 3;
|
||||
indicesdata = malloc(sizeof(Uint16)*index_count);
|
||||
for (size_t i = 0; i < num_faces; i++) {
|
||||
const struct aiFace *face = &mesh->mFaces[i];
|
||||
indicesdata[i*3+0] = face->mIndices[0];
|
||||
indicesdata[i*3+1] = face->mIndices[1];
|
||||
indicesdata[i*3+2] = face->mIndices[2];
|
||||
}
|
||||
|
||||
// Build a JS object for the mesh data
|
||||
JSValue js_mesh = JS_NewObject(js);
|
||||
|
||||
// Positions
|
||||
JS_SetProperty(js, js_mesh, pos_atom,
|
||||
make_gpu_buffer(js, posdata, sizeof(float)*3*num_verts, JS_TYPED_ARRAY_FLOAT32, 3, 1, 0));
|
||||
|
||||
// UV
|
||||
JS_SetProperty(js, js_mesh, uv_atom,
|
||||
make_gpu_buffer(js, uvdata, sizeof(float)*2*num_verts, JS_TYPED_ARRAY_FLOAT32, 2, 1, 0));
|
||||
|
||||
// Color
|
||||
JS_SetProperty(js, js_mesh, color_atom,
|
||||
make_gpu_buffer(js, colordata, sizeof(float)*4*num_verts, JS_TYPED_ARRAY_FLOAT32, 4, 1, 0));
|
||||
|
||||
// Normal
|
||||
JS_SetProperty(js, js_mesh, norm_atom,
|
||||
make_gpu_buffer(js, normdata, sizeof(float)*3*num_verts, JS_TYPED_ARRAY_FLOAT32, 3, 1, 0));
|
||||
|
||||
// Indices
|
||||
JS_SetProperty(js, js_mesh, indices_atom,
|
||||
make_gpu_buffer(js, indicesdata, sizeof(Uint16)*index_count, JS_TYPED_ARRAY_UINT16, 0, 1, 1));
|
||||
|
||||
// Metadata
|
||||
JS_SetProperty(js, js_mesh, vertices_atom, number2js(js, (double)num_verts));
|
||||
JS_SetProperty(js, js_mesh, count_atom, number2js(js, (double)index_count));
|
||||
|
||||
// Build final "model" object with mesh + material
|
||||
JSValue model_obj = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js, model_obj, "mesh", js_mesh);
|
||||
JS_SetPropertyStr(js, model_obj, "material", JS_DupValue(js,materials[mesh->mMaterialIndex]));
|
||||
|
||||
// Place into our return array
|
||||
JS_SetPropertyUint32(js, ret_arr, m, model_obj);
|
||||
|
||||
// Cleanup (per-mesh)
|
||||
free(posdata);
|
||||
free(normdata);
|
||||
free(uvdata);
|
||||
free(colordata);
|
||||
free(indicesdata);
|
||||
}
|
||||
|
||||
aiReleaseImport(scene);
|
||||
// Create an array to hold all the "model" objects
|
||||
JSValue ret_arr = JS_NewArray(js);
|
||||
|
||||
/*
|
||||
Loop over all cgltf_meshes. Each mesh can contain multiple "primitives."
|
||||
Each primitive can have different attributes (POSITION, NORMAL, etc.)
|
||||
and references exactly one material.
|
||||
*/
|
||||
for (int m = 0; m < (int)data->meshes_count; m++) {
|
||||
cgltf_mesh *cgmesh = &data->meshes[m];
|
||||
// Go through each primitive in this mesh
|
||||
for (int p = 0; p < (int)cgmesh->primitives_count; p++) {
|
||||
cgltf_primitive *prim = &cgmesh->primitives[p];
|
||||
if (!prim->attributes) {
|
||||
// No attributes => no geometry
|
||||
continue;
|
||||
}
|
||||
|
||||
// We'll collect attribute data in arrays, just like with Assimp
|
||||
float *posdata = NULL, *normdata = NULL, *uvdata = NULL, *colordata = NULL;
|
||||
Uint16 *indicesdata = NULL;
|
||||
size_t num_verts = 0;
|
||||
size_t index_count = 0;
|
||||
|
||||
// Helper function to find an accessor by "POSITION", "NORMAL", "TEXCOORD_0", etc.
|
||||
// We'll parse it below in parseAttributeFloat.
|
||||
cgltf_accessor* findAccessor(cgltf_primitive* prim, const char* semantic) {
|
||||
for (int a = 0; a < (int)prim->attributes_count; a++) {
|
||||
if (prim->attributes[a].name && strcmp(prim->attributes[a].name, semantic) == 0)
|
||||
return prim->attributes[a].data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// parseAttributeFloat:
|
||||
// read floats from a cgltf_accessor into outBuffer
|
||||
// The 'stride' is how many floats we read per element (e.g. 3 for POSITION)
|
||||
// Returns the number of elements read
|
||||
size_t parseAttributeFloat(JSContext* js, cgltf_accessor* acc, float** outBuffer, int stride, float defaultVal) {
|
||||
if (!acc) {
|
||||
// If the attribute doesn't exist, fill default
|
||||
size_t count = 0;
|
||||
*outBuffer = NULL;
|
||||
return count;
|
||||
}
|
||||
size_t count = acc->count;
|
||||
size_t total_floats = count * stride;
|
||||
*outBuffer = malloc(total_floats * sizeof(float));
|
||||
if (!(*outBuffer)) return 0;
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
float tmp[4] = { defaultVal, defaultVal, defaultVal, defaultVal };
|
||||
cgltf_accessor_read_float(acc, i, tmp, 4);
|
||||
// copy only 'stride' components
|
||||
for (int c = 0; c < stride; c++)
|
||||
(*outBuffer)[i*stride + c] = tmp[c];
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// 1) POSITION
|
||||
cgltf_accessor *accPos = findAccessor(prim, "POSITION");
|
||||
num_verts = parseAttributeFloat(js, accPos, &posdata, 3, 0.0f);
|
||||
|
||||
// 2) NORMAL
|
||||
cgltf_accessor *accNorm = findAccessor(prim, "NORMAL");
|
||||
// If missing normals, default them to (0,0,1)
|
||||
parseAttributeFloat(js, accNorm, &normdata, 3, 0.0f);
|
||||
if (!normdata && num_verts > 0) {
|
||||
normdata = malloc(num_verts*3*sizeof(float));
|
||||
for (size_t i = 0; i < num_verts; i++) {
|
||||
normdata[i*3+0] = 0.0f;
|
||||
normdata[i*3+1] = 0.0f;
|
||||
normdata[i*3+2] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// 3) TEXCOORD_0
|
||||
cgltf_accessor *accUV = findAccessor(prim, "TEXCOORD_0");
|
||||
parseAttributeFloat(js, accUV, &uvdata, 2, 0.0f);
|
||||
if (!uvdata && num_verts > 0) {
|
||||
uvdata = malloc(num_verts*2*sizeof(float));
|
||||
for (size_t i = 0; i < num_verts; i++) {
|
||||
uvdata[i*2+0] = 0.0f;
|
||||
uvdata[i*2+1] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// 4) COLOR_0
|
||||
cgltf_accessor *accColor = findAccessor(prim, "COLOR_0");
|
||||
parseAttributeFloat(js, accColor, &colordata, 4, 1.0f);
|
||||
if (!colordata && num_verts > 0) {
|
||||
colordata = malloc(num_verts*4*sizeof(float));
|
||||
for (size_t i = 0; i < num_verts; i++) {
|
||||
colordata[i*4+0] = 1.0f;
|
||||
colordata[i*4+1] = 1.0f;
|
||||
colordata[i*4+2] = 1.0f;
|
||||
colordata[i*4+3] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// 5) Indices (if present)
|
||||
if (prim->indices) {
|
||||
cgltf_accessor *idxAcc = prim->indices;
|
||||
index_count = idxAcc->count;
|
||||
indicesdata = malloc(index_count*sizeof(Uint16));
|
||||
if (indicesdata) {
|
||||
for (size_t i = 0; i < index_count; i++) {
|
||||
// cgltf_accessor_read_index can read the index as uint32_t
|
||||
uint32_t val = 0;
|
||||
val = cgltf_accessor_read_index(idxAcc, i);
|
||||
// NOTE: if val > 65535, you'll need 32-bit index buffers
|
||||
indicesdata[i] = (Uint16)val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build a JS object for the mesh data
|
||||
JSValue js_mesh = JS_NewObject(js);
|
||||
|
||||
// Positions
|
||||
if (posdata && num_verts > 0)
|
||||
JS_SetProperty(js, js_mesh, pos_atom,
|
||||
make_gpu_buffer(js, posdata, sizeof(float)*3*num_verts, JS_TYPED_ARRAY_FLOAT32, 3, 1, 0));
|
||||
|
||||
// UV
|
||||
if (uvdata && num_verts > 0)
|
||||
JS_SetProperty(js, js_mesh, uv_atom,
|
||||
make_gpu_buffer(js, uvdata, sizeof(float)*2*num_verts, JS_TYPED_ARRAY_FLOAT32, 2, 1, 0));
|
||||
|
||||
// Color
|
||||
if (colordata && num_verts > 0)
|
||||
JS_SetProperty(js, js_mesh, color_atom,
|
||||
make_gpu_buffer(js, colordata, sizeof(float)*4*num_verts, JS_TYPED_ARRAY_FLOAT32, 4, 1, 0));
|
||||
|
||||
// Normal
|
||||
if (normdata && num_verts > 0)
|
||||
JS_SetProperty(js, js_mesh, norm_atom,
|
||||
make_gpu_buffer(js, normdata, sizeof(float)*3*num_verts, JS_TYPED_ARRAY_FLOAT32, 3, 1, 0));
|
||||
|
||||
// Indices
|
||||
if (indicesdata && index_count > 0)
|
||||
JS_SetProperty(js, js_mesh, indices_atom,
|
||||
make_gpu_buffer(js, indicesdata, sizeof(Uint16)*index_count, JS_TYPED_ARRAY_UINT16, 0, 1, 1));
|
||||
|
||||
// Metadata
|
||||
JS_SetProperty(js, js_mesh, vertices_atom, number2js(js, (double)num_verts));
|
||||
JS_SetProperty(js, js_mesh, count_atom, number2js(js, (double)index_count));
|
||||
|
||||
// Build final "model" object with mesh + material
|
||||
JSValue model_obj = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js, model_obj, "mesh", js_mesh);
|
||||
|
||||
// Figure out the index of the material in data->materials. If prim->material is non-null,
|
||||
// its index is `prim->material - data->materials`.
|
||||
int mat_index = -1;
|
||||
if (prim->material) mat_index = (int)(prim->material - data->materials);
|
||||
if (mat_index >= 0 && mat_index < (int)data->materials_count)
|
||||
JS_SetPropertyStr(js, model_obj, "material", JS_DupValue(js, materials[mat_index]));
|
||||
else
|
||||
JS_SetPropertyStr(js, model_obj, "material", JS_NewObject(js));
|
||||
|
||||
// Place this "model" object into our return array
|
||||
uint32_t idx_in_array = js_arrlen(js,ret_arr);
|
||||
JS_SetPropertyUint32(js, ret_arr, idx_in_array, model_obj);
|
||||
|
||||
// Cleanup (per-primitive)
|
||||
if (posdata) free(posdata);
|
||||
if (normdata) free(normdata);
|
||||
if (uvdata) free(uvdata);
|
||||
if (colordata) free(colordata);
|
||||
if (indicesdata) free(indicesdata);
|
||||
}
|
||||
}
|
||||
|
||||
cgltf_free(data);
|
||||
|
||||
ret = ret_arr;
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user