Browse Source

Merge: merge material ids if they are identical + handle lods

lviguier 3 months ago
parent
commit
292c48f87d
1 changed files with 69 additions and 22 deletions
  1. 69 22
      hide/view/Model.hx

+ 69 - 22
hide/view/Model.hx

@@ -1305,7 +1305,7 @@ class Model extends FileView {
 			e.preventDefault();
 			var current = tree.getCurrentOver();
 			var menuItems : Array<hide.comp.ContextMenu.MenuItem> = [
-				{ label : "Merge selected", enabled : canMergeElements(selectedElements), click: () -> mergeModels(cast selectedElements) },
+				{ label : "Merge selected", enabled : false /*canMergeElements(selectedElements)*/, click: () -> mergeModels(cast selectedElements) },
 				{ label : "Merge all meshes", enabled : true, click: () -> mergeModels(cast [for (m in obj.findAll(o -> Std.downcast(o, h3d.scene.Mesh))) m]) },
 			];
 
@@ -1519,7 +1519,7 @@ class Model extends FileView {
 			var p2 = Std.downcast(m2.primitive, h3d.prim.HMDModel);
 
 			if (p1 == null || p2 == null)
-				throw "!";
+				throw "Can't merge non-HMDModels";
 
 			// Creation of the merged HMD
 			var hmd = new hxd.fmt.hmd.Data();
@@ -1530,12 +1530,6 @@ class Model extends FileView {
 			hmd.animations = [];
 			hmd.shapes = [];
 
-			var mat = new hxd.fmt.hmd.Data.Material();
-			mat.name = "SimpleBlock";
-			mat.blendMode = None;
-			mat.props = [];
-			hmd.materials.push(mat);
-
 			var maxLod = Std.int(hxd.Math.max(p1.lodCount(), p2.lodCount()));
 			var modelName = m1.name + "_" + m2.name;
 
@@ -1543,7 +1537,7 @@ class Model extends FileView {
 			model.name = modelName;
 			model.name = model.toLODName(0);
 			model.geometry = 0;
-			model.materials = [0];
+			model.materials = [];
 			model.parent = -1;
 			model.position = new hxd.fmt.hmd.Data.Position();
 			model.position.x = 0;
@@ -1560,7 +1554,55 @@ class Model extends FileView {
 			model.props.push(HasLod);
 			hmd.models.push(model);
 
+			var mat1 = m1.getMaterials();
+			var mat2 = m2.getMaterials();
+			var indexCounts = [];
+			var totalCount = 0;
+			var remap : Array<Array<{ count : Int, offset : Int }>> = [];
+			for (mIdx in 0...(mat1.length + mat2.length)) {
+				var indexCount = mIdx < mat1.length ? p1.getMaterialIndexCount(mIdx) : p2.getMaterialIndexCount(mIdx - mat1.length);
+				var m = mIdx < mat1.length ? mat1[mIdx] : mat2[mIdx - mat1.length];
+				var mId = -1;
+				for (id in model.materials) {
+					if (hmd.materials[id].name == m.name)
+						mId = id;
+				}
+
+				if (mId != -1) {
+					indexCounts[mId] += indexCount;
+					remap[mId].push({ count: indexCount, offset: totalCount });
+					totalCount += indexCount;
+					continue;
+				}
+
+				mId = hmd.materials.length;
+
+				var matData : hxd.fmt.hmd.Data.Material = null;
+				@:privateAccess {
+					for (dataIdx in 0...(p1.lib.header.materials.length + p2.lib.header.materials.length)) {
+						matData = dataIdx < p1.lib.header.materials.length ? p1.lib.header.materials[dataIdx] :  p1.lib.header.materials[dataIdx - p1.lib.header.materials.length];
+						if (matData.name == m.name)
+							break;
+					}
+				}
+
+				remap[mId] = [{ count: indexCount, offset: totalCount }];
+				indexCounts.push(indexCount);
+				hmd.materials.push(matData);
+				model.materials.push(mId);
+				totalCount += indexCount;
+			}
+
 			var dataOut = new haxe.io.BytesOutput();
+			var totalVertexCount = 0;
+			for (lodIdx in 0...maxLod) {
+				var newFormat = hxd.BufferFormat.make([for (i in format.getInputs()) i]);
+				var d1 = hxd.fmt.fbx.Writer.getPrimitiveInfos(p1, newFormat, lodIdx);
+				var d2 = hxd.fmt.fbx.Writer.getPrimitiveInfos(p2, newFormat, lodIdx);
+				totalVertexCount += Std.int((d1.vertexBuffer.length + d2.vertexBuffer.length) / d1.vertexFormat.stride);
+			}
+
+			var is32 = totalVertexCount > 0x10000;
 			for (lodIdx in 0...maxLod) {
 				var newFormat = hxd.BufferFormat.make([for (i in format.getInputs()) i]);
 
@@ -1572,7 +1614,7 @@ class Model extends FileView {
 
 				var g = new hxd.fmt.hmd.Data.Geometry();
 				g.bounds = new h3d.col.Bounds();
-				g.indexCounts = [ indexCount ];
+				g.indexCounts = indexCounts;
 				g.vertexCount = vertexCount;
 				g.vertexFormat = newFormat;
 				g.vertexPosition = dataOut.length;
@@ -1601,7 +1643,7 @@ class Model extends FileView {
 						if (vIdx < d1.vertexBuffer.length)
 							return d1.vertexBuffer[vIdx];
 						else
-							return d2.vertexBuffer[vIdx % d1.vertexBuffer.length];
+							return d2.vertexBuffer[vIdx - d1.vertexBuffer.length];
 					}
 
 					for (i in g.vertexFormat.getInputs()) {
@@ -1626,19 +1668,24 @@ class Model extends FileView {
 				}
 
 				g.indexPosition = dataOut.length;
-				var offset = 0;
-				for (i in 0...indexCount) {
-					function get(vIdx: Int) {
-						if (vIdx < d1.indexesBuffer.length) {
-							if (offset < d1.indexesBuffer[vIdx])
-								offset = d1.indexesBuffer[vIdx];
-							return d1.indexesBuffer[vIdx];
-						}
-						else
-							return d2.indexesBuffer[vIdx % d1.indexesBuffer.length] + offset + 1;
+				function get(vIdx: Int) {
+					if (vIdx < d1.indexesBuffer.length) {
+						return d1.indexesBuffer[vIdx];
 					}
+					else
+						return d2.indexesBuffer[vIdx - d1.indexesBuffer.length] + Std.int(d1.vertexBuffer.length / g.vertexFormat.stride);
+				}
 
-					dataOut.writeUInt16(get(i));
+				for (r in remap) {
+					for (i in r) {
+						for (idx in 0...i.count) {
+							var realIdx = idx + i.offset;
+							if (is32)
+								dataOut.writeInt32(get(realIdx));
+							else
+								dataOut.writeUInt16(get(realIdx));
+						}
+					}
 				}
 			}