forked from LeenkxTeam/LNXSDK
130 lines
3.4 KiB
Haxe
130 lines
3.4 KiB
Haxe
package iron.data;
|
|
|
|
import kha.graphics4.Usage;
|
|
import kha.graphics4.VertexData;
|
|
import kha.arrays.Int16Array;
|
|
import kha.arrays.Uint32Array;
|
|
import iron.data.SceneFormat;
|
|
|
|
class MeshData {
|
|
|
|
public var name: String;
|
|
public var raw: TMeshData;
|
|
public var format: TSceneFormat;
|
|
public var geom: Geometry;
|
|
public var start = 0; // Batched
|
|
public var count = -1;
|
|
public var refcount = 0; // Number of users
|
|
public var handle: String; // Handle used to retrieve this object in Data
|
|
public var scalePos: kha.FastFloat = 1.0;
|
|
public var scaleTex: kha.FastFloat = 1.0;
|
|
public var isSkinned: Bool;
|
|
|
|
public function new(raw: TMeshData, done: MeshData->Void) {
|
|
this.raw = raw;
|
|
this.name = raw.name;
|
|
|
|
if (raw.scale_pos != null) scalePos = raw.scale_pos;
|
|
if (raw.scale_tex != null) scaleTex = raw.scale_tex;
|
|
|
|
// Mesh data
|
|
var indices: Array<Uint32Array> = [];
|
|
var materialIndices: Array<Int> = [];
|
|
for (ind in raw.index_arrays) {
|
|
indices.push(ind.values);
|
|
materialIndices.push(ind.material);
|
|
}
|
|
|
|
// Skinning
|
|
isSkinned = raw.skin != null;
|
|
|
|
// Prepare vertex array for skinning and fill size data
|
|
var vertexArrays = raw.vertex_arrays;
|
|
if (isSkinned) {
|
|
vertexArrays.push({ attrib: "bone", values: null, data: "short4norm" });
|
|
vertexArrays.push({ attrib: "weight", values: null, data: "short4norm" });
|
|
}
|
|
for (i in 0...vertexArrays.length) {
|
|
vertexArrays[i].size = getVertexSize(vertexArrays[i].data, getPadding(vertexArrays[i].padding));
|
|
}
|
|
|
|
// Usage, also used for instanced data
|
|
var parsedUsage = Usage.StaticUsage;
|
|
if (raw.dynamic_usage != null && raw.dynamic_usage == true) parsedUsage = Usage.DynamicUsage;
|
|
var usage = parsedUsage;
|
|
|
|
if (isSkinned) {
|
|
var bonea = null;
|
|
var weighta = null;
|
|
var vertex_length = Std.int(vertexArrays[0].values.length / vertexArrays[0].size);
|
|
var l = vertex_length * 4;
|
|
bonea = new Int16Array(l);
|
|
weighta = new Int16Array(l);
|
|
|
|
var index = 0;
|
|
var ai = 0;
|
|
for (i in 0...vertex_length) {
|
|
var boneCount = raw.skin.bone_count_array[i];
|
|
for (j in index...(index + boneCount)) {
|
|
bonea[ai] = raw.skin.bone_index_array[j];
|
|
weighta[ai] = raw.skin.bone_weight_array[j];
|
|
ai++;
|
|
}
|
|
// Fill unused weights
|
|
for (j in boneCount...4) {
|
|
bonea[ai] = 0;
|
|
weighta[ai] = 0;
|
|
ai++;
|
|
}
|
|
index += boneCount;
|
|
}
|
|
vertexArrays[vertexArrays.length - 2].values = bonea;
|
|
vertexArrays[vertexArrays.length - 1].values = weighta;
|
|
}
|
|
|
|
// Make vertex buffers
|
|
geom = new Geometry(this, indices, materialIndices, usage);
|
|
geom.name = name;
|
|
|
|
done(this);
|
|
}
|
|
|
|
public function delete() {
|
|
geom.delete();
|
|
}
|
|
|
|
public static function parse(name: String, id: String, done: MeshData->Void) {
|
|
Data.getSceneRaw(name, function(format: TSceneFormat) {
|
|
var raw: TMeshData = Data.getMeshRawByName(format.mesh_datas, id);
|
|
if (raw == null) {
|
|
trace('Mesh data "$id" not found!');
|
|
done(null);
|
|
}
|
|
|
|
new MeshData(raw, function(dat: MeshData) {
|
|
dat.format = format;
|
|
// Skinned
|
|
#if lnx_skin
|
|
if (raw.skin != null) {
|
|
dat.geom.initSkeletonTransforms(raw.skin.transformsI);
|
|
}
|
|
#end
|
|
done(dat);
|
|
});
|
|
});
|
|
}
|
|
|
|
function getVertexSize(vertex_data: String, padding: Int = 0): Int {
|
|
switch (vertex_data) {
|
|
case "short4norm": return 4 - padding;
|
|
case "short2norm": return 2 - padding;
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
inline function getPadding(padding: Null<Int>): Int {
|
|
return padding != null ? padding : 0;
|
|
}
|
|
}
|
|
|