Ver Fonte

Rewrote LOD parser in HMDModel and clean code

TothBenoit há 1 ano atrás
pai
commit
d024cea29d
3 ficheiros alterados com 62 adições e 59 exclusões
  1. 8 4
      h3d/prim/HMDModel.hx
  2. 8 9
      h3d/scene/Mesh.hx
  3. 46 46
      hxd/fmt/hmd/Library.hx

+ 8 - 4
h3d/prim/HMDModel.hx

@@ -61,7 +61,7 @@ class HMDModel extends MeshPrimitive {
 		dispose();
 
 		var vertexCount : Int = 0;
-		var vertexFormat : hxd.BufferFormat = lods[0].vertexFormat;
+		var vertexFormat : hxd.BufferFormat = data.vertexFormat;
 		indexCount = 0;
 		indexesTriPos = [];
 		for ( lod in lods ) {
@@ -83,6 +83,9 @@ class HMDModel extends MeshPrimitive {
 		var curIndexCount : Int = 0;
 		
 		for ( lod in lods ) {
+			if (lod.vertexFormat != vertexFormat)
+				throw "LOD has a different vertex format";
+			
 			var size = lod.vertexCount * vertexFormat.strideBytes;
 			var bytes = entry.fetchBytes(dataPosition + lod.vertexPosition, size);			
 			engine.driver.uploadBufferBytes(buffer, curVertexCount, lod.vertexCount, bytes, 0);
@@ -230,8 +233,8 @@ class HMDModel extends MeshPrimitive {
 			return;
 		}
 
-		var materialCount = lods[0].indexCounts.length;
-		var lodLevel = Std.int(curMaterial / lods[0].indexCounts.length);
+		var materialCount = data.indexCounts.length;
+		var lodLevel = Std.int(curMaterial / data.indexCounts.length);
 
 		if( indexes == null || indexes.isDisposed() )
 			alloc(engine);
@@ -272,6 +275,7 @@ class HMDModel extends MeshPrimitive {
 		return lods.length;
 	}
 	
+	public static var lodExportKeyword : String = "LOD";
 	static var lodConfig : Array<Float> = [0.02, 0.002, 0.0002];
 	public static function loadLodConfig( config : Array<Float> ) {
 		lodConfig = config;
@@ -280,7 +284,7 @@ class HMDModel extends MeshPrimitive {
 	override public function screenRatioToLod( screenRatio : Float ) : Int {
 		var lodCount = lodCount();
 
-		if ( lodCount < 2 )
+		if ( lodCount == 1 )
 			return 0;
 
 		if ( lodConfig != null && lodConfig.length >= lodCount - 1) {

+ 8 - 9
h3d/scene/Mesh.hx

@@ -75,10 +75,8 @@ class Mesh extends Object {
 	}
 
 	function calcScreenRatio( ctx : RenderContext ) {
-		if ( primitive.lodCount() < 2 ) {
-			curScreenRatio = 1.0;
+		if ( primitive.lodCount() == 1 )
 			return;
-		}
 
 		if ( ctx.forcedScreenRatio >= 0.0 ) {
 			curScreenRatio = ctx.forcedScreenRatio;
@@ -91,15 +89,16 @@ class Mesh extends Object {
 			return;
 		}
 
-		var worldRadius = bounds.dimension() / 3.0;
-		var worldCenter = getAbsPos().getPosition();
+		var absPos = getAbsPos();
+		var worldCenter = absPos.getPosition();
+		var worldScale = absPos.getScale(); 
+		var worldRadius = bounds.dimension() * hxd.Math.max( worldScale.x, hxd.Math.max(worldScale.y, worldScale.z) ) / 2.0;
 
-		var cameraForward = ctx.camera.getForward();
 		var cameraRight = ctx.camera.getRight();
 		var cameraUp = ctx.camera.getUp();
-		var cameraTopLeft = cameraUp - cameraRight;
-		var worldTopLeft = worldCenter + ( cameraTopLeft - cameraForward ) * worldRadius;
-		var worldBottomRight = worldCenter + ( cameraTopLeft.scaled(-1) - cameraForward ) * worldRadius;
+		var cameraTopLeft = (cameraUp - cameraRight).normalized();
+		var worldTopLeft = worldCenter + cameraTopLeft * worldRadius;
+		var worldBottomRight = worldCenter - cameraTopLeft * worldRadius;
 
 		var screenTopLeft = ctx.camera.project( worldTopLeft.x, worldTopLeft.y, worldTopLeft.z, 1.0, 1.0, false );
 		var screenBottomRight = ctx.camera.project( worldBottomRight.x, worldBottomRight.y, worldBottomRight.z, 1.0, 1.0, false );

+ 46 - 46
hxd/fmt/hmd/Library.hx

@@ -1,4 +1,5 @@
 package hxd.fmt.hmd;
+import h3d.prim.HMDModel;
 import hxd.fmt.hmd.Data;
 
 private class FormatMap {
@@ -271,10 +272,15 @@ class Library {
 		var p = cachedPrimitives[id];
 		if( p != null ) return p;
 
-		var lods : Array<Geometry> = findLODs(model);
-		if (lods == null)
+		var lodModelName : String = "";
+		var lodLevel = getLODLevel( model, lodModelName ) ;
+		if ( lodLevel > 0)
 			return null;
 
+		var lods : Array<Geometry> = null;
+		if (lodLevel == 0 )
+			lods = findLODs( lodModelName );
+		
 		p = new h3d.prim.HMDModel(header.geometries[id], header.dataPosition, this, lods);
 		p.incref(); // Prevent from auto-disposing
 		cachedPrimitives[id] = p;
@@ -369,59 +375,53 @@ class Library {
 		return def;
 	}
 
-	function findLODs(model : Model) : Array<Geometry> {
+	function getLODLevel( model : Model, ?outModelName : String ) : Int {
 		var modelName : String = model.name;
-		if (modelName == null)
-			return [];
-
-		var keyword = "LOD";
+		var keyword = h3d.prim.HMDModel.lodExportKeyword;
+		if (modelName == null || modelName.length <= keyword.length)
+			return -1;
+	
+		// Test prefix
+		if ( modelName.substr(0, keyword.length) == keyword) {
+			var parsedInt = Std.parseInt(modelName.substr( keyword.length, 1 ));
+			if (parsedInt != null) {
+				if ( Std.parseInt( modelName.substr( keyword.length + 1, 1 ) ) != null )
+					throw 'Did not expect a second number after LOD in ${modelName}';
+				outModelName = modelName.substr(keyword.length);
+				return parsedInt;
+			}
+		}
 
-		var startCursor : Int = modelName.indexOf(keyword);
-		if ( startCursor < 0 )
-			return [];
-		startCursor += keyword.length;
-		if ( startCursor > modelName.length )
-			throw 'Missing LOD index for model ${modelName}';
+		// Test suffix
+		var maxCursor = modelName.length - keyword.length - 1;
+		if ( modelName.substr( maxCursor, keyword.length ) == keyword ) {
+			var parsedInt = Std.parseInt( modelName.charAt( modelName.length - 1) );
+			if ( parsedInt != null ) {
+				outModelName = modelName.substr( 0, maxCursor );
+				return parsedInt;
+			}
+		}
 
-		var endCursor : Int = startCursor;
-		while (endCursor < modelName.length && Std.parseInt(modelName.substr(endCursor, 1)) != null)
-			endCursor++;
+		return -1;
+	}
 
-		var lodLevel : Int = Std.parseInt(modelName.substr(startCursor, endCursor));
-		if (lodLevel > 0)
+	function findLODs( modelName : String ) : Array<Geometry> {
+		if ( modelName == null )
 			return null;
 
-		modelName = modelName.substr(0, startCursor) + modelName.substr(endCursor);
-
 		var lods : Array<Geometry> = [];
-		for ( curModel in header.models ) {
-			if (curModel.name == null || curModel == model)
-				continue;
-
-			var curModelName : String = curModel.name;
-
-			startCursor = curModelName.indexOf(keyword);
-			if (startCursor > curModelName.length)
-				continue;
-			startCursor += keyword.length;
-			if ( startCursor > curModelName.length )
-				throw 'Missing LOD index for model ${curModelName}';
-
-			endCursor = startCursor;
-			while (endCursor < curModelName.length && Std.parseInt(curModelName.substr(endCursor, 1)) != null)
-				endCursor++;
-
-			var curLodLevel : Int = Std.parseInt(curModelName.substr(startCursor, endCursor));
-			if (curLodLevel == 0)
-				continue;
-
-			curModelName = curModelName.substr(0, startCursor) + curModelName.substr(endCursor);
-
+		for ( curModel in header.models ) {			
+			var curModelName : String = "";
+			var lodLevel = getLODLevel(curModel, curModelName);
+			if ( lodLevel < 1 )
+				continue;	
 			if ( curModelName == modelName ) {
-				var capacityNeeded = curLodLevel;
-				if (capacityNeeded > lods.length)
+				var capacityNeeded = lodLevel;
+				if ( capacityNeeded > lods.length )
 					lods.resize(capacityNeeded);
-				lods[curLodLevel-1] = header.geometries[curModel.geometry];
+				if ( lods[lodLevel - 1] != null )
+					throw 'Multiple LODs with the same level : ${curModel.name}';
+				lods[lodLevel - 1] = header.geometries[curModel.geometry];
 			}
 		}