luboslenco 1 tháng trước cách đây
mục cha
commit
fcd65a71cc

BIN
base/assets/Scene.arm


+ 1 - 1
base/sources/iron_obj.h

@@ -22,7 +22,7 @@ typedef struct raw_mesh {
 	int udims_u; // Number of horizontal udim tiles
 	int udims_v;
 	void *vertex_arrays; // vertex_array_t[]
-	void *index_arrays; // index_array_t[]
+	struct u32_array *index_array;
 } raw_mesh_t;
 
 raw_mesh_t *obj_parse(buffer_t *file_bytes, char split_code, uint64_t start_pos, bool udim);

+ 1 - 4
base/sources/ts/box_export.ts

@@ -400,10 +400,7 @@ function box_export_tab_export_mesh(ui: ui_t, htab: ui_handle_t) {
 		}
 		for (let i: i32 = 0; i < paint_objects.length; ++i) {
 			let po: mesh_object_t = paint_objects[i];
-			for (let i: i32 = 0; i < po.data.index_arrays.length; ++i) {
-				let inda: index_array_t = po.data.index_arrays[i];
-				tris += math_floor(inda.values.length / 3);
-			}
+			tris += math_floor(po.data.index_array.length / 3);
 		}
 		ui_text(tris + " " + tr("triangles"));
 

+ 2 - 2
base/sources/ts/export_obj.ts

@@ -136,7 +136,7 @@ function export_obj_run(path: string, paint_objects: mesh_object_t[], apply_disp
 			export_obj_write_string(o, "\n");
 		}
 
-		let inda: u32_array_t = mesh.index_arrays[0].values;
+		let inda: u32_array_t = mesh.index_array;
 		for (let i: i32 = 0; i < math_floor(inda.length / 3); ++i) {
 			let pi1: i32 = posmap[inda[i * 3    ]] + 1 + poff;
 			let pi2: i32 = posmap[inda[i * 3 + 1]] + 1 + poff;
@@ -235,7 +235,7 @@ function export_obj_run_fast(path: string, paint_objects: mesh_object_t[]) {
 			export_obj_write_string(o, "\n");
 		}
 
-		let inda: u32_array_t = mesh.index_arrays[0].values;
+		let inda: u32_array_t = mesh.index_array;
 		for (let i: i32 = 0; i < math_floor(inda.length / 3); ++i) {
 			let pi1: i32 = inda[i * 3    ] + 1 + poff;
 			let pi2: i32 = inda[i * 3 + 1] + 1 + poff;

+ 1 - 1
base/sources/ts/geom.ts

@@ -146,5 +146,5 @@ declare type raw_mesh_t = {
 	udims_u?: i32;
 	udims_v?: i32;
 	vertex_arrays?: vertex_array_t[];
-	index_arrays?: index_array_t[];
+	index_array?: u32_array_t;
 };

+ 1 - 6
base/sources/ts/import_mesh.ts

@@ -285,12 +285,7 @@ function import_mesh_raw_mesh(mesh: raw_mesh_t): mesh_data_t {
 				data: "short2norm"
 			}
 		],
-		index_arrays: [
-			{
-				values: mesh.inda,
-				material: 0
-			}
-		],
+		index_array: mesh.inda,
 		scale_pos: mesh.scale_pos,
 		scale_tex: mesh.scale_tex
 	};

+ 1 - 5
base/sources/ts/iron/material_data.ts

@@ -59,8 +59,7 @@ function material_data_get_raw_by_name(datas: material_data_t[], name: string):
 function material_data_get_context(raw: material_data_t, name: string): material_context_t {
 	for (let i: i32 = 0; i < raw._.contexts.length; ++i) {
 		let c: material_context_t = raw._.contexts[i];
-		// "mesh" will fetch both "mesh" and "meshheight" contexts
-		if (substring(c.name, 0, name.length) == name) {
+		if (c.name == name) {
 			return c;
 		}
 	}
@@ -71,14 +70,11 @@ function material_context_create(raw: material_context_t): material_context_t {
 	raw._ = {};
 	if (raw.bind_textures != null && raw.bind_textures.length > 0) {
 		raw._.textures = [];
-
 		for (let i: i32 = 0; i < raw.bind_textures.length; ++i) {
 			let tex: bind_tex_t = raw.bind_textures[i];
-
 			if (tex.file == "") { // Empty texture
 				continue;
 			}
-
 			let image: gpu_texture_t = data_get_image(tex.file);
 			array_push(raw._.textures, image);
 		}

+ 20 - 116
base/sources/ts/iron/mesh_data.ts

@@ -25,19 +25,13 @@ function mesh_data_get_raw_by_name(datas: mesh_data_t[], name: string): mesh_dat
 
 function mesh_data_create(raw: mesh_data_t): mesh_data_t {
 	raw._ = {};
-
-	if (!raw.scale_pos) {
+	if (raw.scale_pos == 0.0) {
 		raw.scale_pos = 1.0;
 	}
-	if (!raw.scale_tex) {
+	if (raw.scale_tex == 0.0) {
 		raw.scale_tex = 1.0;
 	}
-
-	raw._.refcount = 0;
-	raw._.vertex_buffer_map = map_create();
-	raw._.ready = false;
 	raw._.structure = mesh_data_get_vertex_struct(raw.vertex_arrays);
-
 	return raw;
 }
 
@@ -53,27 +47,23 @@ function mesh_data_get_vertex_data(data: string): vertex_data_t {
 	if (data == "short4norm") {
 		return vertex_data_t.I16_4X_NORM;
 	}
-	else if (data == "short2norm") {
-		return vertex_data_t.I16_2X_NORM;
-	}
-	else {
-		return vertex_data_t.I16_4X_NORM;
+	return vertex_data_t.I16_2X_NORM; // short2norm
+}
+
+function mesh_data_get_vertex_size(vertex_data: string): i32 {
+	if (vertex_data == "short4norm") {
+		return 4;
 	}
+	return 2; // short2norm
 }
 
-function mesh_data_build_vertices(vertices: buffer_t, vertex_arrays: vertex_array_t[], offset: i32 = 0, fake_uvs: bool = false, uvs_index: i32 = -1) {
+function mesh_data_build_vertices(vertices: buffer_t, vertex_arrays: vertex_array_t[]) {
 	let size: i32 = mesh_data_get_vertex_size(vertex_arrays[0].data);
 	let num_verts: i32 = vertex_arrays[0].values.length / size;
-	let di: i32 = -1 + offset;
+	let di: i32 = -1;
 	for (let i: i32 = 0; i < num_verts; ++i) {
 		for (let va: i32 = 0; va < vertex_arrays.length; ++va) {
 			let l: i32 = mesh_data_get_vertex_size(vertex_arrays[va].data);
-			if (fake_uvs && va == uvs_index) { // Add fake uvs if uvs where "asked" for but not found
-				for (let j: i32 = 0; j < l; ++j) {
-					buffer_set_i16(vertices, ++di * 2, 0);
-				}
-				continue;
-			}
 			for (let o: i32 = 0; o < l; ++o) {
 				buffer_set_i16(vertices, ++di * 2, vertex_arrays[va].values[i * l + o]);
 			}
@@ -81,18 +71,6 @@ function mesh_data_build_vertices(vertices: buffer_t, vertex_arrays: vertex_arra
 	}
 }
 
-function mesh_data_get_vertex_size(vertex_data: string): i32 {
-	if (vertex_data == "short4norm") {
-		return 4;
-	}
-	else if (vertex_data == "short2norm") {
-		return 2;
-	}
-	else {
-		return 0;
-	}
-}
-
 function mesh_data_get_vertex_array(raw: mesh_data_t, name: string): vertex_array_t {
 	for (let i: i32 = 0; i < raw.vertex_arrays.length; ++i) {
 		if (raw.vertex_arrays[i].attrib == name) {
@@ -102,59 +80,7 @@ function mesh_data_get_vertex_array(raw: mesh_data_t, name: string): vertex_arra
 	return null;
 }
 
-function mesh_data_get(raw: mesh_data_t, vs: vertex_element_t[]): gpu_buffer_t {
-	let key: string = "";
-	for (let i: i32 = 0; i < vs.length; ++i) {
-		let e: vertex_element_t = vs[i];
-		key += e.name;
-	}
-	let vb: gpu_buffer_t = map_get(raw._.vertex_buffer_map, key);
-	if (vb == null) {
-		let vertex_arrays: vertex_array_t[] = [];
-		let has_tex: bool = false;
-		let tex_offset: i32 = -1;
-		let has_col: bool = false;
-		for (let e: i32 = 0; e < vs.length; ++e) {
-			if (vs[e].name == "tex") {
-				has_tex = true;
-				tex_offset = e;
-			}
-			else if (vs[e].name == "col") {
-				has_col = true;
-			}
-			for (let va: i32 = 0; va < raw.vertex_arrays.length; ++va) {
-				let name: string = vs[e].name;
-				if (name == raw.vertex_arrays[va].attrib) {
-					array_push(vertex_arrays, raw.vertex_arrays[va]);
-				}
-			}
-		}
-		// Multi-mat mesh with different vertex structures
-		let positions: vertex_array_t = mesh_data_get_vertex_array(raw, "pos");
-		let uvs: vertex_array_t = mesh_data_get_vertex_array(raw, "tex");
-		let cols: vertex_array_t = mesh_data_get_vertex_array(raw, "col");
-		let vstruct: gpu_vertex_structure_t = mesh_data_get_vertex_struct(vertex_arrays);
-		let size: i32 = mesh_data_get_vertex_size(positions.data);
-		vb = gpu_create_vertex_buffer(math_floor(positions.values.length / size), vstruct);
-		let vertices: buffer_t = gpu_lock_vertex_buffer(vb);
-		mesh_data_build_vertices(vertices, vertex_arrays, 0, has_tex && uvs == null, tex_offset);
-		gpu_vertex_buffer_unlock(vb);
-		map_set(raw._.vertex_buffer_map, key, vb);
-		if (has_tex && uvs == null) {
-			iron_log("Geometry " + raw.name + " is missing UV map");
-		}
-		if (has_col && cols == null) {
-			iron_log("Geometry " + raw.name + " is missing vertex colors");
-		}
-	}
-	return vb;
-}
-
 function mesh_data_build(raw: mesh_data_t) {
-	if (raw._.ready) {
-		return;
-	}
-
 	let positions: vertex_array_t = mesh_data_get_vertex_array(raw, "pos");
 	let size: i32 = mesh_data_get_vertex_size(positions.data);
 	raw._.vertex_buffer = gpu_create_vertex_buffer(math_floor(positions.values.length / size), raw._.structure);
@@ -162,27 +88,14 @@ function mesh_data_build(raw: mesh_data_t) {
 	mesh_data_build_vertices(vertices, raw.vertex_arrays);
 	gpu_vertex_buffer_unlock(raw._.vertex_buffer);
 
-	let struct_str: string = "";
-	for (let i: i32 = 0; i < raw._.structure.size; ++i) {
-		let e: gpu_vertex_element_t = ADDRESS(ARRAY_ACCESS(raw._.structure.elements, i));
-		struct_str += e.name;
-	}
-	map_set(raw._.vertex_buffer_map, struct_str, raw._.vertex_buffer);
-
-	raw._.index_buffers = [];
-
-	for (let i: i32 = 0; i < raw.index_arrays.length; ++i) {
-		let id: u32_array_t = raw.index_arrays[i].values;
-		let index_buffer: gpu_buffer_t = gpu_create_index_buffer(id.length);
-		let indices_array: u32_array_t = gpu_lock_index_buffer(index_buffer);
-		for (let i: i32 = 0; i < indices_array.length; ++i) {
-			indices_array[i] = id[i];
-		}
-		gpu_index_buffer_unlock(index_buffer);
-		array_push(raw._.index_buffers, index_buffer);
+	let id: u32_array_t = raw.index_array;
+	let index_buffer: gpu_buffer_t = gpu_create_index_buffer(id.length);
+	let indices_array: u32_array_t = gpu_lock_index_buffer(index_buffer);
+	for (let i: i32 = 0; i < indices_array.length; ++i) {
+		indices_array[i] = id[i];
 	}
-
-	raw._.ready = true;
+	gpu_index_buffer_unlock(index_buffer);
+	raw._.index_buffer = index_buffer;
 }
 
 function mesh_data_calculate_aabb(raw: mesh_data_t): vec4_t {
@@ -219,15 +132,6 @@ function mesh_data_calculate_aabb(raw: mesh_data_t): vec4_t {
 }
 
 function mesh_data_delete(raw: mesh_data_t) {
-	let vertex_buffer_keys: string[] = map_keys(raw._.vertex_buffer_map);
-	for (let i: i32 = 0; i < vertex_buffer_keys.length; ++i) {
-		let buf: gpu_buffer_t = map_get(raw._.vertex_buffer_map, vertex_buffer_keys[i]);
-		if (buf != null) {
-			gpu_delete_buffer(buf);
-		}
-	}
-	for (let i: i32 = 0; i < raw._.index_buffers.length; ++i) {
-		let buf: gpu_buffer_t = raw._.index_buffers[i];
-		gpu_delete_buffer(buf);
-	}
+	gpu_delete_buffer(raw._.vertex_buffer);
+	gpu_delete_buffer(raw._.index_buffer);
 }

+ 2 - 9
base/sources/ts/iron/mesh_object.ts

@@ -30,7 +30,6 @@ function mesh_object_create(data: mesh_data_t, materials: material_data_t[]): me
 
 function mesh_object_set_data(raw: mesh_object_t, data: mesh_data_t) {
 	raw.data = data;
-	data._.refcount++;
 	mesh_data_build(data);
 
 	// Scale-up packed (-1,1) mesh coords
@@ -39,8 +38,6 @@ function mesh_object_set_data(raw: mesh_object_t, data: mesh_data_t) {
 
 function mesh_object_remove(raw: mesh_object_t) {
 	array_remove(scene_meshes, raw);
-	raw.data._.refcount--;
-
 	object_remove_super(raw.base);
 }
 
@@ -113,9 +110,6 @@ function mesh_object_get_contexts(raw: mesh_object_t, context: string, materials
 }
 
 function mesh_object_render(raw: mesh_object_t, context: string, bind_params: string[]) {
-	if (raw.data == null || !raw.data._.ready) {
-		return; // Data not yet streamed
-	}
 	if (!raw.base.visible) {
 		return; // Skip render if object is hidden
 	}
@@ -139,7 +133,6 @@ function mesh_object_render(raw: mesh_object_t, context: string, bind_params: st
 
 	// Render mesh
 	let scontext: shader_context_t = shader_contexts[0];
-	let elems: vertex_element_t[] = scontext.vertex_elements;
 
 	// Uniforms
 	if (scontext._.pipe_state != _mesh_object_last_pipeline) {
@@ -150,8 +143,8 @@ function mesh_object_render(raw: mesh_object_t, context: string, bind_params: st
 	uniforms_set_obj_consts(scontext, raw.base);
 	uniforms_set_material_consts(scontext, material_contexts[0]);
 
-	gpu_set_vertex_buffer(mesh_data_get(raw.data, elems));
-	gpu_set_index_buffer(raw.data._.index_buffers[0]);
+	gpu_set_vertex_buffer(raw.data._.vertex_buffer);
+	gpu_set_index_buffer(raw.data._.index_buffer);
 	gpu_draw();
 }
 

+ 2 - 10
base/sources/ts/iron/scene.ts

@@ -419,17 +419,14 @@ type mesh_data_t = {
 	scale_pos?: f32; // Unpack pos from (-1,1) coords
 	scale_tex?: f32; // Unpack tex from (-1,1) coords
 	vertex_arrays?: vertex_array_t[];
-	index_arrays?: index_array_t[];
+	index_array?: u32_array_t; // size = 3
 	_?: mesh_data_runtime_t;
 };
 
 type mesh_data_runtime_t = {
-	refcount?: i32; // Number of users
 	handle?: string; // Handle used to retrieve this object in Data
 	vertex_buffer?: gpu_buffer_t;
-	vertex_buffer_map?: map_t<string, gpu_buffer_t>;
-	index_buffers?: gpu_buffer_t[];
-	ready?: bool;
+	index_buffer?: gpu_buffer_t;
 	structure?: gpu_vertex_structure_t;
 };
 
@@ -439,11 +436,6 @@ type vertex_array_t = {
 	values?: i16_array_t;
 };
 
-type index_array_t = {
-	material?: i32;
-	values?: u32_array_t; // size = 3
-};
-
 type camera_data_t = {
 	name?: string;
 	near_plane?: f32;

+ 1 - 1
base/sources/ts/line_draw.ts

@@ -269,7 +269,7 @@ function shape_draw_sphere(mat: mat4_t) {
 			buffer_set_f32(data, (i * 3 + 2) * 4, posa[i * 4 + 2] / 32767);
 		}
 		gpu_vertex_buffer_unlock(_shape_draw_sphere_vb);
-		_shape_draw_sphere_ib = md._.index_buffers[0];
+		_shape_draw_sphere_ib = md._.index_buffer;
 	}
 
 	gpu_set_vertex_buffer(_shape_draw_sphere_vb);

+ 1 - 1
base/sources/ts/physics_body.ts

@@ -57,7 +57,7 @@ function physics_body_init(body: physics_body_t, obj: object_t) {
 		let scale: vec4_t = obj.transform.scale;
 
 		let positions: i16_array_t = mesh_data_get_vertex_array(data, "pos").values;
-		let indices0: u32_array_t = data.index_arrays[0].values;
+		let indices0: u32_array_t = data.index_array;
 
 		scale_pos = scale.x * data.scale_pos;
 		posa = positions;

+ 3 - 3
base/sources/ts/render_path_raytrace.ts

@@ -164,14 +164,14 @@ function render_path_raytrace_raytrace_init(shader_name: string, build: bool = t
 			if (!po.base.visible) {
 				continue;
 			}
-			iron_raytrace_as_add(po.data._.vertex_buffer, po.data._.index_buffers[0], po.base.transform.world_unpack);
+			iron_raytrace_as_add(po.data._.vertex_buffer, po.data._.index_buffer, po.base.transform.world_unpack);
 		}
 		///else
 		iron_raytrace_as_add(render_path_raytrace_vb, render_path_raytrace_ib, render_path_raytrace_transform);
 		///end
 
 		let vb_full: gpu_buffer_t = context_raw.merged_object.data._.vertex_buffer;
-		let ib_full: gpu_buffer_t = context_raw.merged_object.data._.index_buffers[0];
+		let ib_full: gpu_buffer_t = context_raw.merged_object.data._.index_buffer;
 
 		iron_raytrace_as_build(vb_full, ib_full);
 	}
@@ -203,7 +203,7 @@ function render_path_raytrace_build_data(bake: bool = false) {
 	}
 
 	render_path_raytrace_vb = mo.data._.vertex_buffer;
-	render_path_raytrace_ib = mo.data._.index_buffers[0];
+	render_path_raytrace_ib = mo.data._.index_buffer;
 }
 
 function render_path_raytrace_draw(use_live_layer: bool) {

+ 1 - 3
base/sources/ts/tab_meshes.ts

@@ -371,9 +371,7 @@ function tab_meshes_set_default_mesh(name: string) {
 				{ values: mesh.nora, attrib: "nor", data: "short2norm" },
 				{ values: mesh.texa, attrib: "tex", data: "short2norm" }
 			],
-			index_arrays: [
-				{ values: mesh.inda, material: 0 }
-			],
+			index_array: mesh.inda,
 			scale_pos: mesh.scale_pos,
 			scale_tex: mesh.scale_tex
 		};

+ 2 - 3
base/sources/ts/tab_plugins.ts

@@ -49,14 +49,13 @@ function plugin_uv_unwrap_button() {
 			posa: md.vertex_arrays[0].values,
 			nora: md.vertex_arrays[1].values,
 			texa: null,
-			inda: md.index_arrays[0].values
+			inda: md.index_array
 		};
 		js_call_ptr(cb, mesh);
 		md.vertex_arrays[0].values = mesh.posa;
 		md.vertex_arrays[1].values = mesh.nora;
 		md.vertex_arrays[2].values = mesh.texa;
-		md.index_arrays[0].values = mesh.inda;
-		md._.ready = false;
+		md.index_array = mesh.inda;
 		mesh_data_build(md);
 	}
 	util_mesh_merge();

+ 1 - 6
base/sources/ts/ui_menubar.ts

@@ -184,12 +184,7 @@ function ui_menubar_draw_tab_header() {
 								data: "short2norm"
 							}
 						],
-						index_arrays: [
-							{
-								values: mesh.inda,
-								material: 0
-							}
-						],
+						index_array: mesh.inda,
 						scale_pos: mesh.scale_pos,
 						scale_tex: mesh.scale_tex
 					};

+ 3 - 12
base/sources/ts/util_encode.ts

@@ -45,9 +45,7 @@ function util_encode_mesh_data_size(datas: mesh_data_t[]): i32 {
 		for (let j: i32 = 0; j < datas[i].vertex_arrays.length; ++j) {
 			size += datas[i].vertex_arrays[j].values.length * 2;
 		}
-		for (let j: i32 = 0; j < datas[i].index_arrays.length; ++j) {
-			size += datas[i].index_arrays[j].values.length * 4;
-		}
+		size += datas[i].index_array.length * 4;
 	}
 	return size;
 }
@@ -103,15 +101,8 @@ function util_encode_mesh_datas(datas: mesh_data_t[]) {
 			armpack_encode_string("values");
 			armpack_encode_array_i16(datas[i].vertex_arrays[j].values);
 		}
-		armpack_encode_string("index_arrays");
-		armpack_encode_array(datas[i].index_arrays.length);
-		for (let j: i32 = 0; j < datas[i].index_arrays.length; ++j) {
-			armpack_encode_map(2);
-			armpack_encode_string("material");
-			armpack_encode_i32(datas[i].index_arrays[j].material);
-			armpack_encode_string("values");
-			armpack_encode_array_i32(datas[i].index_arrays[j].values);
-		}
+		armpack_encode_string("index_array");
+		armpack_encode_array_i32(datas[i].index_array);
 	}
 }
 

+ 8 - 13
base/sources/ts/util_mesh.ts

@@ -18,7 +18,7 @@ function util_mesh_merge(paint_objects: mesh_object_t[] = null) {
 	let max_scale: f32 = 0.0;
 	for (let i: i32 = 0; i < paint_objects.length; ++i) {
 		vlen += paint_objects[i].data.vertex_arrays[0].values.length;
-		ilen += paint_objects[i].data.index_arrays[0].values.length;
+		ilen += paint_objects[i].data.index_array.length;
 		if (paint_objects[i].data.scale_pos > max_scale) {
 			max_scale = paint_objects[i].data.scale_pos;
 		}
@@ -34,7 +34,7 @@ function util_mesh_merge(paint_objects: mesh_object_t[] = null) {
 	let ioff: i32 = 0;
 	for (let i: i32 = 0; i < paint_objects.length; ++i) {
 		let vas: vertex_array_t[] = paint_objects[i].data.vertex_arrays;
-		let ias: index_array_t[] = paint_objects[i].data.index_arrays;
+		let ia: u32_array_t = paint_objects[i].data.index_array;
 		let scale: f32 = paint_objects[i].data.scale_pos;
 
 		// Pos
@@ -71,12 +71,12 @@ function util_mesh_merge(paint_objects: mesh_object_t[] = null) {
 			}
 		}
 		// Indices
-		for (let j: i32 = 0; j < ias[0].values.length; ++j) {
-			ia[j + ioff] = ias[0].values[j] + voff;
+		for (let j: i32 = 0; j < ia.length; ++j) {
+			ia[j + ioff] = ia[j] + voff;
 		}
 
 		voff += math_floor(vas[0].values.length / 4);
-		ioff += math_floor(ias[0].values.length);
+		ioff += math_floor(ia.length);
 	}
 
 	let raw: mesh_data_t = {
@@ -98,12 +98,7 @@ function util_mesh_merge(paint_objects: mesh_object_t[] = null) {
 				data: "short2norm"
 			}
 		],
-		index_arrays: [
-			{
-				values: ia,
-				material: 0
-			}
-		],
+		index_array: ia,
 		scale_pos: max_scale,
 		scale_tex: 1.0
 	};
@@ -211,7 +206,7 @@ function util_mesh_calc_normals(smooth: bool = false) {
 		let o: mesh_object_t = objects[i];
 		let g: mesh_data_t = o.data;
 		let l: i32 = gpu_vertex_struct_size(g._.structure) / 2;
-		let inda: u32_array_t = g.index_arrays[0].values;
+		let inda: u32_array_t = g.index_array;
 		let vertices: buffer_t = gpu_lock_vertex_buffer(g._.vertex_buffer); // posnortex
 		for (let i: i32 = 0; i < math_floor(inda.length / 3); ++i) {
 			let i1: i32 = inda[i * 3    ];
@@ -457,7 +452,7 @@ function util_mesh_decimate() {
 	let posa: i16_array_t = vas[0].values;
 	let nora: i16_array_t = vas[1].values;
 	let texa: i16_array_t = vas[2].values;
-	let inda: u32_array_t = o.data.index_arrays[0].values;
+	let inda: u32_array_t = o.data.index_array;
 
 	let mesh: raw_mesh_t = {
 		posa: posa,

+ 3 - 3
base/sources/ts/util_uv.ts

@@ -33,7 +33,7 @@ function util_uv_cache_uv_map() {
 				merged.data : context_raw.paint_object.data;
 
 	let texa: i16_array_t = mesh.vertex_arrays[2].values;
-	let inda: u32_array_t = mesh.index_arrays[0].values;
+	let inda: u32_array_t = mesh.index_array;
 	draw_begin(util_uv_uvmap, true, 0x00000000);
 	draw_set_color(0xffffffff);
 	let strength: f32 = res_x > 2048 ? 2.0 : 1.0;
@@ -71,7 +71,7 @@ function util_uv_cache_triangle_map() {
 	let merged: mesh_data_t = context_raw.merged_object != null ? context_raw.merged_object.data : context_raw.paint_object.data;
 	let mesh: mesh_data_t = merged;
 	let texa: i16_array_t = mesh.vertex_arrays[2].values;
-	let inda: u32_array_t = mesh.index_arrays[0].values;
+	let inda: u32_array_t = mesh.index_array;
 	draw_begin(util_uv_trianglemap, true, 0xff000000);
 	let f: f32 = (1 / 32767) * util_uv_trianglemap.width;
 	let color: i32 = 0xff000001;
@@ -127,7 +127,7 @@ function util_uv_cache_dilate_map() {
 	_gpu_begin(util_uv_dilatemap, null, null, clear_flag_t.COLOR, 0x00000000);
 	gpu_set_pipeline(util_uv_pipe_dilate);
 	gpu_set_vertex_buffer(geom._.vertex_buffer);
-	gpu_set_index_buffer(geom._.index_buffers[0]);
+	gpu_set_index_buffer(geom._.index_buffer);
 	gpu_draw();
 	gpu_end();
 	util_uv_dilatemap_cached = true;

+ 1 - 1
base/tests/fall/sources/main.ts

@@ -146,7 +146,7 @@ function scene_ready() {
 
 	asim_world_create();
 	body = asim_body_create(1, 1, 1, 1, 1, 0, 0, 5, null, null, 1);
-	asim_body_create(0, 1, 1, 1, 1, 0, 0, 0, mesh.data.vertex_arrays[0].values, mesh.data.index_arrays[0].values, mesh.data.scale_pos);
+	asim_body_create(0, 1, 1, 1, 1, 0, 0, 0, mesh.data.vertex_arrays[0].values, mesh.data.index_array, mesh.data.scale_pos);
 }
 
 function scene_update() {

+ 1 - 11
base/tools/io_export_arm.py

@@ -333,8 +333,6 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
         for poly in exportMesh.polygons:
             poly_map[poly.material_index].append(poly)
 
-        o["index_arrays"] = []
-
         # map polygon indices to triangle loops
         tri_loops = {}
         for loop in exportMesh.loop_triangles:
@@ -358,15 +356,7 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
                     prim[i + 2] = loops[loop.loops[2]].index
                     i += 3
 
-            ia = {}
-            ia["material"] = 0
-            if len(mats) > 1:
-                for i in range(len(mats)):  # Multi-mat mesh
-                    if mats[i] == mats[index]:  # Default material for empty slots
-                        ia["material"] = i
-                        break
-            ia["values"] = prim
-            o["index_arrays"].append(ia)
+            o["index_array"] = prim
 
     def export_mesh(self, objectRef):
         # This function exports a single mesh object

+ 1 - 1
lab/sources/render_path_paint.ts

@@ -190,7 +190,7 @@ function render_path_paint_draw_cursor(mx: f32, my: f32, radius: f32, tint_r: f3
 	let inv_vp: mat4_t = mat4_inv(scene_camera.vp);
 	gpu_set_matrix4(pipes_cursor_inv_vp, inv_vp);
 	gpu_set_vertex_buffer(geom._.vertex_buffer);
-	gpu_set_index_buffer(geom._.index_buffers[0]);
+	gpu_set_index_buffer(geom._.index_buffer);
 	gpu_draw();
 	render_path_end();
 }

BIN
paint/assets/meshes/box.arm


BIN
paint/assets/meshes/box_bevel.arm


BIN
paint/assets/meshes/box_bevel_shared_uvs.arm


BIN
paint/assets/meshes/box_shared_uvs.arm


BIN
paint/assets/meshes/cone.arm


BIN
paint/assets/meshes/cylinder.arm


BIN
paint/assets/meshes/torus.arm


+ 2 - 4
paint/sources/render_path_paint.ts

@@ -451,7 +451,7 @@ function render_path_paint_draw_cursor(mx: f32, my: f32, radius: f32, tint_r: f3
 	let inv_vp: mat4_t = mat4_inv(scene_camera.vp);
 	gpu_set_matrix4(pipes_cursor_inv_vp, inv_vp);
 	gpu_set_vertex_buffer(geom._.vertex_buffer);
-	gpu_set_index_buffer(geom._.index_buffers[0]);
+	gpu_set_index_buffer(geom._.index_buffer);
 	gpu_draw();
 	render_path_end();
 }
@@ -754,9 +754,7 @@ function render_path_paint_set_plane_mesh() {
 				{ attrib: "nor", values: i16_array_create_from_array(nora), data: "short2norm" },
 				{ attrib: "tex", values: i16_array_create_from_array(texa), data: "short2norm" }
 			],
-			index_arrays: [
-				{ values: u32_array_create_from_array(inda), material: 0 }
-			],
+			index_array: u32_array_create_from_array(inda),
 			scale_pos: 1.5,
 			scale_tex: 1.0
 		};