basic text renderer implemented

This commit is contained in:
ad044 2020-10-01 15:57:38 +04:00
parent 68672f0112
commit c76cbcb7d0
10 changed files with 277 additions and 167 deletions

View file

@ -20,8 +20,8 @@
"recoil": "0.0.10",
"three": "^0.119.1",
"three-plain-animator": "^1.0.2",
"typescript": "^3.7.5",
"ts-node": "^9.0.0"
"ts-node": "^9.0.0",
"typescript": "^3.7.5"
},
"scripts": {
"start": "react-scripts start",

View file

@ -123,7 +123,7 @@ const BlueOrb = memo((props: BlueOrbContructorProps) => {
<a.mesh
position={props.position as [number, number, number]}
rotation-y={props.rotation[1]}
scale={[0.25, 0.15, 0.25]}
scale={[0.36, 0.2, 0.36]}
renderOrder={1}
>
<planeBufferGeometry attach="geometry" />

View file

@ -11,166 +11,162 @@ import { a, useSpring } from "@react-spring/three";
import { useRecoilValue } from "recoil";
import { hudActiveAtom } from "./HUDElementAtom";
import { currentHUDAtom } from "./HUDElementAtom";
import HUDText from "./HUDText";
export type HUDElementProps = {
hudVisibility: boolean;
hudVisibility: boolean;
};
type HudShapeData = {
position: number[];
scale: number[];
type: string;
initial_position: number[];
position: number[];
scale: number[];
type: string;
initial_position: number[];
};
export type BlueOrbHudData = {
long: HudShapeData;
boring: HudShapeData;
big: HudShapeData;
long: HudShapeData;
boring: HudShapeData;
big: HudShapeData;
};
export type BlueOrbHuds = {
[blue_orb_hud_id: string]: BlueOrbHudData;
[blue_orb_hud_id: string]: BlueOrbHudData;
};
type LevelYValues = {
[level: string]: number;
[level: string]: number;
};
const HUDElement = memo((props: HUDElementProps) => {
const currentBlueOrbHUD = useRecoilValue(currentHUDAtom);
const currentBlueOrbHUD = useRecoilValue(currentHUDAtom);
const hudActive = useRecoilValue(hudActiveAtom);
const hudActive = useRecoilValue(hudActiveAtom);
const { bigHUDPositionX } = useSpring({
bigHUDPositionX: hudActive,
config: { duration: 500 },
});
const { bigHUDPositionX } = useSpring({
bigHUDPositionX: hudActive,
config: { duration: 500 },
});
const { longHUDPositionX } = useSpring({
longHUDPositionX: hudActive,
config: { duration: 500 },
});
const { longHUDPositionX } = useSpring({
longHUDPositionX: hudActive,
config: { duration: 500 },
});
const { boringHUDPositionX } = useSpring({
boringHUDPositionX: hudActive,
config: { duration: 500 },
});
const { boringHUDPositionX } = useSpring({
boringHUDPositionX: hudActive,
config: { duration: 500 },
});
const bigHUDPosX = bigHUDPositionX.to(
[0, 1],
[
currentBlueOrbHUD["big"]["initial_position"][0],
currentBlueOrbHUD["big"]["position"][0],
]
);
const bigHUDPosX = bigHUDPositionX.to(
[0, 1],
[
currentBlueOrbHUD["big"]["initial_position"][0],
currentBlueOrbHUD["big"]["position"][0],
]
);
const boringHUDPosX = boringHUDPositionX.to(
[0, 1],
[
currentBlueOrbHUD["boring"]["initial_position"][0],
currentBlueOrbHUD["boring"]["position"][0],
]
);
const boringHUDPosX = boringHUDPositionX.to(
[0, 1],
[
currentBlueOrbHUD["boring"]["initial_position"][0],
currentBlueOrbHUD["boring"]["position"][0],
]
);
const longHUDPosX = longHUDPositionX.to(
[0, 1],
[
currentBlueOrbHUD["long"]["initial_position"][0],
currentBlueOrbHUD["long"]["position"][0],
]
);
const longHUDPosX = longHUDPositionX.to(
[0, 1],
[
currentBlueOrbHUD["long"]["initial_position"][0],
currentBlueOrbHUD["long"]["position"][0],
]
);
// these hud elements come in all shapes and forms, some of them are mirrored, rotated
// you name it. this function allows me to specify whether i want a normal texture
// for the blue orb or the mirrored/rotated one.
const spriteTypeToSprite = (spriteType: string, hudElement: string) => {
switch (spriteType) {
case "normal":
switch (hudElement) {
case "long":
return longHud;
case "boring":
return boringHud;
case "big":
return bigHud;
}
break;
case "mirrored":
switch (hudElement) {
case "big":
return bigHudMirrored;
case "long":
return longHudMirrored;
case "boring":
return boringHudMirrored;
}
// these hud elements come in all shapes and forms, some of them are mirrored, rotated
// you name it. this function allows me to specify whether i want a normal texture
// for the blue orb or the mirrored/rotated one.
const spriteTypeToSprite = (spriteType: string, hudElement: string) => {
switch (spriteType) {
case "normal":
switch (hudElement) {
case "long":
return longHud;
case "boring":
return boringHud;
case "big":
return bigHud;
}
};
break;
case "mirrored":
switch (hudElement) {
case "big":
return bigHudMirrored;
case "long":
return longHudMirrored;
case "boring":
return boringHudMirrored;
}
}
};
const longHudTexture = useLoader(
THREE.TextureLoader,
spriteTypeToSprite(currentBlueOrbHUD["long"]["type"], "long")!
);
const longHudTexture = useLoader(
THREE.TextureLoader,
spriteTypeToSprite(currentBlueOrbHUD["long"]["type"], "long")!
);
const longHudBoringTexture = useLoader(
THREE.TextureLoader,
spriteTypeToSprite(currentBlueOrbHUD["boring"]["type"], "boring")!
);
const longHudBoringTexture = useLoader(
THREE.TextureLoader,
spriteTypeToSprite(currentBlueOrbHUD["boring"]["type"], "boring")!
);
const bigHudTexture = useLoader(
THREE.TextureLoader,
spriteTypeToSprite(currentBlueOrbHUD["big"]["type"], "big")!
);
const bigHudTexture = useLoader(
THREE.TextureLoader,
spriteTypeToSprite(currentBlueOrbHUD["big"]["type"], "big")!
);
return (
<group visible={props.hudVisibility} renderOrder={1}>
<a.sprite
position-x={longHUDPosX}
position-y={
currentBlueOrbHUD["long"]["position"][1]
}
position-z={currentBlueOrbHUD["long"]["position"][2]}
scale={currentBlueOrbHUD["long"]["scale"] as [number, number, number]}
>
<spriteMaterial
attach="material"
map={longHudTexture}
transparent={true}
/>
</a.sprite>
<a.sprite
position-x={boringHUDPosX}
position-y={
currentBlueOrbHUD!["boring"]["position"][1]
}
position-z={currentBlueOrbHUD!["boring"]["position"][2]}
scale={
currentBlueOrbHUD!["boring"]["scale"] as [number, number, number]
}
>
<spriteMaterial
attach="material"
map={longHudBoringTexture}
transparent={true}
/>
</a.sprite>
<a.sprite
position-x={bigHUDPosX}
position-y={
currentBlueOrbHUD!["big"]["position"][1]
}
position-z={currentBlueOrbHUD!["big"]["position"][2]}
scale={currentBlueOrbHUD!["big"]["scale"] as [number, number, number]}
>
<spriteMaterial
attach="material"
map={bigHudTexture}
transparent={true}
/>
</a.sprite>
</group>
);
return (
<group visible={props.hudVisibility} renderOrder={1}>
<a.sprite
position-x={longHUDPosX}
position-y={currentBlueOrbHUD["long"]["position"][1]}
position-z={currentBlueOrbHUD["long"]["position"][2]}
scale={currentBlueOrbHUD["long"]["scale"] as [number, number, number]}
>
<spriteMaterial
attach="material"
map={longHudTexture}
transparent={true}
/>
</a.sprite>
<a.sprite
position-x={boringHUDPosX}
position-y={currentBlueOrbHUD!["boring"]["position"][1]}
position-z={currentBlueOrbHUD!["boring"]["position"][2]}
scale={
currentBlueOrbHUD!["boring"]["scale"] as [number, number, number]
}
>
<spriteMaterial
attach="material"
map={longHudBoringTexture}
transparent={true}
/>
</a.sprite>
<a.sprite
position-x={bigHUDPosX}
position-y={currentBlueOrbHUD!["big"]["position"][1]}
position-z={currentBlueOrbHUD!["big"]["position"][2]}
scale={currentBlueOrbHUD!["big"]["scale"] as [number, number, number]}
>
<spriteMaterial
attach="material"
map={bigHudTexture}
transparent={true}
/>
</a.sprite>
<HUDText text={"Tda028"} hudTextPos={[-0.35, 0.23, -8.7]} />
</group>
);
});
export default HUDElement;

View file

@ -9,7 +9,7 @@ export const hudActiveAtom = atom({
export const hudVisibilityAtom = atom({
key: "hudVisibilityAtom",
default: false,
default: true,
});
export const currentHUDAtom = atom({

View file

@ -0,0 +1,27 @@
import React from "react";
import orange_font_json from "../../resources/orange_font.json";
import Letter from "../TextRenderer";
type HUDTextProps = {
text: string;
hudTextPos: number[];
};
const HUDText = (props: HUDTextProps) => {
return (
<group position={props.hudTextPos as [number, number, number]} scale={[0.04, 0.06, 0.04]}>
{props.text.split("").map((letter: string, idx: number) => {
return (
<Letter
color={"yellow"}
letter={letter}
kerningOffset={idx}
key={idx}
/>
);
})}
</group>
);
};
export default HUDText;

View file

@ -58,7 +58,6 @@ const MainScene = () => {
position-z={3}
position-y={cameraState.camPosY}
rotation-y={cameraState.camRotY}
aspect={-1}
>
<Suspense fallback={null}>
<MainSceneIntro />

View file

@ -46,7 +46,6 @@ const OrthoCamera = memo(() => {
>
<HUDElement key={1} hudVisibility={hudVisible} />
<Orb orbVisibility={orbVisible} />
{/*<TextRenderer />*/}
</a.orthographicCamera>
</a.group>
);

View file

@ -22,20 +22,20 @@ const Site = memo(() => {
<>
<Suspense fallback={<>loading...</>}>
{/* distance between LEVELS is 1.5 */}
{Object.values(level_y_values).map((yVal) => {
return <Level levelPosY={yVal} key={yVal} />;
})}
{/*{Object.values(level_y_values).map((yVal) => {*/}
{/* return <Level levelPosY={yVal} key={yVal} />;*/}
{/*})}*/}
{Array.from(Array(8).keys()).map((colIdx: number) => {
return (
<Column
columnData={siteData.siteA.filter((blueOrb) =>
siteData.columnJson[colIdx].includes(blueOrb[0].substr(2))
)}
key={colIdx}
/>
);
})}
{/*{Array.from(Array(8).keys()).map((colIdx: number) => {*/}
{/* return (*/}
{/* <Column*/}
{/* columnData={siteData.siteA.filter((blueOrb) =>*/}
{/* siteData.columnJson[colIdx].includes(blueOrb[0].substr(2))*/}
{/* )}*/}
{/* key={colIdx}*/}
{/* />*/}
{/* );*/}
{/*})}*/}
</Suspense>
</>
);

View file

@ -1,22 +1,111 @@
import { useLoader } from "react-three-fiber";
import * as THREE from "three";
import { RepeatWrapping } from "three";
import orangeFont from "../static/sprites/orange_font_texture.png";
import yellowFont from "../static/sprites/yellow_font_texture.png";
import orange_font_json from "../resources/orange_font.json";
import React from "react";
import { a } from "@react-spring/three";
import React, { useMemo } from "react";
const TextRenderer = () => {
const orangeFontTexture: THREE.Texture = useLoader(
THREE.TextureLoader,
orangeFont
);
type LetterProps = {
color: string;
letter: string;
kerningOffset: number;
};
type LineYOffsets = {
[line: number]: number;
};
type ColorToTexture = {
[key: string]: string;
};
type LetterData = {
[letter: string]: number[];
};
type BigFontData = {
kerning: number;
baseline: number;
height: number;
glyphs: LetterData;
};
const Letter = (props: LetterProps) => {
const colorToTexture = (color: string) => {
return ({ orange: orangeFont, yellow: yellowFont } as ColorToTexture)[
color
];
};
// first letter in big font is always orange in this case so make it orange if so. else,
// run through the function.
const color =
props.kerningOffset === 0 ? orangeFont : colorToTexture(props.color);
const colorTexture: THREE.Texture = useLoader(THREE.TextureLoader, color);
// i have yet to figure out a genrealizable way of
// calculating the y offset, this shit will do for now
// also, we dont have all the lines since i dont need them yet.
// also, baseline offsets dont work properly since i dont need them yet either
// should be trivial to calculate though, im just lazy
const getLineNum = (letter: string) => {
const lineOne = "ABCDEFGHIJKLMNOPQ";
const lineTwo = "RSTUVWXYZ01234567";
const lineThree = "89abcdefghijklmnopqrs";
if (lineOne.includes(letter)) {
return 1;
} else if (lineTwo.includes(letter)) {
return 2;
} else {
return 3;
}
};
const lineYOffsets: LineYOffsets = {
1: 0.884,
2: 0.765,
3: 0.65,
};
const letterData = (orange_font_json as BigFontData)["glyphs"][props.letter];
const geometry = new THREE.PlaneBufferGeometry();
const uvAttribute = geometry.attributes.uv;
for (let i = 0; i < uvAttribute.count; i++) {
let u = uvAttribute.getX(i);
let v = uvAttribute.getY(i);
u = (u * letterData[2]) / 256 + letterData[0] / 256;
v =
(v * letterData[3]) / 136 +
letterData[4] / 136 +
lineYOffsets[getLineNum(props.letter)] -
letterData[4] / 136;
uvAttribute.setXY(i, u, v);
}
return (
<group position={[0, 0, -9]}>
<sprite>
<spriteMaterial attach="material" map={orangeFontTexture} />
</sprite>
</group>
<a.mesh
position-x={
props.kerningOffset === 0
? props.kerningOffset
: props.kerningOffset + 0.3
}
position-y={props.kerningOffset === 0 ? -0.03 : 0}
scale={props.kerningOffset === 0 ? [1.7, 1, 1.7] : [1, 1, 1]}
geometry={geometry}
>
<meshBasicMaterial map={colorTexture} attach="material" transparent={true} />
</a.mesh>
);
};
export default TextRenderer;
export default Letter;

View file

@ -13,16 +13,16 @@
},
"14": {
"position": [-0.35, 0, 1.3],
"rotation": [0, -0.15, 0]
"position": [-0.5, 0, 1.1],
"rotation": [0, -0.23, 0]
},
"22": {
"position": [-0.35, 0.3, 1.3],
"rotation": [0, -0.15, 0]
"position": [-0.5, 0.4, 1.1],
"rotation": [0, -0.23, 0]
},
"06": {
"position": [-0.35, -0.3, 1.3],
"rotation": [0, -0.15, 0]
"position": [-0.5, -0.4, 1.1],
"rotation": [0, -0.23, 0]
},
"07": {