feat: initialize sunrise with 100-player shared rooms
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
import { Box3, BufferAttribute, BufferGeometry, Group, Sphere, Vector3, Vector4 } from 'three';
|
||||
import { BUILDINGS } from '../constants/buildings.ts';
|
||||
import { createBuildingMesh, finishBuildingScene } from './buildingScene.ts';
|
||||
import type { BuildingCounts, BuildingHeightSource } from './buildingScene.ts';
|
||||
import { restoreBuildingLightSpill } from './buildingLightSpill.ts';
|
||||
import type { TerrainMetadata } from './terrainGeometry.ts';
|
||||
|
||||
export interface BuildingAssetManifest {
|
||||
version: number;
|
||||
sourceHash: string;
|
||||
bufferHash: string;
|
||||
byteLength: number;
|
||||
terrain: Pick<TerrainMetadata, 'origin' | 'observerSurfaceElevation'>;
|
||||
counts: BuildingCounts;
|
||||
target: [number, number, number];
|
||||
meshes: {
|
||||
source: BuildingHeightSource;
|
||||
vertices: number;
|
||||
position: number;
|
||||
normal: number;
|
||||
lightHeight: number;
|
||||
index: number;
|
||||
indexCount: number;
|
||||
indexType: 'uint16' | 'uint32';
|
||||
box: [number, number, number, number, number, number];
|
||||
sphere: [number, number, number, number];
|
||||
}[];
|
||||
spill: { offset: number; size: number; bounds: [number, number, number, number] };
|
||||
}
|
||||
|
||||
export interface BuildingAssets { manifest: BuildingAssetManifest; buffer: ArrayBuffer }
|
||||
|
||||
export async function loadBuildingAssets(): Promise<BuildingAssets> {
|
||||
const response = await fetch(BUILDINGS.assetManifestUrl);
|
||||
if (!response.ok) throw new Error('건물 메타데이터를 불러오지 못했습니다.');
|
||||
const manifest = await response.json() as BuildingAssetManifest;
|
||||
if (manifest.version !== BUILDINGS.assetVersion) throw new Error('건물 파일 버전이 다릅니다. 건물을 다시 생성해 주세요.');
|
||||
const binary = await fetch(`${BUILDINGS.assetBufferUrl}?v=${manifest.bufferHash}`);
|
||||
if (!binary.ok) throw new Error('건물 버퍼를 불러오지 못했습니다.');
|
||||
const buffer = await binary.arrayBuffer();
|
||||
if (buffer.byteLength !== manifest.byteLength) throw new Error('건물 버퍼 크기가 올바르지 않습니다.');
|
||||
return { manifest, buffer };
|
||||
}
|
||||
|
||||
export function createBakedBuildings({ manifest, buffer }: BuildingAssets, terrain: TerrainMetadata) {
|
||||
if (manifest.version !== BUILDINGS.assetVersion || buffer.byteLength !== manifest.byteLength) {
|
||||
throw new Error('건물 파일 버전 또는 버퍼 크기가 올바르지 않습니다.');
|
||||
}
|
||||
if (manifest.terrain.origin.latitude !== terrain.origin.latitude || manifest.terrain.origin.longitude !== terrain.origin.longitude ||
|
||||
manifest.terrain.observerSurfaceElevation !== terrain.observerSurfaceElevation) {
|
||||
throw new Error('건물과 지형 기준점이 다릅니다. 건물을 다시 생성해 주세요.');
|
||||
}
|
||||
const group = new Group();
|
||||
for (const mesh of manifest.meshes) {
|
||||
const geometry = new BufferGeometry();
|
||||
// Views of the downloaded buffer: no extrusion, deduplication or array copies.
|
||||
geometry.setAttribute('position', new BufferAttribute(new Float32Array(buffer, mesh.position, mesh.vertices * 3), 3));
|
||||
geometry.setAttribute('normal', new BufferAttribute(new Float32Array(buffer, mesh.normal, mesh.vertices * 3), 3));
|
||||
geometry.setAttribute('buildingLightHeight', new BufferAttribute(new Float32Array(buffer, mesh.lightHeight, mesh.vertices), 1));
|
||||
const indices = mesh.indexType === 'uint32' ? new Uint32Array(buffer, mesh.index, mesh.indexCount) : new Uint16Array(buffer, mesh.index, mesh.indexCount);
|
||||
geometry.setIndex(new BufferAttribute(indices, 1));
|
||||
geometry.boundingBox = new Box3(new Vector3().fromArray(mesh.box), new Vector3().fromArray(mesh.box, 3));
|
||||
geometry.boundingSphere = new Sphere(new Vector3().fromArray(mesh.sphere), mesh.sphere[3]);
|
||||
group.add(createBuildingMesh(mesh.source, geometry));
|
||||
}
|
||||
const spill = restoreBuildingLightSpill(new Uint8Array(buffer, manifest.spill.offset, manifest.spill.size ** 2),
|
||||
manifest.spill.size, new Vector4().fromArray(manifest.spill.bounds));
|
||||
return finishBuildingScene(group, manifest.counts, new Vector3().fromArray(manifest.target), spill);
|
||||
}
|
||||
Reference in New Issue
Block a user