Skip to content

Commit

Permalink
Make the OBJ flipping change less breaking
Browse files Browse the repository at this point in the history
  • Loading branch information
zbx1425 committed Jul 31, 2023
1 parent a6085af commit 35cb9d4
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 33 deletions.
37 changes: 31 additions & 6 deletions common/src/main/java/cn/zbx1425/mtrsteamloco/Debug.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,68 @@
import cn.zbx1425.sowcerext.model.loader.NmbModelLoader;
import cn.zbx1425.sowcerext.model.loader.ObjModelLoader;
import mtr.data.TransportMode;
import mtr.mappings.UtilitiesClient;
import mtr.render.JonModelTrainRenderer;
import net.minecraft.client.Minecraft;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.Resource;
import org.apache.commons.io.FilenameUtils;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;

public class Debug {

public static void saveAllBuiltinModels(Path outputDir) {
mtr.client.TrainClientRegistry.forEach(TransportMode.TRAIN, (trainId, trainProperties) -> {
if (trainProperties.renderer instanceof JonModelTrainRenderer renderer) {
if (trainProperties.renderer instanceof JonModelTrainRenderer renderer
&& renderer.model != null && renderer.textureId != null) {
try {
String textureName = FilenameUtils.getBaseName(renderer.textureId);
RawModel[] modelHead0 = TrainModelCapture.captureModels(
renderer.model, new ResourceLocation(renderer.textureId + ".png"),
1, 3);
ObjModelLoader.saveModels(nameModels(modelHead0),
outputDir.resolve(trainId + "_head0.obj"), false);
outputDir.resolve(trainId + "_head0.obj"),
outputDir.resolve(textureName + ".mtl"), false);
RawModel[] modelHead1 = TrainModelCapture.captureModels(
renderer.model, new ResourceLocation(renderer.textureId + ".png"),
0, 3);
ObjModelLoader.saveModels(nameModels(modelHead1),
outputDir.resolve(trainId + "_head1.obj"), false);
outputDir.resolve(trainId + "_head1.obj"),
outputDir.resolve(textureName + ".mtl"), false);
RawModel[] modelHead2 = TrainModelCapture.captureModels(
renderer.model, new ResourceLocation(renderer.textureId + ".png"),
2, 3);
ObjModelLoader.saveModels(nameModels(modelHead2),
outputDir.resolve(trainId + "_head2.obj"), false);
outputDir.resolve(trainId + "_head2.obj"),
outputDir.resolve(textureName + ".mtl"), false);
RawModel[] modelHead12 = TrainModelCapture.captureModels(
renderer.model, new ResourceLocation(renderer.textureId + ".png"),
0, 1);
ObjModelLoader.saveModels(nameModels(modelHead12),
outputDir.resolve(trainId + "_head12.obj"), false);
outputDir.resolve(trainId + "_head12.obj"),
outputDir.resolve(textureName + ".mtl"), false);

if (!Files.exists(outputDir.resolve(textureName + ".png"))) {
final List<Resource> resources = UtilitiesClient.getResources(Minecraft.getInstance().getResourceManager(),
new ResourceLocation(renderer.textureId + ".png"));
if (resources.size() > 0) {
try {
try (InputStream is = resources.get(0).open()) {
Files.copy(is, outputDir.resolve(textureName + ".png"));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
Expand All @@ -67,7 +92,7 @@ private static Map<String, RawModel> nameModels(RawModel[] capturedModels) {
return Map.of(
"body", capturedModels[0],
"doorXNZN", capturedModels[1], "doorXNZP", capturedModels[2],
"doorXPZN", capturedModels[3], "doorXNPP", capturedModels[4]
"doorXPZN", capturedModels[3], "doorXPZP", capturedModels[4]
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,6 @@ MtrModelRegistryUtil.resourceManager, new ResourceLocation(obj.get("atlasIndex"
if (obj.has("textureId")) {
rawModel.replaceAllTexture("default.png", new ResourceLocation(obj.get("textureId").getAsString()));
}
if (obj.has("DEPRECATED_flipv") && obj.get("DEPRECATED_flipv").getAsBoolean()) {
for (RawMesh mesh : rawModel.meshList.values()) {
for (Vertex vertex : mesh.vertices) {
vertex.v = 1 - vertex.v;
}
}
}

rawModel.sourceLocation = new ResourceLocation(rawModel.sourceLocation.toString() + "/" + key);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,37 @@
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;

public class ObjModelLoader {

public static RawModel loadModel(ResourceManager resourceManager, ResourceLocation objLocation, AtlasManager atlasManager) throws IOException {
Obj srcObj = ObjReader.read(Utilities.getInputStream(resourceManager.getResource(objLocation)));
String objContent = ResourceUtil.readResource(resourceManager, objLocation);
Obj srcObj = ObjReader.read(new StringReader(objContent));
Map<String, Mtl> materials = loadMaterials(resourceManager, srcObj, objLocation);
boolean flipV = shouldTryFlipV(objContent) && materials.keySet().stream().noneMatch(matName -> matName.contains("flipv=1"));

RawModel model = loadModel(srcObj, objLocation, materials, atlasManager);
RawModel model = loadModel(srcObj, objLocation, materials, atlasManager, flipV);
model.sourceLocation = objLocation;
return model;
}

public static Map<String, RawModel> loadModels(ResourceManager resourceManager, ResourceLocation objLocation, AtlasManager atlasManager) throws IOException {
Obj srcObj = ObjReader.read(Utilities.getInputStream(resourceManager.getResource(objLocation)));
String objContent = ResourceUtil.readResource(resourceManager, objLocation);
Obj srcObj = ObjReader.read(new StringReader(objContent));
Map<String, Mtl> materials = loadMaterials(resourceManager, srcObj, objLocation);
boolean flipV = shouldTryFlipV(objContent) && materials.keySet().stream().noneMatch(matName -> matName.contains("flipv=1"));

HashMap<String, RawModel> result = new HashMap<>();
Map<String, Obj> groupObjs = ObjSplitting.splitByGroups(srcObj);
for (Map.Entry<String, Obj> groupEntry : groupObjs.entrySet()) {
RawModel model = loadModel(groupEntry.getValue(), objLocation, materials, atlasManager);
RawModel model = loadModel(groupEntry.getValue(), objLocation, materials, atlasManager, flipV);
String compliantKey = groupEntry.getKey().toLowerCase(Locale.ROOT).replace('\\', '/').replaceAll("[^a-z0-9/._-]", "_");
model.sourceLocation = new ResourceLocation(objLocation.getNamespace(), objLocation.getPath() + "/" + compliantKey);
result.put(groupEntry.getKey(), model);
Expand All @@ -51,13 +53,15 @@ public static Map<String, RawModel> loadModels(ResourceManager resourceManager,
}

public static Map<String, RawModel> loadExternalModels(String path, AtlasManager atlasManager) throws IOException {
try (BufferedInputStream fis = new BufferedInputStream(new FileInputStream(path))) {
Obj srcObj = ObjReader.read(fis);
try (FileInputStream fis = new FileInputStream(path)) {
String objContent = IOUtils.toString(fis);
Obj srcObj = ObjReader.read(new StringReader(objContent));
boolean flipV = shouldTryFlipV(objContent);

HashMap<String, RawModel> result = new HashMap<>();
Map<String, Obj> groupObjs = ObjSplitting.splitByGroups(srcObj);
for (Map.Entry<String, Obj> groupEntry : groupObjs.entrySet()) {
RawModel model = loadModel(groupEntry.getValue(), null, null, atlasManager);
RawModel model = loadModel(groupEntry.getValue(), null, null, atlasManager, flipV);
String compliantPath = path.toLowerCase(Locale.ROOT).replace('\\', '/').replaceAll("[^a-z0-9/._-]", "_");
String compliantKey = groupEntry.getKey().toLowerCase(Locale.ROOT).replace('\\', '/').replaceAll("[^a-z0-9/._-]", "_");
model.sourceLocation = new ResourceLocation("mtrsteamloco-external", compliantPath + "/" + compliantKey);
Expand All @@ -67,7 +71,7 @@ public static Map<String, RawModel> loadExternalModels(String path, AtlasManager
}
}

private static RawModel loadModel(Obj srcObj, ResourceLocation objLocation, Map<String, Mtl> materials, AtlasManager atlasManager) {
private static RawModel loadModel(Obj srcObj, ResourceLocation objLocation, Map<String, Mtl> materials, AtlasManager atlasManager, boolean objFlipV) {
Map<String, Obj> mtlObjs = ObjSplitting.splitByMaterialGroups(srcObj);
RawModel model = new RawModel();
for (Map.Entry<String, Obj> entry : mtlObjs.entrySet()) {
Expand All @@ -76,6 +80,7 @@ private static RawModel loadModel(Obj srcObj, ResourceLocation objLocation, Map<
Map<String, String> materialOptions = splitMaterialOptions(entry.getKey());
String materialGroupName = materialOptions.get("");
String meshRenderType = materialOptions.getOrDefault("#", "exterior").toLowerCase(Locale.ROOT);
boolean matFlipV = materialOptions.getOrDefault("flipv", "0").equals("1");
MaterialProp materialProp = new MaterialProp();

if ((materials != null && materials.size() > 0) && objLocation != null) {
Expand Down Expand Up @@ -116,7 +121,7 @@ private static RawModel loadModel(Obj srcObj, ResourceLocation objLocation, Map<
new Vector3f(normal.getX(), normal.getY(), normal.getZ())
);
seVertex.u = uv.getX();
seVertex.v = 1 - uv.getY();
seVertex.v = (objFlipV || matFlipV) ? 1 - uv.getY() : uv.getY();
mesh.vertices.add(seVertex);
}
for (int i = 0; i < renderObjMesh.getNumFaces(); ++i) {
Expand Down Expand Up @@ -162,10 +167,17 @@ private static Map<String, String> splitMaterialOptions(String src) {
return result;
}

public static void saveModels(Map<String, RawModel> models, Path outputFile, boolean withNormal) throws IOException {
String mtlFileName = FilenameUtils.removeExtension(outputFile.getFileName().toString()) + ".mtl";
try (PrintWriter objFile = new PrintWriter(Files.newOutputStream(outputFile));
PrintWriter mtlFile = new PrintWriter(Files.newOutputStream(outputFile.resolveSibling(mtlFileName)))) {
private static boolean shouldTryFlipV(String objContent) {
int lineEnd = objContent.indexOf('\n');
if (lineEnd < 0) return false;
String firstLine = objContent.substring(0, lineEnd).trim().toLowerCase(Locale.ROOT);
return firstLine.contains("blender") || firstLine.contains("blockbench");
}

public static void saveModels(Map<String, RawModel> models, Path objOutputFile, Path mtlOutputFile, boolean withNormal) throws IOException {
String mtlFileName = mtlOutputFile.getFileName().toString();
try (PrintWriter objFile = new PrintWriter(Files.newOutputStream(objOutputFile));
PrintWriter mtlFile = new PrintWriter(Files.newOutputStream(mtlOutputFile))) {
objFile.println("# Generated by MTR-NTE " + BuildConfig.MOD_VERSION);
mtlFile.println("# Generated by MTR-NTE " + BuildConfig.MOD_VERSION);
Set<String> writtenMaterials = new HashSet<>();
Expand Down Expand Up @@ -204,7 +216,7 @@ public static void saveModels(Map<String, RawModel> models, Path outputFile, boo
if (withNormal) {
objFile.printf("vn %f %f %f\n", vertex.normal.x(), vertex.normal.y(), vertex.normal.z());
}
objFile.printf("vt %f %f\n", vertex.u, vertex.v);
objFile.printf("vt %f %f\n", vertex.u, 1 - vertex.v);
}
for (Face face : mesh.faces) {
if (withNormal) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
"nte_builtin_concrete_sleeper": {
"name": "rail.mtrsteamloco.builtin_concrete_sleeper",
"model": "mtrsteamloco:models/rail.obj",
"DEPRECATED_flipv": true,
"repeatInterval": 0.5
},
"nte_builtin_depot": {
"name": "rail.mtrsteamloco.builtin_depot",
"model": "mtrsteamloco:models/rail_siding.obj",
"DEPRECATED_flipv": true,
"repeatInterval": 0.5
},
"nte_builtin_flat": {
Expand Down

0 comments on commit 35cb9d4

Please sign in to comment.