2 changed files with 130 additions and 129 deletions
			
			
		| @ -0,0 +1,127 @@ | |||||
|  | import axios from "axios"; | ||||
|  | import * as THREE from "three"; | ||||
|  | import { GLTFLoader } from "three/addons/loaders/GLTFLoader"; | ||||
|  | import * as SkeletonUtils from "three/addons/utils/SkeletonUtils"; | ||||
|  | import * as TWEEN from "@tweenjs/tween.js"; | ||||
|  | import { AppString } from "@/constants/app"; | ||||
|  | 
 | ||||
|  | const ANIMATION_DURATION_SECS = 10; | ||||
|  | const BASE32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; | ||||
|  | 
 | ||||
|  | export async function loadLandmarks(vue, world, scene, loop) { | ||||
|  |   const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER; | ||||
|  |   try { | ||||
|  |     const url = | ||||
|  |       endorserApiServer + "/api/v2/report/claims?claimType=GiveAction"; | ||||
|  |     const headers = { "Content-Type": "application/json" }; | ||||
|  |     const resp = await axios.get(url, { headers: headers }); | ||||
|  |     if (resp.status === 200) { | ||||
|  |       const minDate = resp.data.data[resp.data.data.length - 1].issuedAt; | ||||
|  |       const maxDate = resp.data.data[0].issuedAt; | ||||
|  |       const minTimeMillis = new Date(minDate).getTime(); | ||||
|  |       const fullTimeMillis = new Date(maxDate).getTime() - minTimeMillis; | ||||
|  |       // 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
 | ||||
|  |         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,
 | ||||
|  | 
 | ||||
|  |       // eslint-disable-next-line @typescript-eslint/no-this-alias
 | ||||
|  |       const parentWorld = world; | ||||
|  |       loader.load( | ||||
|  |         modelLoc, | ||||
|  |         function (gltf) { | ||||
|  |           gltf.scene.scale.set(0, 0, 0); | ||||
|  |           for (const claim of resp.data.data) { | ||||
|  |             const newPlant = SkeletonUtils.clone(gltf.scene); | ||||
|  |             const randomness = claim.id.substring(10); | ||||
|  |             const x = | ||||
|  |               (100 * BASE32.indexOf(randomness.substring(0, 1))) / 32 - 50; | ||||
|  |             const z = | ||||
|  |               (100 * BASE32.indexOf(randomness.substring(8, 9))) / 32 - 50; | ||||
|  |             newPlant.position.set(x, 0, z); | ||||
|  | 
 | ||||
|  |             parentWorld.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(); | ||||
|  |             parentWorld.bushes = [...parentWorld.bushes, newPlant]; | ||||
|  |           } | ||||
|  |         }, | ||||
|  |         undefined, | ||||
|  |         function (error) { | ||||
|  |           console.error(error); | ||||
|  |         } | ||||
|  |       ); | ||||
|  | 
 | ||||
|  |       // calculate when lights shine on appearing claim area
 | ||||
|  |       for (const claim of resp.data.data) { | ||||
|  |         // claim is a GiveServerRecord (see endorserServer.ts)
 | ||||
|  | 
 | ||||
|  |         // compute location for this claim
 | ||||
|  |         const randomness = claim.id.substring(10); | ||||
|  |         const x = (100 * BASE32.indexOf(randomness.substring(0, 1))) / 32 - 50; | ||||
|  |         const z = (100 * BASE32.indexOf(randomness.substring(8, 9))) / 32 - 50; | ||||
|  |         const light = createLight(); | ||||
|  |         light.position.set(x, 20, z); | ||||
|  |         light.target.position.set(x, 0, 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.log( | ||||
|  |         "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.log("Got exception contacting server:", error); | ||||
|  |     vue.setAlert( | ||||
|  |       "Error With Server", | ||||
|  |       "There was a problem retrieving your claims from the server." | ||||
|  |     ); | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | function 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