mirror of
https://github.com/exogen/t2-mapper.git
synced 2026-03-14 01:40:56 +00:00
fix terrain positioning, layer blending, lighting when sun points up, add xPack2
This commit is contained in:
parent
aeda3ca8d5
commit
7f75ed84da
2238 changed files with 159619 additions and 1107 deletions
|
|
@ -11,7 +11,7 @@ import {
|
|||
Texture,
|
||||
BufferGeometry,
|
||||
} from "three";
|
||||
import { setupColor, setupAlphaTestedTexture } from "../textureUtils";
|
||||
import { setupTexture } from "../textureUtils";
|
||||
import { useDebug } from "./SettingsProvider";
|
||||
import { useShapeInfo, isOrganicShape } from "./ShapeInfoProvider";
|
||||
import { FloatingLabel } from "./FloatingLabel";
|
||||
|
|
@ -217,10 +217,10 @@ const StaticTexture = memo(function StaticTexture({
|
|||
const texture = useTexture(url, (texture) => {
|
||||
// Organic/alpha-tested textures need special handling to avoid mipmap artifacts
|
||||
if (isOrganic || isTranslucent) {
|
||||
return setupAlphaTestedTexture(texture);
|
||||
return setupTexture(texture, { disableMipmaps: true });
|
||||
}
|
||||
// Standard color texture setup for diffuse-only materials
|
||||
return setupColor(texture);
|
||||
return setupTexture(texture);
|
||||
});
|
||||
|
||||
const customMaterial = useMemo(
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import { useGLTF, useTexture } from "@react-three/drei";
|
|||
import { textureToUrl, interiorToUrl } from "../loaders";
|
||||
import type { TorqueObject } from "../torqueScript";
|
||||
import { getPosition, getProperty, getRotation, getScale } from "../mission";
|
||||
import { setupColor } from "../textureUtils";
|
||||
import { setupTexture } from "../textureUtils";
|
||||
import { FloatingLabel } from "./FloatingLabel";
|
||||
import { useDebug } from "./SettingsProvider";
|
||||
import { injectCustomFog } from "../fogShader";
|
||||
|
|
@ -40,7 +40,7 @@ function InteriorTexture({
|
|||
const debugContext = useDebug();
|
||||
const debugMode = debugContext?.debugMode ?? false;
|
||||
const url = textureToUrl(materialName);
|
||||
const texture = useTexture(url, (texture) => setupColor(texture));
|
||||
const texture = useTexture(url, (texture) => setupTexture(texture));
|
||||
|
||||
// Check for self-illuminating flag in material userData
|
||||
// Note: The io_dif Blender add-on needs to be updated to export material flags
|
||||
|
|
@ -95,7 +95,6 @@ function InteriorTexture({
|
|||
key={materialKey}
|
||||
map={texture}
|
||||
toneMapped={false}
|
||||
// @ts-expect-error - defines exists on Material but R3F types don't expose it
|
||||
defines={defines}
|
||||
onBeforeCompile={onBeforeCompile}
|
||||
/>
|
||||
|
|
@ -114,9 +113,8 @@ function InteriorTexture({
|
|||
ref={lambertMaterialRef}
|
||||
key={materialKey}
|
||||
map={texture}
|
||||
lightMap={lightMap ?? undefined}
|
||||
lightMap={lightMap}
|
||||
toneMapped={false}
|
||||
// @ts-expect-error - defines exists on Material but R3F types don't expose it
|
||||
defines={defines}
|
||||
onBeforeCompile={onBeforeCompile}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -39,8 +39,10 @@ const sourceGroupNames: Record<string, string> = {
|
|||
"z_mappacks/CTF/TWL2-MapPack.vl2": "TWL2",
|
||||
"z_mappacks/CTF/TWL2-MapPackEDIT.vl2": "TWL2",
|
||||
"z_mappacks/TWL_T2arenaOfficialMaps.vl2": "Arena",
|
||||
"z_mappacks/xPack2.vl2": "xPack2",
|
||||
"z_mappacks/z_DMP2-V0.6.vl2": "DMP2 (Discord Map Pack)",
|
||||
"z_mappacks/zDMP-4.7.3DX.vl2": "DMP (Discord Map Pack)",
|
||||
"z_mappacks/zDMP-4.7.3DX-ServerOnly.vl2": "DMP (Discord Map Pack)",
|
||||
};
|
||||
|
||||
const dirGroupNames: Record<string, string> = {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { useMemo } from "react";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { Color, Vector3 } from "three";
|
||||
import type { TorqueObject } from "../torqueScript";
|
||||
import { getProperty } from "../mission";
|
||||
import { updateGlobalSunUniforms } from "../globalSunUniforms";
|
||||
|
||||
export function Sun({ object }: { object: TorqueObject }) {
|
||||
// Parse sun direction - points FROM sun TO scene
|
||||
|
|
@ -43,6 +44,16 @@ export function Sun({ object }: { object: TorqueObject }) {
|
|||
return new Color(r, g, b);
|
||||
}, [object]);
|
||||
|
||||
// Torque lighting check (terrLighting.cc): if light direction points up,
|
||||
// terrain surfaces with upward normals receive only ambient light.
|
||||
// direction.y < 0 means light pointing down (toward ground)
|
||||
const sunLightPointsDown = direction.y < 0;
|
||||
|
||||
// Update global uniform so terrain shader knows the light direction
|
||||
useEffect(() => {
|
||||
updateGlobalSunUniforms(sunLightPointsDown);
|
||||
}, [sunLightPointsDown]);
|
||||
|
||||
// Base lighting intensities - neutral baseline, each object type applies its own multipliers
|
||||
// See lightingConfig.ts for per-object-type adjustments
|
||||
const directionalIntensity = 1.0;
|
||||
|
|
@ -69,6 +80,7 @@ export function Sun({ object }: { object: TorqueObject }) {
|
|||
shadow-camera-far={12000}
|
||||
shadow-bias={-0.00001}
|
||||
shadow-normalBias={0.4}
|
||||
shadow-radius={2}
|
||||
/>
|
||||
{/* Ambient fill light - prevents pure black shadows */}
|
||||
<ambientLight color={ambient} intensity={ambientIntensity} />
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import {
|
|||
Vector3,
|
||||
} from "three";
|
||||
import type { TorqueObject } from "../torqueScript";
|
||||
import { getFloat, getInt, getPosition, getProperty } from "../mission";
|
||||
import { getFloat, getInt, getProperty } from "../mission";
|
||||
import { loadTerrain } from "../loaders";
|
||||
import { uint16ToFloat32 } from "../arrayUtils";
|
||||
import { setupMask } from "../textureUtils";
|
||||
|
|
@ -543,10 +543,13 @@ export const TerrainBlock = memo(function TerrainBlock({
|
|||
const visibleDistance = useVisibleDistance();
|
||||
const camera = useThree((state) => state.camera);
|
||||
|
||||
// Torque ignores the mission's terrain position and always uses a fixed formula:
|
||||
// setPosition(Point3F(-squareSize * (BlockSize >> 1), -squareSize * (BlockSize >> 1), 0));
|
||||
// where BlockSize = 256. See tribes2-engine/terrain/terrData.cc:679
|
||||
const basePosition = useMemo(() => {
|
||||
const [x, , z] = getPosition(object);
|
||||
return { x, z };
|
||||
}, [object]);
|
||||
const offset = -squareSize * (TERRAIN_SIZE / 2);
|
||||
return { x: offset, z: offset };
|
||||
}, [squareSize]);
|
||||
|
||||
const emptySquares = useMemo(() => {
|
||||
const value = getProperty(object, "emptySquares");
|
||||
|
|
|
|||
|
|
@ -11,14 +11,12 @@ import {
|
|||
terrainTextureToUrl,
|
||||
textureToUrl,
|
||||
} from "../loaders";
|
||||
import { setupColor } from "../textureUtils";
|
||||
import { setupTexture } from "../textureUtils";
|
||||
import { updateTerrainTextureShader } from "../terrainMaterial";
|
||||
import { useDebug } from "./SettingsProvider";
|
||||
import { injectCustomFog } from "../fogShader";
|
||||
import { globalFogUniforms } from "../globalFogUniforms";
|
||||
|
||||
const DEFAULT_SQUARE_SIZE = 8;
|
||||
|
||||
// Texture tiling factors for each terrain layer
|
||||
const TILING: Record<number, number> = {
|
||||
0: 32,
|
||||
|
|
@ -64,7 +62,7 @@ function BlendedTerrainTextures({
|
|||
const baseTextures = useTexture(
|
||||
textureNames.map((name) => terrainTextureToUrl(name)),
|
||||
(textures) => {
|
||||
textures.forEach((tex) => setupColor(tex));
|
||||
textures.forEach((tex) => setupTexture(tex));
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -76,7 +74,7 @@ function BlendedTerrainTextures({
|
|||
const detailTexture = useTexture(
|
||||
detailTextureUrl ?? FALLBACK_TEXTURE_URL,
|
||||
(tex) => {
|
||||
setupColor(tex);
|
||||
setupTexture(tex);
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -134,7 +132,6 @@ function BlendedTerrainTextures({
|
|||
map={displacementMap}
|
||||
depthWrite
|
||||
side={FrontSide}
|
||||
// @ts-expect-error - defines exists on Material but R3F types don't expose it
|
||||
defines={{ DEBUG_MODE: debugMode ? 1 : 0 }}
|
||||
onBeforeCompile={onBeforeCompile}
|
||||
/>
|
||||
|
|
@ -190,9 +187,10 @@ export const TerrainTile = memo(function TerrainTile({
|
|||
visible = true,
|
||||
}: TerrainTileProps) {
|
||||
const position = useMemo(() => {
|
||||
// Terrain geometry is centered at origin, but Tribes 2 terrain origin is at
|
||||
// corner. The engine always uses the default square size (8) for positioning.
|
||||
const geometryOffset = (DEFAULT_SQUARE_SIZE * 256) / 2;
|
||||
// Terrain geometry is centered at origin. Torque's terrain position formula
|
||||
// is -squareSize * 128, which equals -blockSize / 2. Since our geometry is
|
||||
// already centered, basePosition + geometryOffset cancels to 0 for single tiles.
|
||||
const geometryOffset = blockSize / 2;
|
||||
return [
|
||||
basePosition.x + tileX * blockSize + geometryOffset,
|
||||
0,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import {
|
|||
getRotation,
|
||||
getScale,
|
||||
} from "../mission";
|
||||
import { setupColor } from "../textureUtils";
|
||||
import { setupTexture } from "../textureUtils";
|
||||
import { createWaterMaterial } from "../waterMaterial";
|
||||
import { useDebug, useSettings } from "./SettingsProvider";
|
||||
import { usePositionTracker } from "./usePositionTracker";
|
||||
|
|
@ -63,7 +63,7 @@ export function WaterMaterial({
|
|||
attach?: string;
|
||||
}) {
|
||||
const url = textureToUrl(surfaceTexture);
|
||||
const texture = useTexture(url, (texture) => setupColor(texture));
|
||||
const texture = useTexture(url, (texture) => setupTexture(texture));
|
||||
|
||||
return (
|
||||
<meshStandardMaterial
|
||||
|
|
@ -309,7 +309,7 @@ const WaterReps = memo(function WaterReps({
|
|||
(textures) => {
|
||||
const texArray = Array.isArray(textures) ? textures : [textures];
|
||||
texArray.forEach((tex) => {
|
||||
setupColor(tex);
|
||||
setupTexture(tex);
|
||||
tex.colorSpace = NoColorSpace;
|
||||
tex.wrapS = RepeatWrapping;
|
||||
tex.wrapT = RepeatWrapping;
|
||||
|
|
|
|||
|
|
@ -29,8 +29,9 @@ interface IflAtlas {
|
|||
const atlasCache = new Map<string, IflAtlas>();
|
||||
|
||||
function createAtlas(textures: Texture[]): IflAtlas {
|
||||
const frameWidth = textures[0].image.width;
|
||||
const frameHeight = textures[0].image.height;
|
||||
const firstImage = textures[0].image as HTMLImageElement;
|
||||
const frameWidth = firstImage.width;
|
||||
const frameHeight = firstImage.height;
|
||||
const frameCount = textures.length;
|
||||
|
||||
// Arrange frames in a roughly square grid.
|
||||
|
|
@ -45,7 +46,7 @@ function createAtlas(textures: Texture[]): IflAtlas {
|
|||
textures.forEach((tex, i) => {
|
||||
const col = i % columns;
|
||||
const row = Math.floor(i / columns);
|
||||
ctx.drawImage(tex.image, col * frameWidth, row * frameHeight);
|
||||
ctx.drawImage(tex.image as CanvasImageSource, col * frameWidth, row * frameHeight);
|
||||
});
|
||||
|
||||
const texture = new CanvasTexture(canvas);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue