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; | ||
|  | 	} | ||
|  | } | ||
|  | 
 |