feat: improved lighting and grid

This commit is contained in:
TrèsAbhi committed 2024-01-02 13:31:34 -06:00
1 parent e65582a432
commit 3ea872c6a4
7 files changed
+174 -21

No files matched your search

+1
View File
@@ -26,6 +26,7 @@
"deburr",
"decalmask",
"diacriticless",
"donotremove",
"drei",
"dvpl",
"DVPLCRC",
Binary file not shown.
+2 -1
View File
@@ -532,7 +532,8 @@ if (allTargets || targets?.includes('tankModels')) {
// if (id !== 7297) continue; // 60tp
// if (id !== 1) continue; // t-34
// if (id !== 6753) continue; // type 71
if (id !== 5137) continue; // tiger ii
// if (id !== 5137) continue; // tiger ii
if (id !== 11633) continue; // tiger ii
// if (id !== 6225) continue; // fv215b
console.log(`Building model ${id} @ ${nation}/${tankIndex}`);
+34 -20
View File
@@ -20,16 +20,16 @@ import {
Theme,
Tooltip,
} from '@radix-ui/themes';
import { Environment, OrbitControls } from '@react-three/drei';
import { OrbitControls } from '@react-three/drei';
import { Canvas, ThreeEvent, useLoader } from '@react-three/fiber';
import { EffectComposer, SSAO } from '@react-three/postprocessing';
import { go } from 'fuzzysort';
import { debounce } from 'lodash';
import Link from 'next/link';
import { use, useEffect, useRef, useState } from 'react';
import { Group, Mesh, Vector3 } from 'three';
import { Color, Group, Mesh, Vector3 } from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { Flag } from '../../../../components/Flag';
import InfiniteGridHelper from '../../../../components/InfiniteGridHelper';
import { ModuleButtons } from '../../../../components/ModuleButton';
import PageWrapper from '../../../../components/PageWrapper';
import { asset } from '../../../../core/blitzkrieg/asset';
@@ -63,7 +63,7 @@ export default function Page({ params }: { params: { id: string } }) {
const [versusGun, setVersusGun] = useState(versusTurret.guns.at(-1)!);
const [versusTankTab, setVersusTankTab] = useState('search');
const canvas = useRef<HTMLCanvasElement>(null);
const gltf = useLoader(GLTFLoader, '/test/5137.glb');
const gltf = useLoader(GLTFLoader, `/test/${id}.glb`);
const turretOrigin = new Vector3(
tank.turretOrigin[0],
tank.turretOrigin[1],
@@ -135,32 +135,46 @@ export default function Page({ params }: { params: { id: string } }) {
<div style={{ height: '50vh', maxHeight: 576 }}>
<Canvas
shadows
ref={canvas}
onPointerDown={(event) => event.preventDefault()}
camera={{ fov: 20, position: [4, 0, -16] }}
camera={{ fov: 20 }}
>
<TankAlignment model={hullContainer} />
<OrbitControls enabled={orbitControlsEnabled} />
<gridHelper />
<InfiniteGridHelper
position={[0, 0, 0]}
axes="xzy"
size1={1 / 5}
size2={1}
distance={20}
color={new Color('#ffffff')}
/>
<InfiniteGridHelper
position={[0, 0, 0]}
axes="xzy"
size1={0}
size2={100}
distance={25}
color={new Color('red')}
/>
{/* I really like apartment, dawn, and sunset */}
<Environment preset="apartment" />
<EffectComposer enabled={true}>
<SSAO
worldDistanceFalloff={1.0}
worldDistanceThreshold={Infinity}
worldProximityFalloff={0.5}
worldProximityThreshold={8.0}
samples={10}
radius={0.25}
intensity={10}
/>
</EffectComposer>
<directionalLight
position={[1, 1, -1]}
intensity={1}
castShadow
/>
<directionalLight
position={[-1, 1, 1]}
intensity={2}
castShadow
/>
<ambientLight intensity={0.25} />
<group
ref={hullContainer}
rotation={[0 /*-Math.PI / 2*/, 0, hullRotation]}
rotation={[-Math.PI / 2, 0, hullRotation]}
>
{gltf.scene.children[0].children.map((child) => {
const isHull = child.name === 'hull';
+79
View File
@@ -0,0 +1,79 @@
import { MeshProps } from '@react-three/fiber';
import { forwardRef } from 'react';
import { DoubleSide, Mesh } from 'three';
interface InfiniteGridHelperProps extends MeshProps {
size1?: number;
size2?: number;
color?: THREE.Color;
distance?: number;
axes?: string;
}
/**
* Thanks, Fyrestar, for [THREE.InfiniteGridHelper](https://github.com/Fyrestar/THREE.InfiniteGridHelper/)!
*/
const InfiniteGridHelper = forwardRef<Mesh, InfiniteGridHelperProps>(
({ size1, size2, color, axes = 'xzy', distance, ...props }, ref) => {
const planeAxes = axes.slice(0, 2);
return (
<mesh {...props} ref={ref} frustumCulled={false}>
<shaderMaterial
args={[
{
side: DoubleSide,
uniforms: {
uSize1: { value: size1 },
uSize2: { value: size2 },
uColor: { value: color },
uDistance: { value: distance },
},
extensions: { derivatives: true },
transparent: true,
vertexShader: `
varying vec3 worldPosition;
uniform float uDistance;
void main() {
vec3 pos = position.${axes} * uDistance;
worldPosition = pos;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
`,
fragmentShader: `
varying vec3 worldPosition;
uniform float uSize1;
uniform float uSize2;
uniform vec3 uColor;
uniform float uDistance;
vec2 origin = vec2(0.0, 0.0);
float getGrid(float size) {
vec2 r = worldPosition.${planeAxes} / size;
vec2 grid = abs(fract(r - 0.5) - 0.5) / fwidth(r);
float line = min(grid.x, grid.y);
return 1.0 - min(line, 1.0);
}
void main() {
float d = 1.0 - min(distance(origin, worldPosition.${planeAxes}) / uDistance, 1.0);
float g1 = getGrid(uSize1);
float g2 = getGrid(uSize2);
gl_FragColor = vec4(uColor.rgb, mix(g2, g1, g1) * pow(d, 10.0));
gl_FragColor.a = mix(0.5 * gl_FragColor.a, gl_FragColor.a, g2);
if ( gl_FragColor.a <= 0.0 ) discard;
}
`,
},
]}
/>
<planeGeometry />
</mesh>
);
},
);
export default InfiniteGridHelper;
+9
View File
@@ -14,6 +14,10 @@ import { ScgStream, vertexAttributeVectorSizes } from '../streams/scg';
import { VertexAttribute } from '../streams/scpg';
import { readDVPLFile } from './readDVPLFile';
BigInt.prototype.toJSON = function () {
return this.toString();
};
const MAX_FLOAT32 = 2 ** 127 * (2 - 2 ** -23);
const vertexAttributeGLTFName: Partial<Record<VertexAttribute, string>> = {
@@ -168,9 +172,14 @@ export async function extractModel(
case 'NewSlotComponent':
case 'StateSwitcherComponent':
case 'CustomPropertiesComponent':
case 'ActionComponent':
case 'ParticleEffectComponent':
case 'SlotComponent':
case 'TankElementComponent':
break;
// console.log(JSON.stringify(component, null, 2));
case 'TransformComponent': {
const translation = new Vector3();
const rotation = new Quaternion();
+49
View File
@@ -183,6 +183,55 @@ export type Component =
'cpc.properties.archive': {
'editor.donotremove': number;
};
}
| ({
'comp.typename': 'ActionComponent';
'ac.actionCount': number;
} & Record<
string, // 0000, 0001, ...
{
'act.delay': number;
'act.delayVariation': number;
'act.entityName': string;
'act.event': number;
'act.eventToTrigger': string;
'act.motionFrameTime': number;
'act.motionSpeed': number;
'act.stateActivated': number;
'act.stopAfterNRepeats': number;
'act.stopWhenEmpty': boolean;
'act.switchIndex': number;
'act.type': number;
'act.userEventId': string;
}
>)
| {
'comp.typename': 'ParticleEffectComponent';
'pe.clearOnRestart': boolean;
'pe.effectDuration': number;
'pe.emitters': {
'##name': string;
'emitter.data': {
'emitter.id': `${number}`;
'emitter.quality': string;
}[];
'emitter.position': Vector3Tuple;
'emitter.rotation': Vector4Tuple;
'emitter.scale': Vector3Tuple;
}[];
'pe.inheritScale': boolean;
'pe.nestedEmitters': boolean;
'pe.repeatsCount': number;
'pe.startFromTime': number;
'pe.stopWhenEmpty': boolean;
'pe.version': number;
'ro.flags': number;
}
| {
'comp.typename': 'TankElementComponent';
isDestructible: boolean;
shouldCastShadow: boolean;
shouldGenerateSilhouette: boolean;
};
interface SceneComponents {