@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
107 lines (84 loc) • 3.55 kB
JavaScript
import { vec3 } from "gl-matrix";
import { Box3, MeshStandardMaterial, PlaneBufferGeometry, Sphere } from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { Color } from "../../../../core/color/Color.js";
import { kelvin_to_rgb } from "../../../../core/color/kelvin/kelvin_to_rgb.js";
import { noop } from "../../../../core/function/noop.js";
import Quaternion from "../../../../core/geom/Quaternion.js";
import Vector3 from "../../../../core/geom/Vector3.js";
import { Transform } from "../../../ecs/transform/Transform.js";
import { DirectionalLight } from "../../render/forward_plus/model/DirectionalLight.js";
import { three_object_replace_materials } from "../../three/three_object_replace_materials.js";
import { three_object_to_path_traced_scene } from "./three_object_to_path_traced_scene.js";
export function make_sun({
temperature = 5000, // around clear-sky day
color = '#FFFFFF',
intensity = 1,
direction = new Vector3(-0.5, -1, -0.05)
} = {}) {
const temp_c = new Color();
kelvin_to_rgb(temp_c, 0, temperature);
const light = new DirectionalLight();
light.color.parse(color);
vec3.multiply(light.color, light.color, temp_c);
const n = vec3.length(light.color);
vec3.scale(light.color, light.color, 1 / n); // normalize color vector
light.intensity.set(intensity * n);
light.direction.copy(direction);
light.direction.normalize();
return light;
}
/**
*
* @param {string} url
* @return {Promise<GLTF>}
*/
function promise_gltf(url) {
return new Promise((resolve, reject) => {
new GLTFLoader().load(url, resolve, noop, reject);
});
}
/**
*
* @param {PathTracedScene} scene
* @param {THREE.Camera} camera
* @param {string} url
* @param {number} [zoom]
* @param {number} [floor_level]
* @param {Object} [sun]
* @param {boolean} [no_materials]
* @return {Promise<void>}
*/
export async function prepare_scene_gltf({
scene,
camera,
url,
zoom = 1,
floor_level = 0,
sun,
no_materials = false
}) {
const gltf = await promise_gltf(url);
const ground_material = new MeshStandardMaterial({
color: '#ffceae'
});
scene.createMesh(new PlaneBufferGeometry(), ground_material, Transform.fromJSON({
position: new Vector3(0, floor_level, 0),
scale: 5000,
rotation: Quaternion.fromEulerAngles(-Math.PI / 2, 0, 0)
}).matrix);
const gltf_scene = gltf.scene;
if (no_materials) {
three_object_replace_materials(gltf_scene, new MeshStandardMaterial({ color: 'white' }));
}
three_object_to_path_traced_scene(gltf_scene, scene);
const box3 = new Box3();
box3.setFromObject(gltf_scene);
const sphere = new Sphere();
box3.getBoundingSphere(sphere);
scene.addLight(make_sun(sun));
camera.position.set(1, 1.3, 1)
.normalize()
.multiplyScalar(sphere.radius * 2.6 * (1 / zoom));
camera.lookAt(sphere.center);
}