From 14835a76f38d0c721d50bd381be2e657d8c2c005 Mon Sep 17 00:00:00 2001 From: bananu7 Date: Mon, 13 Mar 2023 22:44:48 +0100 Subject: [PATCH 01/22] Added a prototype of models loaded from file --- packages/client/src/gfx/FileModel.tsx | 44 +++++++++++++++++++++++++++ packages/client/src/gfx/Unit3D.tsx | 28 +++++++++++------ 2 files changed, 62 insertions(+), 10 deletions(-) create mode 100644 packages/client/src/gfx/FileModel.tsx diff --git a/packages/client/src/gfx/FileModel.tsx b/packages/client/src/gfx/FileModel.tsx new file mode 100644 index 0000000..51e7249 --- /dev/null +++ b/packages/client/src/gfx/FileModel.tsx @@ -0,0 +1,44 @@ +import { useLoader } from '@react-three/fiber' +import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' + +import * as THREE from 'three'; +import { useRef, useEffect, useState, useLayoutEffect } from 'react' + +export type FileModelProps = { + position: {x: number, y: number}, + path: string, + accentColor: THREE.ColorRepresentation, +} + +export function FileModel(props: FileModelProps) { + const gltf = useLoader(GLTFLoader, props.path) + + useEffect(() => { + (gltf.materials['bricksDark(Clone)'] as THREE.MeshStandardMaterial).color.set("#bb3"); + (gltf.materials['stone(Clone)'] as THREE.MeshStandardMaterial).color.set("#ddd"); + //console.log(gltf); + }, []); + + const [dialScene, setDialScene] = useState(undefined); + + if (!dialScene) { + const dialScene = gltf.scene.clone(true); + setDialScene(dialScene); + } + + const accentMaterial = ((gltf.nodes.mesh_0_2 as THREE.Mesh).material as THREE.Material).clone(); + (accentMaterial as THREE.MeshStandardMaterial).color.set(props.accentColor); + + return ( + + {/**/} + + + + + ) +} \ No newline at end of file diff --git a/packages/client/src/gfx/Unit3D.tsx b/packages/client/src/gfx/Unit3D.tsx index e1e4094..01f8ee0 100644 --- a/packages/client/src/gfx/Unit3D.tsx +++ b/packages/client/src/gfx/Unit3D.tsx @@ -9,14 +9,12 @@ import { import * as THREE from 'three'; -//import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' -//import { SkeletonUtils } from "three/examples/jsm/utils/SkeletonUtils" - import { Board, Unit, GameMap, UnitId, Position, UnitState } from 'server/src/types' import { SelectionCircle } from './SelectionCircle' import { Line3D } from './Line3D' import { Map3D, Box } from './Map3D' import { ThreeCache } from './ThreeCache' +import { FileModel } from './FileModel' import { Horizon } from '../debug/Horizon' @@ -93,7 +91,7 @@ export function Unit3D(props: Unit3DProps) { // TODO proper unit catalog const isBuilding = props.unit.kind === 'Base' || props.unit.kind === 'Barracks'; const unitSize = isBuilding ? 4 : 1; - const selectorSize = isBuilding ? 3 : 1; + const selectorSize = isBuilding ? 5 : 1; // smoothing const unitGroupRef = useRef(null); @@ -198,12 +196,22 @@ export function Unit3D(props: Unit3DProps) { 0.01 || smoothingVelocity.y > 0.01} /> } - + { + isBuilding ? + + : + + } + From f5e8562218bb63ffd16c0e8fca20ba1d0d2c5226 Mon Sep 17 00:00:00 2001 From: bananu7 Date: Mon, 13 Mar 2023 22:44:58 +0100 Subject: [PATCH 02/22] Increased ambient light intensity --- packages/client/src/gfx/View3D.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/client/src/gfx/View3D.tsx b/packages/client/src/gfx/View3D.tsx index c84a7b5..8ec0344 100644 --- a/packages/client/src/gfx/View3D.tsx +++ b/packages/client/src/gfx/View3D.tsx @@ -87,7 +87,7 @@ function MapSpotlight() { angle={0.16} distance={0} decay={0} - intensity={6} + intensity={4} color={0xffffff} castShadow @@ -136,7 +136,7 @@ export function View3D(props: Props) { > - + {props.children} From 5a878e4f6474d7843369a8a676f30d2bfc4ee588 Mon Sep 17 00:00:00 2001 From: bananu7 Date: Mon, 13 Mar 2023 22:45:10 +0100 Subject: [PATCH 03/22] Fixed selection circle params --- packages/client/src/gfx/SelectionCircle.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/client/src/gfx/SelectionCircle.tsx b/packages/client/src/gfx/SelectionCircle.tsx index 67c8080..ef9a040 100644 --- a/packages/client/src/gfx/SelectionCircle.tsx +++ b/packages/client/src/gfx/SelectionCircle.tsx @@ -9,8 +9,6 @@ const friendlyMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); -const ringGeometry = new THREE.RingGeometry(1, 1.1, 32); - export function SelectionCircle(props: { size: number, enemy?: boolean }) { const innerRadius = props.size; const outerRadius = props.size * 1.1; @@ -30,8 +28,8 @@ export function SelectionCircle(props: { size: number, enemy?: boolean }) { name="SelectionRing" position={[0, 0, 0]} material={props.enemy ? enemyMaterial : friendlyMaterial} - geometry={ringGeometry} > + ); } \ No newline at end of file From 00796472e7defc4f0ce98c12678c5c9035617601 Mon Sep 17 00:00:00 2001 From: bananu7 Date: Mon, 13 Mar 2023 23:19:28 +0100 Subject: [PATCH 04/22] Made the map a bit more visually appealing --- packages/client/src/gfx/Map3D.tsx | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/client/src/gfx/Map3D.tsx b/packages/client/src/gfx/Map3D.tsx index ad6f45a..aea6a89 100644 --- a/packages/client/src/gfx/Map3D.tsx +++ b/packages/client/src/gfx/Map3D.tsx @@ -75,11 +75,24 @@ export function Map3D(props: Map3DProps) { const isPassable = props.map.tiles[ix] === 0; const color = isPassable ? 0x11aa11 : 0x888888; - const height = isPassable ? 0 : 0.8; + const height = (isPassable ? 0 : 0.8 + Math.random() * 0.7) - 0.01; // TODO quick hack - mat4Pos.makeTranslation(x * xSize, height, y * ySize); + mat4Pos.makeTranslation(x * xSize, height, y * ySize); // TODO -1 to move them down because of their height vec3Color.set(color); + // TODO - this is just a quick and dirty solution + if (isPassable) { + const f = 0.06; + vec3Color.r += (Math.random() - 0.5) * f; + vec3Color.g += (Math.random() - 0.5) * f; + vec3Color.b += (Math.random() - 0.5) * f; + } else { + const d = (Math.random() - 0.5) * 0.1; + vec3Color.r += d; + vec3Color.g += d; + vec3Color.b += d; + } + ref.current.setMatrixAt(ix, mat4Pos); ref.current.setColorAt(ix, vec3Color); } @@ -114,7 +127,7 @@ export function Map3D(props: Map3DProps) { receiveShadow > {/**/} - + From b7ec4a98b78590f59c7e7a8252173be76a8edef5 Mon Sep 17 00:00:00 2001 From: bananu7 Date: Tue, 14 Mar 2023 19:05:19 +0100 Subject: [PATCH 05/22] Improved FileModel to be a more flexible with real models --- packages/client/src/gfx/FileModel.tsx | 26 +++++++++++++++++--------- packages/client/src/gfx/Unit3D.tsx | 9 +++++++-- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/packages/client/src/gfx/FileModel.tsx b/packages/client/src/gfx/FileModel.tsx index 51e7249..9324e34 100644 --- a/packages/client/src/gfx/FileModel.tsx +++ b/packages/client/src/gfx/FileModel.tsx @@ -14,8 +14,6 @@ export function FileModel(props: FileModelProps) { const gltf = useLoader(GLTFLoader, props.path) useEffect(() => { - (gltf.materials['bricksDark(Clone)'] as THREE.MeshStandardMaterial).color.set("#bb3"); - (gltf.materials['stone(Clone)'] as THREE.MeshStandardMaterial).color.set("#ddd"); //console.log(gltf); }, []); @@ -26,19 +24,29 @@ export function FileModel(props: FileModelProps) { setDialScene(dialScene); } - const accentMaterial = ((gltf.nodes.mesh_0_2 as THREE.Mesh).material as THREE.Material).clone(); - (accentMaterial as THREE.MeshStandardMaterial).color.set(props.accentColor); + const origAccentMaterial = gltf.materials['accent']; + if (!origAccentMaterial || !(origAccentMaterial instanceof THREE.MeshStandardMaterial)) + throw new Error ("No accent material in FileModel"); + const accentMaterial = origAccentMaterial.clone(); + accentMaterial.color.set(props.accentColor); + + const meshes = []; + for (const n in gltf.nodes) { + const mesh = (gltf.nodes[n] as THREE.Mesh); + meshes.push(); + } return ( - {/**/} - - - + {meshes} ) } \ No newline at end of file diff --git a/packages/client/src/gfx/Unit3D.tsx b/packages/client/src/gfx/Unit3D.tsx index 01f8ee0..cdda62b 100644 --- a/packages/client/src/gfx/Unit3D.tsx +++ b/packages/client/src/gfx/Unit3D.tsx @@ -204,12 +204,17 @@ export function Unit3D(props: Unit3DProps) { accentColor={color} /> : - + /* + />*/ } From 32e71dbfdcd3b626a5b77dd99a88427c5eb6eedb Mon Sep 17 00:00:00 2001 From: bananu7 Date: Tue, 14 Mar 2023 19:06:57 +0100 Subject: [PATCH 06/22] Do not commit GLTF models --- packages/client/public/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 packages/client/public/.gitignore diff --git a/packages/client/public/.gitignore b/packages/client/public/.gitignore new file mode 100644 index 0000000..bdc9933 --- /dev/null +++ b/packages/client/public/.gitignore @@ -0,0 +1 @@ +*.glb \ No newline at end of file From 6b1b0252ce1697b3f31734f688efa835c75fa9e8 Mon Sep 17 00:00:00 2001 From: bananu7 Date: Tue, 14 Mar 2023 20:11:23 +0100 Subject: [PATCH 07/22] Allow properly loading other models --- packages/client/src/gfx/FileModel.tsx | 18 +++++++++----- packages/client/src/gfx/Unit3D.tsx | 34 ++++++++++----------------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/packages/client/src/gfx/FileModel.tsx b/packages/client/src/gfx/FileModel.tsx index 9324e34..1a64770 100644 --- a/packages/client/src/gfx/FileModel.tsx +++ b/packages/client/src/gfx/FileModel.tsx @@ -25,25 +25,31 @@ export function FileModel(props: FileModelProps) { } const origAccentMaterial = gltf.materials['accent']; - if (!origAccentMaterial || !(origAccentMaterial instanceof THREE.MeshStandardMaterial)) - throw new Error ("No accent material in FileModel"); - const accentMaterial = origAccentMaterial.clone(); - accentMaterial.color.set(props.accentColor); + const accentMaterial = (() => { + if (!origAccentMaterial || !(origAccentMaterial instanceof THREE.MeshStandardMaterial)) + return undefined; + const accentMaterial = origAccentMaterial.clone(); + accentMaterial.color.set(props.accentColor); + return accentMaterial; + })(); const meshes = []; for (const n in gltf.nodes) { const mesh = (gltf.nodes[n] as THREE.Mesh); + const material = mesh.material === origAccentMaterial ? accentMaterial : mesh.material; + + // TODO pull rotation and scaling info meshes.push(); } return ( {meshes} diff --git a/packages/client/src/gfx/Unit3D.tsx b/packages/client/src/gfx/Unit3D.tsx index cdda62b..a6ee587 100644 --- a/packages/client/src/gfx/Unit3D.tsx +++ b/packages/client/src/gfx/Unit3D.tsx @@ -93,6 +93,14 @@ export function Unit3D(props: Unit3DProps) { const unitSize = isBuilding ? 4 : 1; const selectorSize = isBuilding ? 5 : 1; + const modelPath = + isBuilding ? + '/public/castle_1.glb' + : props.unit.owner !== 0 ? + '/public/peasant_1.glb' + : '/public/gold_node.glb' + ; + // smoothing const unitGroupRef = useRef(null); const softSnapVelocity = @@ -196,27 +204,11 @@ export function Unit3D(props: Unit3DProps) { 0.01 || smoothingVelocity.y > 0.01} /> } - { - isBuilding ? - - : - - /**/ - } - + From cd1380d2ee2773f2f7689d42f4be1a87fe6cebe5 Mon Sep 17 00:00:00 2001 From: bananu7 Date: Wed, 15 Mar 2023 20:39:46 +0100 Subject: [PATCH 08/22] Working animation with one hardcoded model --- packages/client/src/gfx/FileModel.tsx | 238 +++++++++++++++++++++++--- packages/client/src/gfx/Unit3D.tsx | 10 +- 2 files changed, 217 insertions(+), 31 deletions(-) diff --git a/packages/client/src/gfx/FileModel.tsx b/packages/client/src/gfx/FileModel.tsx index 1a64770..aa9b191 100644 --- a/packages/client/src/gfx/FileModel.tsx +++ b/packages/client/src/gfx/FileModel.tsx @@ -1,29 +1,21 @@ -import { useLoader } from '@react-three/fiber' +import { useLoader, useFrame } from '@react-three/fiber' import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' import * as THREE from 'three'; -import { useRef, useEffect, useState, useLayoutEffect } from 'react' +import { useRef, useEffect, useState, useLayoutEffect, memo } from 'react' export type FileModelProps = { - position: {x: number, y: number}, path: string, accentColor: THREE.ColorRepresentation, } -export function FileModel(props: FileModelProps) { +function FileModel_(props: FileModelProps) { const gltf = useLoader(GLTFLoader, props.path) useEffect(() => { - //console.log(gltf); + console.log(gltf); }, []); - const [dialScene, setDialScene] = useState(undefined); - - if (!dialScene) { - const dialScene = gltf.scene.clone(true); - setDialScene(dialScene); - } - const origAccentMaterial = gltf.materials['accent']; const accentMaterial = (() => { if (!origAccentMaterial || !(origAccentMaterial instanceof THREE.MeshStandardMaterial)) @@ -33,26 +25,220 @@ export function FileModel(props: FileModelProps) { return accentMaterial; })(); - const meshes = []; + const nodes = []; for (const n in gltf.nodes) { - const mesh = (gltf.nodes[n] as THREE.Mesh); - const material = mesh.material === origAccentMaterial ? accentMaterial : mesh.material; - - // TODO pull rotation and scaling info - meshes.push(); + const node = gltf.nodes[n]; + + if (node instanceof THREE.SkinnedMesh) { + const material = node.material === origAccentMaterial ? accentMaterial : node.material; + + // TODO pull rotation and scaling info + nodes.push(); + } + else if (node instanceof THREE.Mesh) { + const material = node.material === origAccentMaterial ? accentMaterial : node.material; + + // TODO pull rotation and scaling info + nodes.push(); + } else { + nodes.push(); + } } + const ref = useRef(null); + + let mixer: THREE.AnimationMixer | null = null; + useFrame((state, delta) => { + if(!ref.current) + return; + + if(gltf.animations.length === 0) { + return; + } + + if (!mixer) { + console.log("new mixer") + mixer = new THREE.AnimationMixer(ref.current); + + //mixer.clipAction(gltf.animations[0]).play(); + //console.log("playing") + } + + //mixer.update(delta); + }); + return ( - {meshes} + {nodes} ) -} \ No newline at end of file +} + +export const FileModel = memo(FileModel_); + + +function PeasantModel_(props: FileModelProps) { + const gltf = useLoader(GLTFLoader, props.path) + + useEffect(() => { + console.log(gltf); + }, []); + + const origAccentMaterial = gltf.materials['accent']; + const accentMaterial = (() => { + if (!origAccentMaterial || !(origAccentMaterial instanceof THREE.MeshStandardMaterial)) + return undefined; + const accentMaterial = origAccentMaterial.clone(); + accentMaterial.color.set(props.accentColor); + return accentMaterial; + })(); + + const nodes = gltf.nodes as any; + + const ref = useRef(null); + + let mixer: THREE.AnimationMixer | null = null; + useFrame((state, delta) => { + if(!ref.current) + return; + + if(gltf.animations.length === 0) { + return; + } + + if (!mixer) { + console.log("new mixer") + mixer = new THREE.AnimationMixer(ref.current); + + mixer.clipAction(gltf.animations[0]).play(); + //console.log("playing") + } + + mixer.update(delta); + }); + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} + +export const PeasantModel = memo(PeasantModel_); \ No newline at end of file diff --git a/packages/client/src/gfx/Unit3D.tsx b/packages/client/src/gfx/Unit3D.tsx index a6ee587..92d032f 100644 --- a/packages/client/src/gfx/Unit3D.tsx +++ b/packages/client/src/gfx/Unit3D.tsx @@ -14,7 +14,7 @@ import { SelectionCircle } from './SelectionCircle' import { Line3D } from './Line3D' import { Map3D, Box } from './Map3D' import { ThreeCache } from './ThreeCache' -import { FileModel } from './FileModel' +import { FileModel, PeasantModel } from './FileModel' import { Horizon } from '../debug/Horizon' @@ -204,11 +204,11 @@ export function Unit3D(props: Unit3DProps) { 0.01 || smoothingVelocity.y > 0.01} /> } - + {/* + + />*/} From 744f891ff94e77ca972516d65b60eadfc0100255 Mon Sep 17 00:00:00 2001 From: bananu7 Date: Wed, 15 Mar 2023 21:31:58 +0100 Subject: [PATCH 09/22] In this state both work but both show just one model --- packages/client/src/gfx/FileModel.tsx | 103 +++++++++++++++----------- packages/client/src/gfx/Unit3D.tsx | 3 +- 2 files changed, 61 insertions(+), 45 deletions(-) diff --git a/packages/client/src/gfx/FileModel.tsx b/packages/client/src/gfx/FileModel.tsx index aa9b191..29cf9d3 100644 --- a/packages/client/src/gfx/FileModel.tsx +++ b/packages/client/src/gfx/FileModel.tsx @@ -32,10 +32,12 @@ function FileModel_(props: FileModelProps) { if (node instanceof THREE.SkinnedMesh) { const material = node.material === origAccentMaterial ? accentMaterial : node.material; + console.log(`adding skinned mesh ${n}`) // TODO pull rotation and scaling info nodes.push(); - } else { - nodes.push(); + } else if (node instanceof THREE.Bone) { + console.log(`adding primitive ${n}`) + const allowednames = [ + "Spine", + "Left_Hip", + "Right_Hip", + "neutral_bone", + "neutral_bone_1", + "neutral_bone_2", + "neutral_bone_3", + "neutral_bone_4", + "neutral_bone_5" + ]; + if (allowednames.indexOf(n) !== -1) + nodes.push(); } } @@ -69,13 +86,14 @@ function FileModel_(props: FileModelProps) { if (!mixer) { console.log("new mixer") + console.log(state); mixer = new THREE.AnimationMixer(ref.current); - //mixer.clipAction(gltf.animations[0]).play(); + mixer.clipAction(gltf.animations[0]).play(); //console.log("playing") } - //mixer.update(delta); + mixer.update(delta); }); return ( @@ -84,6 +102,15 @@ function FileModel_(props: FileModelProps) { rotation={[0, 0, 0]} > {nodes} + {/*} + + + + + + + + */} ) } @@ -95,7 +122,7 @@ function PeasantModel_(props: FileModelProps) { const gltf = useLoader(GLTFLoader, props.path) useEffect(() => { - console.log(gltf); + //console.log(gltf); }, []); const origAccentMaterial = gltf.materials['accent']; @@ -122,6 +149,7 @@ function PeasantModel_(props: FileModelProps) { if (!mixer) { console.log("new mixer") + console.log(state); mixer = new THREE.AnimationMixer(ref.current); mixer.clipAction(gltf.animations[0]).play(); @@ -132,14 +160,11 @@ function PeasantModel_(props: FileModelProps) { }); return ( - - - + > @@ -161,33 +186,30 @@ function PeasantModel_(props: FileModelProps) { material={nodes.arm_right.material} skeleton={nodes.arm_right.skeleton} /> - - - - - - - + + + + - - - - - - - ) } diff --git a/packages/client/src/gfx/Unit3D.tsx b/packages/client/src/gfx/Unit3D.tsx index 92d032f..b52bd65 100644 --- a/packages/client/src/gfx/Unit3D.tsx +++ b/packages/client/src/gfx/Unit3D.tsx @@ -176,7 +176,8 @@ export function Unit3D(props: Unit3DProps) { } { /* those things are always world axis oriented */} From ba0c93a918ce3d699ebf2ddfaade97c163878923 Mon Sep 17 00:00:00 2001 From: bananu7 Date: Wed, 15 Mar 2023 21:57:26 +0100 Subject: [PATCH 10/22] Simple clone works best --- packages/client/src/gfx/FileModel.tsx | 216 ++------------------------ packages/client/src/gfx/Unit3D.tsx | 7 +- 2 files changed, 11 insertions(+), 212 deletions(-) diff --git a/packages/client/src/gfx/FileModel.tsx b/packages/client/src/gfx/FileModel.tsx index 29cf9d3..df43905 100644 --- a/packages/client/src/gfx/FileModel.tsx +++ b/packages/client/src/gfx/FileModel.tsx @@ -2,6 +2,7 @@ import { useLoader, useFrame } from '@react-three/fiber' import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' import * as THREE from 'three'; +import * as SkeletonUtils from 'three/examples/jsm/utils/SkeletonUtils'; import { useRef, useEffect, useState, useLayoutEffect, memo } from 'react' export type FileModelProps = { @@ -12,10 +13,6 @@ export type FileModelProps = { function FileModel_(props: FileModelProps) { const gltf = useLoader(GLTFLoader, props.path) - useEffect(() => { - console.log(gltf); - }, []); - const origAccentMaterial = gltf.materials['accent']; const accentMaterial = (() => { if (!origAccentMaterial || !(origAccentMaterial instanceof THREE.MeshStandardMaterial)) @@ -25,54 +22,6 @@ function FileModel_(props: FileModelProps) { return accentMaterial; })(); - const nodes = []; - for (const n in gltf.nodes) { - const node = gltf.nodes[n]; - - if (node instanceof THREE.SkinnedMesh) { - const material = node.material === origAccentMaterial ? accentMaterial : node.material; - - console.log(`adding skinned mesh ${n}`) - // TODO pull rotation and scaling info - nodes.push(); - } - else if (node instanceof THREE.Mesh) { - const material = node.material === origAccentMaterial ? accentMaterial : node.material; - - console.log(`adding mesh ${n}`) - // TODO pull rotation and scaling info - nodes.push(); - } else if (node instanceof THREE.Bone) { - console.log(`adding primitive ${n}`) - const allowednames = [ - "Spine", - "Left_Hip", - "Right_Hip", - "neutral_bone", - "neutral_bone_1", - "neutral_bone_2", - "neutral_bone_3", - "neutral_bone_4", - "neutral_bone_5" - ]; - if (allowednames.indexOf(n) !== -1) - nodes.push(); - } - } - const ref = useRef(null); let mixer: THREE.AnimationMixer | null = null; @@ -85,175 +34,30 @@ function FileModel_(props: FileModelProps) { } if (!mixer) { - console.log("new mixer") - console.log(state); mixer = new THREE.AnimationMixer(ref.current); mixer.clipAction(gltf.animations[0]).play(); - //console.log("playing") } mixer.update(delta); }); + const clonedObject = SkeletonUtils.clone(gltf.scene); + clonedObject.traverse(o => { + if (o instanceof THREE.Mesh) { + if (o.material.name === "accent") + o.material = accentMaterial; + } + }); + return ( - {nodes} - {/*} - - - - - - - - */} + ) } export const FileModel = memo(FileModel_); - - -function PeasantModel_(props: FileModelProps) { - const gltf = useLoader(GLTFLoader, props.path) - - useEffect(() => { - //console.log(gltf); - }, []); - - const origAccentMaterial = gltf.materials['accent']; - const accentMaterial = (() => { - if (!origAccentMaterial || !(origAccentMaterial instanceof THREE.MeshStandardMaterial)) - return undefined; - const accentMaterial = origAccentMaterial.clone(); - accentMaterial.color.set(props.accentColor); - return accentMaterial; - })(); - - const nodes = gltf.nodes as any; - - const ref = useRef(null); - - let mixer: THREE.AnimationMixer | null = null; - useFrame((state, delta) => { - if(!ref.current) - return; - - if(gltf.animations.length === 0) { - return; - } - - if (!mixer) { - console.log("new mixer") - console.log(state); - mixer = new THREE.AnimationMixer(ref.current); - - mixer.clipAction(gltf.animations[0]).play(); - //console.log("playing") - } - - mixer.update(delta); - }); - - return ( - - - - - - - - - - - - - - - - - - - - - - - - - ) -} - -export const PeasantModel = memo(PeasantModel_); \ No newline at end of file diff --git a/packages/client/src/gfx/Unit3D.tsx b/packages/client/src/gfx/Unit3D.tsx index b52bd65..6d9013b 100644 --- a/packages/client/src/gfx/Unit3D.tsx +++ b/packages/client/src/gfx/Unit3D.tsx @@ -177,7 +177,6 @@ export function Unit3D(props: Unit3DProps) { { /* those things are always world axis oriented */} @@ -205,11 +204,7 @@ export function Unit3D(props: Unit3DProps) { 0.01 || smoothingVelocity.y > 0.01} /> } - - {/**/} + From 48df167963145118dc0ece27ff2ab817c934125d Mon Sep 17 00:00:00 2001 From: bananu7 Date: Wed, 15 Mar 2023 22:10:15 +0100 Subject: [PATCH 11/22] Animations now dynamically update only when moving --- packages/client/src/gfx/FileModel.tsx | 4 +++- packages/client/src/gfx/Unit3D.tsx | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/client/src/gfx/FileModel.tsx b/packages/client/src/gfx/FileModel.tsx index df43905..98c0589 100644 --- a/packages/client/src/gfx/FileModel.tsx +++ b/packages/client/src/gfx/FileModel.tsx @@ -8,6 +8,7 @@ import { useRef, useEffect, useState, useLayoutEffect, memo } from 'react' export type FileModelProps = { path: string, accentColor: THREE.ColorRepresentation, + animate: boolean, // TODO which anims how fast etc } function FileModel_(props: FileModelProps) { @@ -39,7 +40,8 @@ function FileModel_(props: FileModelProps) { mixer.clipAction(gltf.animations[0]).play(); } - mixer.update(delta); + if (props.animate) + mixer.update(delta*5); }); const clonedObject = SkeletonUtils.clone(gltf.scene); diff --git a/packages/client/src/gfx/Unit3D.tsx b/packages/client/src/gfx/Unit3D.tsx index 6d9013b..874daef 100644 --- a/packages/client/src/gfx/Unit3D.tsx +++ b/packages/client/src/gfx/Unit3D.tsx @@ -168,6 +168,8 @@ export function Unit3D(props: Unit3DProps) { return new THREE.Vector3(a.x, 1, a.y); }); + const animate = props.unit.status === 'Moving'; + return ( { debugFlags.showPaths && @@ -204,7 +206,7 @@ export function Unit3D(props: Unit3DProps) { 0.01 || smoothingVelocity.y > 0.01} /> } - + From 94463a127987609b729b27053cf67673e441ccac Mon Sep 17 00:00:00 2001 From: bananu7 Date: Wed, 15 Mar 2023 22:23:59 +0100 Subject: [PATCH 12/22] Shadow bias to avoid banding when receiveShadows is enabled --- packages/client/src/gfx/FileModel.tsx | 2 ++ packages/client/src/gfx/Unit3D.tsx | 2 +- packages/client/src/gfx/View3D.tsx | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/client/src/gfx/FileModel.tsx b/packages/client/src/gfx/FileModel.tsx index 98c0589..211dbe5 100644 --- a/packages/client/src/gfx/FileModel.tsx +++ b/packages/client/src/gfx/FileModel.tsx @@ -49,6 +49,8 @@ function FileModel_(props: FileModelProps) { if (o instanceof THREE.Mesh) { if (o.material.name === "accent") o.material = accentMaterial; + o.castShadow = true; + o.receiveShadow = true; } }); diff --git a/packages/client/src/gfx/Unit3D.tsx b/packages/client/src/gfx/Unit3D.tsx index 874daef..0b859a1 100644 --- a/packages/client/src/gfx/Unit3D.tsx +++ b/packages/client/src/gfx/Unit3D.tsx @@ -178,7 +178,7 @@ export function Unit3D(props: Unit3DProps) { } { /* those things are always world axis oriented */} diff --git a/packages/client/src/gfx/View3D.tsx b/packages/client/src/gfx/View3D.tsx index 8ec0344..42277cf 100644 --- a/packages/client/src/gfx/View3D.tsx +++ b/packages/client/src/gfx/View3D.tsx @@ -95,6 +95,7 @@ function MapSpotlight() { shadow-camera-far={500} shadow-mapSize-height={1024} shadow-mapSize-width={1024} + shadow-bias={-0.002} /> ) From 22155fbd6ec09bdcfde690fc7e214bb0bca92669 Mon Sep 17 00:00:00 2001 From: bananu7 Date: Wed, 15 Mar 2023 23:56:07 +0100 Subject: [PATCH 13/22] Changed camera FOV to the SC2 value --- packages/client/src/gfx/View3D.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/gfx/View3D.tsx b/packages/client/src/gfx/View3D.tsx index 42277cf..b9aac6e 100644 --- a/packages/client/src/gfx/View3D.tsx +++ b/packages/client/src/gfx/View3D.tsx @@ -124,7 +124,7 @@ export function View3D(props: Props) {
Date: Sat, 18 Mar 2023 10:22:55 +0100 Subject: [PATCH 14/22] Removed whitespace --- packages/client/src/gfx/FileModel.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/client/src/gfx/FileModel.tsx b/packages/client/src/gfx/FileModel.tsx index 211dbe5..688ee00 100644 --- a/packages/client/src/gfx/FileModel.tsx +++ b/packages/client/src/gfx/FileModel.tsx @@ -36,7 +36,6 @@ function FileModel_(props: FileModelProps) { if (!mixer) { mixer = new THREE.AnimationMixer(ref.current); - mixer.clipAction(gltf.animations[0]).play(); } From fc964c93997e331af230b2c9a432b54c2dfa36b8 Mon Sep 17 00:00:00 2001 From: bananu7 Date: Sat, 18 Mar 2023 18:50:46 +0100 Subject: [PATCH 15/22] Added a unit display catalog to attach paths to specific units --- packages/client/src/gfx/Unit3D.tsx | 15 ++++++------ packages/client/src/gfx/UnitDisplayCatalog.ts | 23 +++++++++++++++++++ 2 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 packages/client/src/gfx/UnitDisplayCatalog.ts diff --git a/packages/client/src/gfx/Unit3D.tsx b/packages/client/src/gfx/Unit3D.tsx index 0b859a1..a3c4272 100644 --- a/packages/client/src/gfx/Unit3D.tsx +++ b/packages/client/src/gfx/Unit3D.tsx @@ -14,7 +14,8 @@ import { SelectionCircle } from './SelectionCircle' import { Line3D } from './Line3D' import { Map3D, Box } from './Map3D' import { ThreeCache } from './ThreeCache' -import { FileModel, PeasantModel } from './FileModel' +import { FileModel } from './FileModel' +import { UNIT_DISPLAY_CATALOG } from './UnitDisplayCatalog' import { Horizon } from '../debug/Horizon' @@ -93,13 +94,11 @@ export function Unit3D(props: Unit3DProps) { const unitSize = isBuilding ? 4 : 1; const selectorSize = isBuilding ? 5 : 1; - const modelPath = - isBuilding ? - '/public/castle_1.glb' - : props.unit.owner !== 0 ? - '/public/peasant_1.glb' - : '/public/gold_node.glb' - ; + const unitCatalogEntry = UNIT_DISPLAY_CATALOG[props.unit.kind]; + if (!unitCatalogEntry) + throw new Error("Unit doesn't exist in catalog"); + + const modelPath = unitCatalogEntry().modelPath; // smoothing const unitGroupRef = useRef(null); diff --git a/packages/client/src/gfx/UnitDisplayCatalog.ts b/packages/client/src/gfx/UnitDisplayCatalog.ts new file mode 100644 index 0000000..29da27c --- /dev/null +++ b/packages/client/src/gfx/UnitDisplayCatalog.ts @@ -0,0 +1,23 @@ +interface UnitDisplayCatalog { + [kind: string]: () => { + modelPath: string; + }; +} + +export const UNIT_DISPLAY_CATALOG : UnitDisplayCatalog = { + 'Harvester': () => ({ + modelPath: 'peasant_1.glb' + }), + 'Base': () => ({ + modelPath: 'castle_1.glb' + }), + 'ResourceNode': () => ({ + modelPath: 'gold_node.glb' + }), + 'Barracks': () => ({ + modelPath: 'castle_1.glb' + }), + 'Trooper': () => ({ + modelPath: 'catapult.glb' + }) +}; From 27df4af9ae188a004b6335bf17f93fae89c8feaf Mon Sep 17 00:00:00 2001 From: bananu7 Date: Sat, 18 Mar 2023 19:41:58 +0100 Subject: [PATCH 16/22] Fixed selector size for gltf models --- packages/client/src/gfx/Unit3D.tsx | 9 +++------ packages/client/src/gfx/UnitDisplayCatalog.ts | 16 +++++++++++----- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/packages/client/src/gfx/Unit3D.tsx b/packages/client/src/gfx/Unit3D.tsx index a3c4272..f1ec1b9 100644 --- a/packages/client/src/gfx/Unit3D.tsx +++ b/packages/client/src/gfx/Unit3D.tsx @@ -89,16 +89,13 @@ export function Unit3D(props: Unit3DProps) { const color = ownerToColor(props.unit.owner); - // TODO proper unit catalog - const isBuilding = props.unit.kind === 'Base' || props.unit.kind === 'Barracks'; - const unitSize = isBuilding ? 4 : 1; - const selectorSize = isBuilding ? 5 : 1; - const unitCatalogEntry = UNIT_DISPLAY_CATALOG[props.unit.kind]; if (!unitCatalogEntry) throw new Error("Unit doesn't exist in catalog"); - const modelPath = unitCatalogEntry().modelPath; + const unitDetails = unitCatalogEntry(); + const modelPath = unitDetails.modelPath; + const selectorSize = unitDetails.selectorSize; // smoothing const unitGroupRef = useRef(null); diff --git a/packages/client/src/gfx/UnitDisplayCatalog.ts b/packages/client/src/gfx/UnitDisplayCatalog.ts index 29da27c..57567d8 100644 --- a/packages/client/src/gfx/UnitDisplayCatalog.ts +++ b/packages/client/src/gfx/UnitDisplayCatalog.ts @@ -1,23 +1,29 @@ interface UnitDisplayCatalog { [kind: string]: () => { modelPath: string; + selectorSize: number; }; } export const UNIT_DISPLAY_CATALOG : UnitDisplayCatalog = { 'Harvester': () => ({ - modelPath: 'peasant_1.glb' + modelPath: 'peasant_1.glb', + selectorSize: 1, }), 'Base': () => ({ - modelPath: 'castle_1.glb' + modelPath: 'castle_1.glb', + selectorSize: 6, }), 'ResourceNode': () => ({ - modelPath: 'gold_node.glb' + modelPath: 'gold_node.glb', + selectorSize: 1.8, }), 'Barracks': () => ({ - modelPath: 'castle_1.glb' + modelPath: 'castle_1.glb', + selectorSize: 6, }), 'Trooper': () => ({ - modelPath: 'catapult.glb' + modelPath: 'catapult.glb', + selectorSize: 2.5, }) }; From 7f11ecabfece518e1a54afe806d64b3ef2b974e7 Mon Sep 17 00:00:00 2001 From: bananu7 Date: Sat, 18 Mar 2023 19:42:18 +0100 Subject: [PATCH 17/22] Movement animation is now picked by name instead of index --- packages/client/src/gfx/FileModel.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/client/src/gfx/FileModel.tsx b/packages/client/src/gfx/FileModel.tsx index 688ee00..b724c88 100644 --- a/packages/client/src/gfx/FileModel.tsx +++ b/packages/client/src/gfx/FileModel.tsx @@ -11,10 +11,12 @@ export type FileModelProps = { animate: boolean, // TODO which anims how fast etc } +const ACCENT_MATERIAL_NAME = 'Accent'; + function FileModel_(props: FileModelProps) { const gltf = useLoader(GLTFLoader, props.path) - const origAccentMaterial = gltf.materials['accent']; + const origAccentMaterial = gltf.materials[ACCENT_MATERIAL_NAME]; const accentMaterial = (() => { if (!origAccentMaterial || !(origAccentMaterial instanceof THREE.MeshStandardMaterial)) return undefined; @@ -36,17 +38,20 @@ function FileModel_(props: FileModelProps) { if (!mixer) { mixer = new THREE.AnimationMixer(ref.current); - mixer.clipAction(gltf.animations[0]).play(); + const moveAction = gltf.animations.find(a => a.name === "Move"); + if (moveAction) { + mixer.clipAction(moveAction).play(); + } } if (props.animate) - mixer.update(delta*5); + mixer.update(delta); }); const clonedObject = SkeletonUtils.clone(gltf.scene); clonedObject.traverse(o => { if (o instanceof THREE.Mesh) { - if (o.material.name === "accent") + if (o.material.name === ACCENT_MATERIAL_NAME) o.material = accentMaterial; o.castShadow = true; o.receiveShadow = true; From 4530af59c691fb47a793292b0d0bfbc9a207742e Mon Sep 17 00:00:00 2001 From: bananu7 Date: Sat, 18 Mar 2023 20:21:18 +0100 Subject: [PATCH 18/22] Added assets download to build pipeline --- Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Dockerfile b/Dockerfile index 265b1bc..28d2d5b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -44,6 +44,10 @@ COPY ./packages/client/index.html ./ RUN yarn build +# get assets +RUN git clone https://github.com/bananu7/rts-assets.git --depth 1 +COPY ./rts-assets/models/*.glb ./public/ + ################################ # second stage - run FROM node:18 From 772e6608d3c994c81be330aab6224c765b260e5f Mon Sep 17 00:00:00 2001 From: bananu7 Date: Sat, 18 Mar 2023 20:24:14 +0100 Subject: [PATCH 19/22] Docker container should now always build, but only push to dockerhub on main --- .github/workflows/node.js.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 5099130..db2b474 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -50,7 +50,6 @@ jobs: docker-server: needs: build - if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -76,5 +75,5 @@ jobs: uses: docker/build-push-action@v3 with: context: ./ - push: true + push: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' tags: ${{ secrets.DOCKERHUB_USERNAME }}/rts:server, ${{ secrets.DOCKERHUB_USERNAME }}/rts:server-${{ steps.vars.outputs.sha_short }} From 546861582bde55bb2acc43bb04a8645b2dfb5ddd Mon Sep 17 00:00:00 2001 From: bananu7 Date: Sat, 18 Mar 2023 20:27:50 +0100 Subject: [PATCH 20/22] Fixed docker image push check eval --- .github/workflows/node.js.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index db2b474..bfba54a 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -75,5 +75,5 @@ jobs: uses: docker/build-push-action@v3 with: context: ./ - push: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' + push: ${{ github.ref == 'refs/heads/main' && github.event_name != 'pull_request' }} tags: ${{ secrets.DOCKERHUB_USERNAME }}/rts:server, ${{ secrets.DOCKERHUB_USERNAME }}/rts:server-${{ steps.vars.outputs.sha_short }} From 0a86557bf3e5a98fa68ab0365e14f702cd5476fb Mon Sep 17 00:00:00 2001 From: bananu7 Date: Sat, 18 Mar 2023 20:57:23 +0100 Subject: [PATCH 21/22] Changed docker copy because clone is inside of the container --- Dockerfile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 28d2d5b..7b4aa0a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,11 +42,12 @@ COPY ./packages/client/src ./src COPY ./packages/client/public ./public COPY ./packages/client/index.html ./ -RUN yarn build - # get assets RUN git clone https://github.com/bananu7/rts-assets.git --depth 1 -COPY ./rts-assets/models/*.glb ./public/ +RUN cp ./rts-assets/models/**/*.glb ./public/ + +RUN yarn build + ################################ # second stage - run From f66b44bf788da72eebb337193719000b8dadedd8 Mon Sep 17 00:00:00 2001 From: bananu7 Date: Sat, 18 Mar 2023 21:14:03 +0100 Subject: [PATCH 22/22] Removed the deprecated set-output from gh action --- .github/workflows/node.js.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index bfba54a..b400a19 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -24,7 +24,7 @@ jobs: - name: Set outputs id: vars - run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)" + run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - name: Build client working-directory: ./packages/client @@ -59,7 +59,7 @@ jobs: - name: Set version string id: vars - run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)" + run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - name: Store version to a file run: echo "${{ steps.vars.outputs.sha_short }}" > ./packages/server/version.txt