Matthew Raymer
1 year ago
8 changed files with 276 additions and 4 deletions
@ -0,0 +1,3 @@ |
|||||
|
[submodule "src/types"] |
||||
|
path = src/types |
||||
|
url = ssh://git@173.199.124.46:222/trent_larson/endorser-types.git |
@ -0,0 +1,28 @@ |
|||||
|
import { PlaneGeometry, MeshLambertMaterial, Mesh, TextureLoader, Color } from "three"; |
||||
|
|
||||
|
class Terrain { |
||||
|
constructor(props: { width: number; height: number; color: Color }) { |
||||
|
const loader = new TextureLoader(); |
||||
|
const heightTexture = loader.load("img/textures/leafy-autumn-forest-floor.jpg"); |
||||
|
const geometry = new PlaneGeometry(props.width, props.height, 64, 64); |
||||
|
|
||||
|
const material = new MeshLambertMaterial({ |
||||
|
color: props.color, |
||||
|
flatShading: true, |
||||
|
map: heightTexture, |
||||
|
}); |
||||
|
|
||||
|
const plane = new Mesh(geometry, material); |
||||
|
plane.position.set(0, 0, 0); |
||||
|
plane.rotation.x -= Math.PI * 0.5; |
||||
|
|
||||
|
// Storing our original vertices position on a new attribute
|
||||
|
plane.geometry.attributes.position.originalPosition = plane.geometry.attributes.position.array; |
||||
|
|
||||
|
plane.tick = () => {}; |
||||
|
|
||||
|
return plane; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export { Terrain }; |
@ -0,0 +1,137 @@ |
|||||
|
import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; |
||||
|
import { SkeletonUtils } from 'three/examples/jsm/utils/SkeletonUtils'; |
||||
|
import axios from 'axios'; |
||||
|
import TWEEN from '@tweenjs/tween.js'; |
||||
|
import * as THREE from 'three' |
||||
|
|
||||
|
class LandmarksLoader { |
||||
|
async load(vue, world, scene, loop, token) { |
||||
|
vue.setWorldProperty("animationDurationSeconds", ANIMATION_DURATION_SECS); |
||||
|
|
||||
|
try { |
||||
|
const url = apiServer + "/api/v2/report/claims?claimType=GiveAction"; |
||||
|
const headers = { |
||||
|
"Content-Type": "application/json", |
||||
|
Authorization: "Bearer " + token, |
||||
|
}; |
||||
|
const resp = await axios.get(url, { headers: headers }); |
||||
|
if (resp.status === 200) { |
||||
|
const landmarks = resp.data.data; |
||||
|
|
||||
|
const minDate = landmarks[landmarks.length - 1].issuedAt; |
||||
|
const maxDate = landmarks[0].issuedAt; |
||||
|
|
||||
|
world.setExposedWorldProperties("startTime", minDate.replace("T", " ")); |
||||
|
world.setExposedWorldProperties("endTime", maxDate.replace("T", " ")); |
||||
|
|
||||
|
const minTimeMillis = new Date(minDate).getTime(); |
||||
|
const fullTimeMillis = |
||||
|
maxDate > minDate ? new Date(maxDate).getTime() - minTimeMillis : 1; // avoid divide by zero
|
||||
|
// ratio of animation time to real time
|
||||
|
const fakeRealRatio = (ANIMATION_DURATION_SECS * 1000) / fullTimeMillis; |
||||
|
|
||||
|
// load plant model first because it takes a second
|
||||
|
const loader = new GLTFLoader(); |
||||
|
// choose the right plant
|
||||
|
const modelLoc = "/models/lupine_plant/scene.gltf"; // push with pokies
|
||||
|
const modScale = 0.1; |
||||
|
//const modelLoc = "/models/round_bush/scene.gltf"; // green & pink
|
||||
|
// modScale = 1;
|
||||
|
//const modelLoc = "/models/coreopsis-flower.glb"; // 3 flowers
|
||||
|
// modScale = 2;
|
||||
|
//const modelLoc = "/models/a_bush/scene.gltf"; // purple leaves
|
||||
|
// modScale = 15;
|
||||
|
|
||||
|
// calculate positions for each claim, especially because some are random
|
||||
|
const locations = landmarks.map((claim: GiveServerRecord) => |
||||
|
locForGive(claim, world.PLATFORM_SIZE, world.PLATFORM_EDGE_FOR_UNKNOWNS) |
||||
|
); |
||||
|
|
||||
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
|
loader.load( |
||||
|
modelLoc, |
||||
|
function (gltf: GLTF) { |
||||
|
gltf.scene.scale.set(0, 0, 0); |
||||
|
for (let i = 0; i < landmarks.length; i++) { |
||||
|
// claim is a GiveServerRecord (see endorserServer.ts)
|
||||
|
const claim = landmarks[i]; |
||||
|
const newPlant = SkeletonUtils.clone(gltf.scene); |
||||
|
|
||||
|
const loc = locations[i]; |
||||
|
newPlant.position.set(loc.x, 0, loc.z); |
||||
|
|
||||
|
world.scene.add(newPlant); |
||||
|
const timeDelayMillis = |
||||
|
fakeRealRatio * |
||||
|
(new Date(claim.issuedAt).getTime() - minTimeMillis); |
||||
|
new TWEEN.Tween(newPlant.scale) |
||||
|
.delay(timeDelayMillis) |
||||
|
.to({ x: modScale, y: modScale, z: modScale }, 5000) |
||||
|
.start(); |
||||
|
world.bushes = [...world.bushes, newPlant]; |
||||
|
} |
||||
|
}, |
||||
|
undefined, |
||||
|
function (error: ErrorEvent) { |
||||
|
console.error(error); |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
// calculate when lights shine on appearing claim area
|
||||
|
for (let i = 0; i < landmarks.length; i++) { |
||||
|
// claim is a GiveServerRecord (see endorserServer.ts)
|
||||
|
const claim = landmarks[i]; |
||||
|
|
||||
|
const loc = locations[i]; |
||||
|
const light = this.createLight(); |
||||
|
light.position.set(loc.x, 20, loc.z); |
||||
|
light.target.position.set(loc.x, 0, loc.z); |
||||
|
loop.updatables.push(light); |
||||
|
scene.add(light); |
||||
|
scene.add(light.target); |
||||
|
|
||||
|
// now figure out the timing and shine a light
|
||||
|
const timeDelayMillis = |
||||
|
fakeRealRatio * (new Date(claim.issuedAt).getTime() - minTimeMillis); |
||||
|
new TWEEN.Tween(light) |
||||
|
.delay(timeDelayMillis) |
||||
|
.to({ intensity: 100 }, 10) |
||||
|
.chain( |
||||
|
new TWEEN.Tween(light.position) |
||||
|
.to({ y: 5 }, 5000) |
||||
|
.onComplete(() => { |
||||
|
scene.remove(light); |
||||
|
light.dispose(); |
||||
|
}) |
||||
|
) |
||||
|
.start(); |
||||
|
world.lights = [...world.lights, light]; |
||||
|
} |
||||
|
} else { |
||||
|
console.error( |
||||
|
"Got bad server response status & data of", |
||||
|
resp.status, |
||||
|
resp.data |
||||
|
); |
||||
|
vue.setAlert( |
||||
|
"Error With Server", |
||||
|
"There was an error retrieving your claims from the server." |
||||
|
); |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error("Got exception contacting server:", error); |
||||
|
vue.setAlert( |
||||
|
"Error With Server", |
||||
|
"There was a problem retrieving your claims from the server." |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private createLight() { |
||||
|
const light = new THREE.SpotLight(0xffffff, 0, 0, Math.PI / 8, 0.5, 0); |
||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
|
light.tick = () => {}; |
||||
|
return light; |
||||
|
} |
||||
|
|
||||
|
} |
Loading…
Reference in new issue