mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 20:19:49 +02:00
feat: baked ao
This commit is contained in:
1 parent
335cd4d699
commit
66cf1fd223
11 files changed
+75
-93
No files matched your search
@@ -1,8 +1,8 @@
|
|||||||
import { ReadStream } from '@blitzkit/core';
|
import { ReadStream } from "@blitzkit/core";
|
||||||
import AdmZip from 'adm-zip';
|
import AdmZip from "adm-zip";
|
||||||
import { readFile, writeFile } from 'fs/promises';
|
import { readFile } from "fs/promises";
|
||||||
import { Parser } from 'pickleparser';
|
import { Parser } from "pickleparser";
|
||||||
import protobuf from 'protobufjs';
|
import protobuf from "protobufjs";
|
||||||
|
|
||||||
interface WotbReplayMetaJson {
|
interface WotbReplayMetaJson {
|
||||||
version: string;
|
version: string;
|
||||||
@@ -24,26 +24,24 @@ export class WotbReplayReadStream extends ReadStream {
|
|||||||
async wotbReplay() {
|
async wotbReplay() {
|
||||||
const pickleParser = new Parser();
|
const pickleParser = new Parser();
|
||||||
const zip = new AdmZip(Buffer.from(this.buffer));
|
const zip = new AdmZip(Buffer.from(this.buffer));
|
||||||
const metaJsonBuffer = zip.getEntry('meta.json')?.getData();
|
const metaJsonBuffer = zip.getEntry("meta.json")?.getData();
|
||||||
const battleResultsDat = zip.getEntry('battle_results.dat')?.getData();
|
const battleResultsDat = zip.getEntry("battle_results.dat")?.getData();
|
||||||
|
|
||||||
if (!metaJsonBuffer || !battleResultsDat)
|
if (!metaJsonBuffer || !battleResultsDat)
|
||||||
throw new SyntaxError('meta.json not found');
|
throw new SyntaxError("meta.json not found");
|
||||||
|
|
||||||
const metaJson = JSON.parse(
|
const metaJson = JSON.parse(
|
||||||
metaJsonBuffer.toString(),
|
metaJsonBuffer.toString()
|
||||||
) as WotbReplayMetaJson;
|
) as WotbReplayMetaJson;
|
||||||
const unpickledBattleResults = pickleParser.parse(battleResultsDat);
|
const unpickledBattleResults = pickleParser.parse(battleResultsDat);
|
||||||
const [, battleResultsString] = unpickledBattleResults as [number, string];
|
const [, battleResultsString] = unpickledBattleResults as [number, string];
|
||||||
const root = await protobuf.load(
|
const root = await protobuf.load(
|
||||||
`${__dirname}/../../protos/BattleResultsClient.proto`,
|
`${__dirname}/../../protos/BattleResultsClient.proto`
|
||||||
);
|
);
|
||||||
const BattleResults = root.lookupType(
|
const BattleResults = root.lookupType(
|
||||||
'BattleResultsGenerated.BattleResultsClient',
|
"BattleResultsGenerated.BattleResultsClient"
|
||||||
);
|
);
|
||||||
|
|
||||||
writeFile('test.dat', Buffer.from(battleResultsString));
|
|
||||||
|
|
||||||
const reader = protobuf.Reader.create(Buffer.from(battleResultsString));
|
const reader = protobuf.Reader.create(Buffer.from(battleResultsString));
|
||||||
|
|
||||||
// const decodedBattleResults = BattleResults.decodeDelimited(
|
// const decodedBattleResults = BattleResults.decodeDelimited(
|
||||||
@@ -53,7 +51,7 @@ export class WotbReplayReadStream extends ReadStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const replay = await readFile('temp/test3.wotbreplay');
|
const replay = await readFile("temp/test3.wotbreplay");
|
||||||
const stream = new WotbReplayReadStream(replay.buffer as ArrayBuffer);
|
const stream = new WotbReplayReadStream(replay.buffer as ArrayBuffer);
|
||||||
|
|
||||||
stream.wotbReplay();
|
stream.wotbReplay();
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
import { toUniqueId } from "@blitzkit/core";
|
import { toUniqueId } from "@blitzkit/core";
|
||||||
import { NodeIO } from "@gltf-transform/core";
|
import { NodeIO } from "@gltf-transform/core";
|
||||||
import { ALL_EXTENSIONS } from "@gltf-transform/extensions";
|
import { ALL_EXTENSIONS } from "@gltf-transform/extensions";
|
||||||
import { readdir, writeFile } from "fs/promises";
|
import { readdir } from "fs/promises";
|
||||||
import { extractModel } from "../core/blitz/extractModel";
|
import { extractModel } from "../core/blitz/extractModel";
|
||||||
import { readXMLDVPL } from "../core/blitz/readXMLDVPL";
|
import { readXMLDVPL } from "../core/blitz/readXMLDVPL";
|
||||||
import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL";
|
import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL";
|
||||||
|
import { commitAssets } from "../core/github/commitAssets";
|
||||||
import { FileChange } from "../core/github/commitMultipleFiles";
|
import { FileChange } from "../core/github/commitMultipleFiles";
|
||||||
import { DATA } from "./constants";
|
import { DATA } from "./constants";
|
||||||
import { VehicleDefinitionList } from "./definitions";
|
import { VehicleDefinitionList } from "./definitions";
|
||||||
@@ -36,8 +37,6 @@ export async function tankModels() {
|
|||||||
|
|
||||||
const id = toUniqueId(nation, tank.id);
|
const id = toUniqueId(nation, tank.id);
|
||||||
|
|
||||||
if (id !== 5681) continue;
|
|
||||||
|
|
||||||
const parameters = await readYAMLDVPL<TankParameters>(
|
const parameters = await readYAMLDVPL<TankParameters>(
|
||||||
`${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`
|
`${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`
|
||||||
);
|
);
|
||||||
@@ -48,13 +47,8 @@ export async function tankModels() {
|
|||||||
const content = Buffer.from(await nodeIO.writeBinary(model));
|
const content = Buffer.from(await nodeIO.writeBinary(model));
|
||||||
|
|
||||||
changes.push({ path: `3d/tanks/models/${id}.glb`, content });
|
changes.push({ path: `3d/tanks/models/${id}.glb`, content });
|
||||||
|
|
||||||
await writeFile(
|
|
||||||
"C:/Projects/blitzkit/packages/website/public/test.glb",
|
|
||||||
content
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// await commitAssets(`tank models ${nation}`, changes);
|
await commitAssets(`tank models ${nation}`, changes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,6 @@ import { dirname } from "path";
|
|||||||
import { readBaseColor } from "../readBaseColor";
|
import { readBaseColor } from "../readBaseColor";
|
||||||
import { readDVPLFile } from "../readDVPLFile";
|
import { readDVPLFile } from "../readDVPLFile";
|
||||||
import { readNormal } from "../readNormal";
|
import { readNormal } from "../readNormal";
|
||||||
import { readOcclusion } from "../readOcclusion";
|
|
||||||
import { readRoughnessMetallic } from "../readRoughnessMetallic";
|
import { readRoughnessMetallic } from "../readRoughnessMetallic";
|
||||||
import {
|
import {
|
||||||
vertexAttributeGLTFName,
|
vertexAttributeGLTFName,
|
||||||
@@ -70,7 +69,10 @@ export async function extractModel(data: string, path: string) {
|
|||||||
.setMimeType("image/jpeg")
|
.setMimeType("image/jpeg")
|
||||||
.setImage(
|
.setImage(
|
||||||
await readBaseColor(
|
await readBaseColor(
|
||||||
`${data}/3d/${dirname(path)}/${textures.baseColorMap ?? textures.albedo}`
|
`${data}/3d/${dirname(path)}/${textures.baseColorMap ?? textures.albedo}`,
|
||||||
|
textures.miscMap
|
||||||
|
? `${data}/3d/${dirname(path)}/${textures.miscMap}`
|
||||||
|
: undefined
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -88,19 +90,6 @@ export async function extractModel(data: string, path: string) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (textures.miscMap) {
|
|
||||||
material.setOcclusionTexture(
|
|
||||||
document
|
|
||||||
.createTexture(node.materialName)
|
|
||||||
.setMimeType("image/jpeg")
|
|
||||||
.setImage(
|
|
||||||
await readOcclusion(
|
|
||||||
`${data}/3d/${dirname(path)}/${textures.miscMap}`
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (textures.baseNormalMap ?? textures.normalmap) {
|
if (textures.baseNormalMap ?? textures.normalmap) {
|
||||||
const isBase = textures.baseNormalMap !== undefined;
|
const isBase = textures.baseNormalMap !== undefined;
|
||||||
|
|
||||||
@@ -236,10 +225,6 @@ export async function extractModel(data: string, path: string) {
|
|||||||
.setBuffer(buffer);
|
.setBuffer(buffer);
|
||||||
|
|
||||||
primitive.setAttribute(name, attributeAccessor);
|
primitive.setAttribute(name, attributeAccessor);
|
||||||
|
|
||||||
if (attribute === VertexAttribute.TEXCOORD0) {
|
|
||||||
primitive.setAttribute("TEXCOORD_2", attributeAccessor);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const mesh = document
|
const mesh = document
|
||||||
|
|||||||
@@ -1,7 +1,48 @@
|
|||||||
import sharp from "sharp";
|
import sharp from "sharp";
|
||||||
import { readTexture } from "./readTexture";
|
import { readTexture } from "./readTexture";
|
||||||
|
|
||||||
export async function readBaseColor(path: string) {
|
export async function readBaseColor(path: string, occlusionPath?: string) {
|
||||||
const raw = await readTexture(path);
|
const baseRaw = await readTexture(path);
|
||||||
return await sharp(raw.data, { raw }).removeAlpha().jpeg().toBuffer();
|
const occlusionRaw = occlusionPath
|
||||||
|
? await readTexture(occlusionPath)
|
||||||
|
: undefined;
|
||||||
|
const base = await sharp(baseRaw.data, { raw: baseRaw })
|
||||||
|
.removeAlpha()
|
||||||
|
.raw()
|
||||||
|
.toBuffer();
|
||||||
|
const occlusion = occlusionRaw
|
||||||
|
? await sharp(occlusionRaw.data, { raw: occlusionRaw })
|
||||||
|
.extractChannel(3)
|
||||||
|
.raw()
|
||||||
|
.toBuffer()
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const combined = Buffer.alloc(baseRaw.width * baseRaw.height * 3);
|
||||||
|
|
||||||
|
for (let i = 0; i < baseRaw.width * baseRaw.height; i++) {
|
||||||
|
let c = 1;
|
||||||
|
|
||||||
|
if (occlusionRaw) {
|
||||||
|
const x = i % baseRaw.width;
|
||||||
|
const y = Math.floor(i / baseRaw.width);
|
||||||
|
const u = Math.floor(x * (occlusionRaw.width / baseRaw.width));
|
||||||
|
const v = Math.floor(y * (occlusionRaw.height / baseRaw.height));
|
||||||
|
|
||||||
|
const occlusionI = u + v * occlusionRaw.width;
|
||||||
|
|
||||||
|
c = occlusion![occlusionI] / 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
combined[i * 3 + 0] = Math.round(base[i * 3 + 0] * c);
|
||||||
|
combined[i * 3 + 1] = Math.round(base[i * 3 + 1] * c);
|
||||||
|
combined[i * 3 + 2] = Math.round(base[i * 3 + 2] * c);
|
||||||
|
}
|
||||||
|
|
||||||
|
const image = await sharp(combined, {
|
||||||
|
raw: { width: baseRaw.width, height: baseRaw.height, channels: 3 },
|
||||||
|
})
|
||||||
|
.jpeg()
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
return image;
|
||||||
}
|
}
|
||||||
@@ -17,8 +17,7 @@ export async function readNormal(path: string, isBase: boolean) {
|
|||||||
*/
|
*/
|
||||||
let x = raw.data[index + 3] * (2 / 255) - 1;
|
let x = raw.data[index + 3] * (2 / 255) - 1;
|
||||||
let y = raw.data[index + 1] * (2 / 255) - 1;
|
let y = raw.data[index + 1] * (2 / 255) - 1;
|
||||||
const underSqrt = 1 - x ** 2 - y ** 2;
|
let z = Math.sqrt(Math.max(0, 1 - x ** 2 - y ** 2));
|
||||||
let z = underSqrt > 0 ? Math.sqrt(underSqrt) : -Math.sqrt(-underSqrt);
|
|
||||||
|
|
||||||
raw.data[index] = Math.round((x + 1) * (255 / 2));
|
raw.data[index] = Math.round((x + 1) * (255 / 2));
|
||||||
raw.data[index + 1] = Math.round((y + 1) * (255 / 2));
|
raw.data[index + 1] = Math.round((y + 1) * (255 / 2));
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
import { writeFile } from "fs/promises";
|
|
||||||
import sharp from "sharp";
|
|
||||||
import { readTexture } from "./readTexture";
|
|
||||||
|
|
||||||
export async function readOcclusion(path: string) {
|
|
||||||
const raw = await readTexture(path);
|
|
||||||
const blitz = sharp(raw.data, { raw: raw });
|
|
||||||
const occlusion = await blitz?.extractChannel(3).raw().toBuffer();
|
|
||||||
|
|
||||||
const combined = Buffer.alloc(raw.width * raw.height * 3);
|
|
||||||
|
|
||||||
for (let i = 0; i < raw.width * raw.height; i++) {
|
|
||||||
combined[i * 3 + 0] = occlusion?.[i] ?? 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const image = await sharp(combined, {
|
|
||||||
raw: { width: raw.width, height: raw.height, channels: 3 },
|
|
||||||
})
|
|
||||||
.jpeg()
|
|
||||||
.toBuffer();
|
|
||||||
|
|
||||||
writeFile("test.ao.jpg", image);
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import { writeFile } from "fs/promises";
|
|
||||||
import sharp from "sharp";
|
import sharp from "sharp";
|
||||||
import { readTexture } from "./readTexture";
|
import { readTexture } from "./readTexture";
|
||||||
|
|
||||||
@@ -11,8 +10,8 @@ export async function readRoughnessMetallic(path: string) {
|
|||||||
const combined = Buffer.alloc(raw.width * raw.height * 3);
|
const combined = Buffer.alloc(raw.width * raw.height * 3);
|
||||||
|
|
||||||
for (let i = 0; i < raw.width * raw.height; i++) {
|
for (let i = 0; i < raw.width * raw.height; i++) {
|
||||||
combined[i * 3 + 1] = roughness?.[i] ?? 0;
|
combined[i * 3 + 1] = roughness[i];
|
||||||
combined[i * 3 + 2] = metallicness?.[i] ?? 0;
|
combined[i * 3 + 2] = metallicness[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
const image = await sharp(combined, {
|
const image = await sharp(combined, {
|
||||||
@@ -21,7 +20,5 @@ export async function readRoughnessMetallic(path: string) {
|
|||||||
.jpeg()
|
.jpeg()
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
|
|
||||||
writeFile("test.rm.jpg", image);
|
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
+2
-2
@@ -11,7 +11,7 @@ const LIGHTS_COUNT = 5;
|
|||||||
const LIGHT_DISTANCE = 13;
|
const LIGHT_DISTANCE = 13;
|
||||||
const LIGHT_HEIGHT_0 = 4;
|
const LIGHT_HEIGHT_0 = 4;
|
||||||
const LIGHT_HEIGHT_1 = 2;
|
const LIGHT_HEIGHT_1 = 2;
|
||||||
const INTENSITY = 30;
|
const INTENSITY = 35;
|
||||||
|
|
||||||
const N = 128;
|
const N = 128;
|
||||||
const TARGET_FRAME_RATE = 30;
|
const TARGET_FRAME_RATE = 30;
|
||||||
@@ -64,7 +64,7 @@ export function Lighting() {
|
|||||||
position={position}
|
position={position}
|
||||||
intensity={INTENSITY}
|
intensity={INTENSITY}
|
||||||
penumbra={1}
|
penumbra={1}
|
||||||
// castShadow={cast}
|
castShadow={cast}
|
||||||
decay={1}
|
decay={1}
|
||||||
color={color}
|
color={color}
|
||||||
/>
|
/>
|
||||||
|
|||||||
+5
-5
@@ -1,8 +1,8 @@
|
|||||||
import { invalidate, useFrame } from '@react-three/fiber';
|
import { invalidate, useFrame } from "@react-three/fiber";
|
||||||
import { clamp } from 'lodash-es';
|
import { clamp } from "lodash-es";
|
||||||
import { Quicklime, type QuicklimeEvent } from 'quicklime';
|
import { Quicklime, type QuicklimeEvent } from "quicklime";
|
||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from "react";
|
||||||
import { Mesh, MeshStandardMaterial } from 'three';
|
import { Mesh, MeshStandardMaterial } from "three";
|
||||||
|
|
||||||
const SIZE = 2 ** 5;
|
const SIZE = 2 ** 5;
|
||||||
|
|
||||||
|
|||||||
-7
@@ -28,13 +28,6 @@ export function TankModel() {
|
|||||||
const { gltf } = useModel(protagonist.tank.id);
|
const { gltf } = useModel(protagonist.tank.id);
|
||||||
const nodes = Object.values(gltf.nodes);
|
const nodes = Object.values(gltf.nodes);
|
||||||
|
|
||||||
nodes.forEach((n) => {
|
|
||||||
if (n instanceof Mesh && n.material instanceof MeshStandardMaterial) {
|
|
||||||
n.material.aoMapIntensity = 10;
|
|
||||||
console.log(n.geometry.attributes);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
useTankTransform(track, turret, turretContainer, gunContainer);
|
useTankTransform(track, turret, turretContainer, gunContainer);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { asset } from "@blitzkit/core";
|
||||||
import { type ObjectMap, useLoader } from "@react-three/fiber";
|
import { type ObjectMap, useLoader } from "@react-three/fiber";
|
||||||
import { Mesh, MeshStandardMaterial } from "three";
|
import { Mesh, MeshStandardMaterial } from "three";
|
||||||
import { type GLTF, GLTFLoader } from "three-stdlib";
|
import { type GLTF, GLTFLoader } from "three-stdlib";
|
||||||
@@ -11,8 +12,7 @@ const cache: Record<
|
|||||||
> = {};
|
> = {};
|
||||||
|
|
||||||
export function useModel(id: number) {
|
export function useModel(id: number) {
|
||||||
// const gltf = useLoader(GLTFLoader, asset(`3d/tanks/models/${id}.glb`));
|
const gltf = useLoader(GLTFLoader, asset(`3d/tanks/models/${id}.glb`));
|
||||||
const gltf = useLoader(GLTFLoader, `/test.glb`);
|
|
||||||
|
|
||||||
if (!cache[id]) {
|
if (!cache[id]) {
|
||||||
cache[id] = {
|
cache[id] = {
|
||||||
|
|||||||
Reference in new issue
Block a user