Browse Source

load stats-world bushes and make 'em grow!

world-fix
Trent Larson 2 years ago
parent
commit
58e962a3bd
  1. 2
      README.md
  2. 11
      public/models/lupine_plant/license.txt
  3. BIN
      public/models/lupine_plant/scene.bin
  4. 229
      public/models/lupine_plant/scene.gltf
  5. BIN
      public/models/lupine_plant/textures/lambert2SG_baseColor.png
  6. BIN
      public/models/lupine_plant/textures/lambert2SG_normal.png
  7. 66
      src/components/World/World.js
  8. 2
      src/components/World/components/lights.js
  9. 8
      src/components/World/components/objects/terrain.js

2
README.md

@ -189,3 +189,5 @@ export const createAndStoreIdentifier = async (mnemonicPassword) => {
## Kudos ## Kudos
* [Máximo Fernández](https://medium.com/@maxfarenas) for the 3D [code](https://github.com/maxfer03/vue-three-ns) and [explanatory post](https://medium.com/nicasource/building-an-interactive-web-portfolio-with-vue-three-js-part-three-implementing-three-js-452cb375ef80) * [Máximo Fernández](https://medium.com/@maxfarenas) for the 3D [code](https://github.com/maxfer03/vue-three-ns) and [explanatory post](https://medium.com/nicasource/building-an-interactive-web-portfolio-with-vue-three-js-part-three-implementing-three-js-452cb375ef80)
* [Many libraries]() such as Veramo.io, Vuejs.org, threejs
* [Bush 3D model](https://sketchfab.com/3d-models/lupine-plant-bf30f1110c174d4baedda0ed63778439)

11
public/models/lupine_plant/license.txt

@ -0,0 +1,11 @@
Model Information:
* title: Lupine Plant
* source: https://sketchfab.com/3d-models/lupine-plant-bf30f1110c174d4baedda0ed63778439
* author: rufusrockwell (https://sketchfab.com/rufusrockwell)
Model License:
* license type: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
* requirements: Author must be credited. Commercial use is allowed.
If you use this 3D model in your project be sure to copy paste this credit wherever you share it:
This work is based on "Lupine Plant" (https://sketchfab.com/3d-models/lupine-plant-bf30f1110c174d4baedda0ed63778439) by rufusrockwell (https://sketchfab.com/rufusrockwell) licensed under CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)

BIN
public/models/lupine_plant/scene.bin

Binary file not shown.

229
public/models/lupine_plant/scene.gltf

@ -0,0 +1,229 @@
{
"accessors": [
{
"bufferView": 2,
"componentType": 5126,
"count": 2759,
"max": [
41.3074951171875,
40.37548828125,
87.85917663574219
],
"min": [
-35.245540618896484,
-36.895416259765625,
-0.9094290137290955
],
"type": "VEC3"
},
{
"bufferView": 2,
"byteOffset": 33108,
"componentType": 5126,
"count": 2759,
"max": [
0.9999382495880127,
0.9986748695373535,
0.9985831379890442
],
"min": [
-0.9998949766159058,
-0.9975876212120056,
-0.411094069480896
],
"type": "VEC3"
},
{
"bufferView": 3,
"componentType": 5126,
"count": 2759,
"max": [
0.9987699389457703,
0.9998998045921326,
0.9577858448028564,
1.0
],
"min": [
-0.9987726807594299,
-0.9990445971488953,
-0.999801516532898,
1.0
],
"type": "VEC4"
},
{
"bufferView": 1,
"componentType": 5126,
"count": 2759,
"max": [
1.0061479806900024,
0.9993550181388855
],
"min": [
0.00279300007969141,
0.0011620000004768372
],
"type": "VEC2"
},
{
"bufferView": 0,
"componentType": 5125,
"count": 6378,
"type": "SCALAR"
}
],
"asset": {
"extras": {
"author": "rufusrockwell (https://sketchfab.com/rufusrockwell)",
"license": "CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)",
"source": "https://sketchfab.com/3d-models/lupine-plant-bf30f1110c174d4baedda0ed63778439",
"title": "Lupine Plant"
},
"generator": "Sketchfab-12.68.0",
"version": "2.0"
},
"bufferViews": [
{
"buffer": 0,
"byteLength": 25512,
"name": "floatBufferViews",
"target": 34963
},
{
"buffer": 0,
"byteLength": 22072,
"byteOffset": 25512,
"byteStride": 8,
"name": "floatBufferViews",
"target": 34962
},
{
"buffer": 0,
"byteLength": 66216,
"byteOffset": 47584,
"byteStride": 12,
"name": "floatBufferViews",
"target": 34962
},
{
"buffer": 0,
"byteLength": 44144,
"byteOffset": 113800,
"byteStride": 16,
"name": "floatBufferViews",
"target": 34962
}
],
"buffers": [
{
"byteLength": 157944,
"uri": "scene.bin"
}
],
"images": [
{
"uri": "textures/lambert2SG_baseColor.png"
},
{
"uri": "textures/lambert2SG_normal.png"
}
],
"materials": [
{
"alphaCutoff": 0.2,
"alphaMode": "MASK",
"doubleSided": true,
"name": "lambert2SG",
"normalTexture": {
"index": 1
},
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 0
},
"metallicFactor": 0.0
}
}
],
"meshes": [
{
"name": "Object_0",
"primitives": [
{
"attributes": {
"NORMAL": 1,
"POSITION": 0,
"TANGENT": 2,
"TEXCOORD_0": 3
},
"indices": 4,
"material": 0,
"mode": 4
}
]
}
],
"nodes": [
{
"children": [
1
],
"matrix": [
1.0,
0.0,
0.0,
0.0,
0.0,
2.220446049250313e-16,
-1.0,
0.0,
0.0,
1.0,
2.220446049250313e-16,
0.0,
0.0,
0.0,
0.0,
1.0
],
"name": "Sketchfab_model"
},
{
"children": [
2
],
"name": "LupineSF.obj.cleaner.materialmerger.gles"
},
{
"mesh": 0,
"name": "Object_2"
}
],
"samplers": [
{
"magFilter": 9729,
"minFilter": 9987,
"wrapS": 10497,
"wrapT": 10497
}
],
"scene": 0,
"scenes": [
{
"name": "Sketchfab_Scene",
"nodes": [
0
]
}
],
"textures": [
{
"sampler": 0,
"source": 0
},
{
"sampler": 0,
"source": 1
}
]
}

BIN
public/models/lupine_plant/textures/lambert2SG_baseColor.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

BIN
public/models/lupine_plant/textures/lambert2SG_normal.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

66
src/components/World/World.js

@ -1,8 +1,10 @@
// from https://medium.com/nicasource/building-an-interactive-web-portfolio-with-vue-three-js-part-three-implementing-three-js-452cb375ef80 // from https://medium.com/nicasource/building-an-interactive-web-portfolio-with-vue-three-js-part-three-implementing-three-js-452cb375ef80
import axios from "axios";
import { SpotLight } from "three";
import * as TWEEN from "@tweenjs/tween.js"; import * as TWEEN from "@tweenjs/tween.js";
import axios from "axios";
import * as THREE from "three";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader";
import * as SkeletonUtils from "three/addons/utils/SkeletonUtils.js";
import { AppString } from "@/constants/app"; import { AppString } from "@/constants/app";
import { createCamera } from "./components/camera.js"; import { createCamera } from "./components/camera.js";
@ -14,16 +16,16 @@ import { Resizer } from "./systems/Resizer.js";
import { createControls } from "./systems/controls.js"; import { createControls } from "./systems/controls.js";
import { createRenderer } from "./systems/renderer.js"; import { createRenderer } from "./systems/renderer.js";
const ANIMATION_DURATION_SECS = 10; const ANIMATION_DURATION_SECS = 20;
const BASE32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; const BASE32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
const COLOR1 = "#42b883"; const COLOR1 = "#dddddd";
const COLOR2 = "#0055aa"; const COLOR2 = "#0055aa";
const PLATFORM_BORDER = 10; const PLATFORM_BORDER = 10;
const PLATFORM_EDGE_FOR_UNKNOWNS = 10; const PLATFORM_EDGE_FOR_UNKNOWNS = 10;
const PLATFORM_SIZE = 100; const PLATFORM_SIZE = 100;
function createLight() { function createLight() {
const light = new SpotLight(0xffffff, 0, 0, Math.PI / 8, 0.5, 0); const light = new THREE.SpotLight(0xffffff, 0, 0, Math.PI / 8, 0.5, 0);
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
light.tick = () => {}; light.tick = () => {};
return light; return light;
@ -38,8 +40,12 @@ class World {
this.scene = createScene(COLOR2); this.scene = createScene(COLOR2);
this.renderer = createRenderer(); this.renderer = createRenderer();
// necessary for models, says https://threejs.org/docs/index.html#examples/en/loaders/GLTFLoader
this.renderer.outputColorSpace = THREE.SRGBColorSpace;
this.light = null; this.light = null;
this.lights = []; this.lights = [];
this.bushes = [];
// Initializae Loop // Initializae Loop
this.loop = new Loop(this.camera, this.scene, this.renderer); this.loop = new Loop(this.camera, this.scene, this.renderer);
@ -82,6 +88,9 @@ class World {
light.updateMatrixWorld(); light.updateMatrixWorld();
light.target.updateMatrixWorld(); light.target.updateMatrixWorld();
}); });
this.lights.forEach((bush) => {
bush.updateMatrixWorld();
});
requestAnimationFrame(this.update); requestAnimationFrame(this.update);
} }
@ -100,6 +109,50 @@ class World {
// ratio of animation time to real time // ratio of animation time to real time
const fakeRealRatio = (ANIMATION_DURATION_SECS * 1000) / fullTimeMillis; 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 = this;
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 // calculate when lights shine on appearing claim area
for (const claim of resp.data.data) { for (const claim of resp.data.data) {
// claim is a GiveServerRecord (see endorserServer.ts) // claim is a GiveServerRecord (see endorserServer.ts)
@ -126,7 +179,7 @@ class World {
.to({ intensity: 100 }, 10) .to({ intensity: 100 }, 10)
.chain( .chain(
new TWEEN.Tween(light.position) new TWEEN.Tween(light.position)
.to({ y: 5 }, 1000) .to({ y: 5 }, 5000)
.onComplete(() => { .onComplete(() => {
this.scene.remove(light); this.scene.remove(light);
light.dispose(); light.dispose();
@ -135,7 +188,6 @@ class World {
.start(); .start();
this.lights = [...this.lights, light]; this.lights = [...this.lights, light];
} }
console.log("done adding cube");
} else { } else {
console.log( console.log(
"Got bad response status & data of", "Got bad response status & data of",

2
src/components/World/components/lights.js

@ -3,7 +3,7 @@ import { DirectionalLight, DirectionalLightHelper } from "three";
function createLights(color) { function createLights(color) {
const light = new DirectionalLight(color, 4); const light = new DirectionalLight(color, 4);
const lightHelper = new DirectionalLightHelper(light, 0); const lightHelper = new DirectionalLightHelper(light, 0);
light.position.set(0, 30, 30); light.position.set(60, 60, 30);
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
light.tick = () => {}; light.tick = () => {};

8
src/components/World/components/objects/terrain.js

@ -1,10 +1,4 @@
import { import { PlaneGeometry, MeshLambertMaterial, Mesh, TextureLoader } from "three";
BoxGeometry,
PlaneGeometry,
MeshLambertMaterial,
Mesh,
TextureLoader,
} from "three";
export function createTerrain(props) { export function createTerrain(props) {
const loader = new TextureLoader(); const loader = new TextureLoader();

Loading…
Cancel
Save