mirror of
https://github.com/exogen/t2-mapper.git
synced 2026-07-11 14:34:51 +00:00
fix texture lookup - try .jpg and .bmp too
This commit is contained in:
parent
5d0a8a3fab
commit
5f48c1c2d2
12 changed files with 95 additions and 46 deletions
|
|
@ -1,10 +1,6 @@
|
|||
import { memo, Suspense, useMemo, useRef, useEffect } from "react";
|
||||
import { useGLTF, useTexture } from "@react-three/drei";
|
||||
import {
|
||||
FALLBACK_TEXTURE_URL,
|
||||
shapeTextureToUrl,
|
||||
shapeToUrl,
|
||||
} from "../loaders";
|
||||
import { FALLBACK_TEXTURE_URL, textureToUrl, shapeToUrl } from "../loaders";
|
||||
import { filterGeometryByVertexGroups, getHullBoneIndices } from "../meshUtils";
|
||||
import {
|
||||
createAlphaAsRoughnessMaterial,
|
||||
|
|
@ -73,7 +69,7 @@ function StaticTexture({ material, shapeName }) {
|
|||
}
|
||||
return resourcePath
|
||||
? // Use custom `resource_path` added by forked io_dts3d Blender add-on
|
||||
shapeTextureToUrl(resourcePath)
|
||||
textureToUrl(resourcePath)
|
||||
: FALLBACK_TEXTURE_URL;
|
||||
}, [material, resourcePath, shapeName]);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { memo, Suspense, useMemo } from "react";
|
|||
import { ErrorBoundary } from "react-error-boundary";
|
||||
import { Mesh } from "three";
|
||||
import { useGLTF, useTexture } from "@react-three/drei";
|
||||
import { interiorTextureToUrl, interiorToUrl } from "../loaders";
|
||||
import { textureToUrl, interiorToUrl } from "../loaders";
|
||||
import type { TorqueObject } from "../torqueScript";
|
||||
import { getPosition, getProperty, getRotation, getScale } from "../mission";
|
||||
import { setupColor } from "../textureUtils";
|
||||
|
|
@ -18,7 +18,7 @@ function useInterior(interiorFile: string) {
|
|||
}
|
||||
|
||||
function InteriorTexture({ materialName }: { materialName: string }) {
|
||||
const url = interiorTextureToUrl(materialName);
|
||||
const url = textureToUrl(materialName);
|
||||
const texture = useTexture(url, (texture) => setupColor(texture));
|
||||
|
||||
return <meshStandardMaterial map={texture} side={2} />;
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ import { Color, ShaderMaterial, BackSide, Euler } from "three";
|
|||
import type { TorqueObject } from "../torqueScript";
|
||||
import { getFloat, getProperty } from "../mission";
|
||||
import { useSettings } from "./SettingsProvider";
|
||||
import { BASE_URL, getUrlForPath, loadDetailMapList } from "../loaders";
|
||||
import { BASE_URL, loadDetailMapList, textureToUrl } from "../loaders";
|
||||
import { useThree } from "@react-three/fiber";
|
||||
|
||||
const FALLBACK_URL = `${BASE_URL}/black.png`;
|
||||
const FALLBACK_TEXTURE_URL = `${BASE_URL}/black.png`;
|
||||
|
||||
/**
|
||||
* Load a .dml file, used to list the textures for different faces of a skybox.
|
||||
|
|
@ -35,20 +35,20 @@ export function SkyBox({
|
|||
() =>
|
||||
detailMapList
|
||||
? [
|
||||
getUrlForPath(detailMapList[1], FALLBACK_URL), // +x
|
||||
getUrlForPath(detailMapList[3], FALLBACK_URL), // -x
|
||||
getUrlForPath(detailMapList[4], FALLBACK_URL), // +y
|
||||
getUrlForPath(detailMapList[5], FALLBACK_URL), // -y
|
||||
getUrlForPath(detailMapList[0], FALLBACK_URL), // +z
|
||||
getUrlForPath(detailMapList[2], FALLBACK_URL), // -z
|
||||
textureToUrl(detailMapList[1]), // +x
|
||||
textureToUrl(detailMapList[3]), // -x
|
||||
textureToUrl(detailMapList[4]), // +y
|
||||
textureToUrl(detailMapList[5]), // -y
|
||||
textureToUrl(detailMapList[0]), // +z
|
||||
textureToUrl(detailMapList[2]), // -z
|
||||
]
|
||||
: [
|
||||
FALLBACK_URL,
|
||||
FALLBACK_URL,
|
||||
FALLBACK_URL,
|
||||
FALLBACK_URL,
|
||||
FALLBACK_URL,
|
||||
FALLBACK_URL,
|
||||
FALLBACK_TEXTURE_URL,
|
||||
FALLBACK_TEXTURE_URL,
|
||||
FALLBACK_TEXTURE_URL,
|
||||
FALLBACK_TEXTURE_URL,
|
||||
FALLBACK_TEXTURE_URL,
|
||||
FALLBACK_TEXTURE_URL,
|
||||
],
|
||||
[detailMapList],
|
||||
);
|
||||
|
|
@ -146,6 +146,22 @@ export function Sky({ object }: { object: TorqueObject }) {
|
|||
// Skybox textures.
|
||||
const materialList = getProperty(object, "materialList");
|
||||
|
||||
const skySolidColor = useMemo(() => {
|
||||
const colorString = getProperty(object, "SkySolidColor");
|
||||
if (colorString) {
|
||||
// `colorString` might specify an alpha value, but three.js doesn't
|
||||
// support opacity on fog or scene backgrounds, so ignore it.
|
||||
// Note: This is a space-separated string, so we split and parse each component.
|
||||
const [r, g, b] = colorString
|
||||
.split(" ")
|
||||
.map((s: string) => parseFloat(s));
|
||||
return [
|
||||
new Color().setRGB(r, g, b),
|
||||
new Color().setRGB(r, g, b).convertSRGBToLinear(),
|
||||
];
|
||||
}
|
||||
}, [object]);
|
||||
|
||||
// Fog parameters.
|
||||
// TODO: There can be multiple fog volumes/layers. Render simple fog for now.
|
||||
const fogDistance = getFloat(object, "fogDistance");
|
||||
|
|
@ -166,8 +182,10 @@ export function Sky({ object }: { object: TorqueObject }) {
|
|||
}
|
||||
}, [object]);
|
||||
|
||||
const backgroundColor = fogColor ? (
|
||||
<color attach="background" args={[fogColor[0]]} />
|
||||
const skyColor = skySolidColor || fogColor;
|
||||
|
||||
const backgroundColor = skyColor ? (
|
||||
<color attach="background" args={[skyColor[0]]} />
|
||||
) : null;
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ import {
|
|||
getActualResourceKey,
|
||||
getMissionInfo,
|
||||
getSourceAndPath,
|
||||
getStandardTextureResourceKey,
|
||||
} from "./manifest";
|
||||
import { parseMissionScript } from "./mission";
|
||||
import { normalizePath } from "./stringUtils";
|
||||
import { parseTerrainBuffer } from "./terrain";
|
||||
|
||||
export const BASE_URL = "/t2-mapper";
|
||||
|
|
@ -46,25 +46,20 @@ export function shapeToUrl(name: string) {
|
|||
|
||||
export function terrainTextureToUrl(name: string) {
|
||||
name = name.replace(/^terrain\./, "");
|
||||
return getUrlForPath(`textures/terrain/${name}.png`, FALLBACK_TEXTURE_URL);
|
||||
}
|
||||
|
||||
export function interiorTextureToUrl(name: string) {
|
||||
// name = name.replace(/\.\d+$/, "");
|
||||
return getUrlForPath(`textures/${name}.png`, FALLBACK_TEXTURE_URL);
|
||||
const resourceKey = getStandardTextureResourceKey(`textures/terrain/${name}`);
|
||||
return getUrlForPath(resourceKey, FALLBACK_TEXTURE_URL);
|
||||
}
|
||||
|
||||
export function textureFrameToUrl(fileName: string) {
|
||||
return getUrlForPath(`textures/skins/${fileName}`, FALLBACK_TEXTURE_URL);
|
||||
}
|
||||
|
||||
export function shapeTextureToUrl(name: string) {
|
||||
// name = name.replace(/\.\d+$/, "");
|
||||
return getUrlForPath(`textures/${name}.png`, FALLBACK_TEXTURE_URL);
|
||||
const resourceKey = getStandardTextureResourceKey(
|
||||
`textures/skins/${fileName}`,
|
||||
);
|
||||
return getUrlForPath(resourceKey, FALLBACK_TEXTURE_URL);
|
||||
}
|
||||
|
||||
export function textureToUrl(name: string) {
|
||||
return getUrlForPath(`textures/${name}.png`, FALLBACK_TEXTURE_URL);
|
||||
const resourceKey = getStandardTextureResourceKey(`textures/${name}`);
|
||||
return getUrlForPath(resourceKey, FALLBACK_TEXTURE_URL);
|
||||
}
|
||||
|
||||
export function audioToUrl(fileName: string) {
|
||||
|
|
@ -76,8 +71,14 @@ export async function loadDetailMapList(name: string) {
|
|||
const res = await fetch(url);
|
||||
const text = await res.text();
|
||||
return text
|
||||
.split(/(?:\r\n|\n|\r)/)
|
||||
.map((line) => `textures/${line.trim().replace(/\.png$/i, "")}.png`);
|
||||
.split(/(?:\r\n|\r|\n)/)
|
||||
.map((line) => {
|
||||
line = line.trim();
|
||||
if (!line.startsWith(";")) {
|
||||
return line;
|
||||
}
|
||||
})
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
export async function loadMission(name: string) {
|
||||
|
|
|
|||
|
|
@ -88,6 +88,40 @@ export function getResourceList(): string[] {
|
|||
return Object.keys(manifest.resources);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard texture file extension loading order:
|
||||
*
|
||||
* 1. "" (no extension - exact filename match)
|
||||
* 2. .jpg
|
||||
* 3. .png
|
||||
* 4. .gif
|
||||
* 5. .bmp
|
||||
*/
|
||||
const standardTextureExt = ["", ".jpg", ".png", ".gif", ".bmp"];
|
||||
export function getStandardTextureResourceKey(resourcePath: string) {
|
||||
const baseResourceKey = getResourceKey(resourcePath);
|
||||
for (const ext of standardTextureExt) {
|
||||
const resourceKey = `${baseResourceKey}${ext}`;
|
||||
if (manifest.resources[resourceKey]) {
|
||||
return resourceKey;
|
||||
}
|
||||
}
|
||||
return baseResourceKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Paletted texture file extension loading order:
|
||||
*
|
||||
* 1. "" (no extension - exact filename match)
|
||||
* 2. .bm8
|
||||
* 3. .bmp
|
||||
* 4. .jpg
|
||||
* 5. .png
|
||||
* 6. .gif
|
||||
*/
|
||||
// Not used for now!
|
||||
const palettedTextureExt = ["", ".bm8", ".bmp", ".jpg", ".png", ".gif"];
|
||||
|
||||
export function getLocalFilePath(resourcePath: string): string {
|
||||
const resourceKey = getResourceKey(resourcePath);
|
||||
const [sourcePath, actualPath] = getSourceAndPath(resourceKey);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue