mirror of
https://github.com/filecoin-project/slate.git
synced 2024-12-25 18:13:10 +03:00
189 lines
5.3 KiB
JavaScript
189 lines
5.3 KiB
JavaScript
import * as THREE from "three";
|
|
|
|
import OrbitControls from "~/common/three/orbital.js";
|
|
import GlobePoints from "~/common/three/points.json";
|
|
import CountryPoints from "~/common/three/countries.json";
|
|
|
|
const convertFlatCoordsToSphereCoords = ({ globe, x, y }) => {
|
|
let latitude = ((x - globe.width) / globe.width) * -180;
|
|
let longitude = ((y - globe.height) / globe.height) * -90;
|
|
latitude = (latitude * Math.PI) / 180;
|
|
longitude = (longitude * Math.PI) / 180;
|
|
const radius = Math.cos(longitude) * globe.radius;
|
|
|
|
return {
|
|
x: Math.cos(latitude) * radius,
|
|
y: Math.sin(longitude) * globe.radius,
|
|
z: Math.sin(latitude) * radius,
|
|
};
|
|
};
|
|
|
|
const convertLatLonToSphereCoords = ({ globe, lon, lat }) => {
|
|
let latitude = (-lat * Math.PI) / 180;
|
|
let longitude = (lon * Math.PI) / 180;
|
|
const radius = Math.cos(longitude) * globe.radius;
|
|
|
|
return {
|
|
x: Math.cos(latitude) * radius,
|
|
y: Math.sin(longitude) * globe.radius,
|
|
z: Math.sin(latitude) * radius,
|
|
};
|
|
};
|
|
|
|
const getViewportData = (width, height) => {
|
|
const viewSize = height;
|
|
const aspectRatio = width / height;
|
|
|
|
return {
|
|
viewSize: viewSize,
|
|
aspectRatio: aspectRatio,
|
|
left: (-aspectRatio * viewSize) / 2,
|
|
right: (aspectRatio * viewSize) / 2,
|
|
top: viewSize / 2,
|
|
bottom: viewSize / -2,
|
|
near: -2048,
|
|
far: 2048,
|
|
};
|
|
};
|
|
|
|
export default class GLComponent {
|
|
constructor(props) {
|
|
this.state = {
|
|
mountedNodes: [],
|
|
width: props.width,
|
|
height: props.height,
|
|
scene: undefined,
|
|
renderer: undefined,
|
|
container: undefined,
|
|
camera: undefined,
|
|
controls: undefined,
|
|
measurements: undefined,
|
|
...props,
|
|
};
|
|
}
|
|
|
|
setState(newProps) {
|
|
this.state = { ...this.state, ...newProps };
|
|
}
|
|
|
|
unmount() {
|
|
this.state.mountedNodes = null;
|
|
this.state.width = null;
|
|
this.state.height = null;
|
|
this.state.scene = null;
|
|
this.state.renderer = null;
|
|
this.state.container = null;
|
|
this.state.camera = null;
|
|
this.state.controls = null;
|
|
this.state.measurements = null;
|
|
this.render = () => {
|
|
console.log("Error: If this is getting called, that is bad.");
|
|
};
|
|
}
|
|
|
|
async mount() {
|
|
this.state.renderer = new THREE.WebGLRenderer({
|
|
antialias: true,
|
|
alpha: true,
|
|
});
|
|
this.state.renderer.shadowMap.enabled = true;
|
|
this.state.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
|
this.state.renderer.physicallyBasedShading = true;
|
|
this.state.renderer.setClearColor(0x000000, 0);
|
|
this.state.renderer.setPixelRatio(window.devicePixelRatio);
|
|
this.state.renderer.setSize(this.state.width, this.state.height);
|
|
this.state.scene = new THREE.Scene();
|
|
this.state.container.appendChild(this.state.renderer.domElement);
|
|
|
|
const viewport = getViewportData(this.state.width, this.state.height);
|
|
|
|
this.state.camera = new THREE.OrthographicCamera(
|
|
viewport.left,
|
|
viewport.right,
|
|
viewport.top,
|
|
viewport.bottom,
|
|
viewport.near,
|
|
viewport.far
|
|
);
|
|
|
|
this.state.camera.position.x = 0.2;
|
|
this.state.camera.position.y = 0.25;
|
|
this.state.camera.position.z = 0.2;
|
|
|
|
this.state.controls = new OrbitControls(
|
|
this.state.camera,
|
|
this.state.renderer.domElement
|
|
);
|
|
|
|
const hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x888888, 0.9);
|
|
this.state.scene.add(hemisphereLight);
|
|
|
|
const ambientLight = new THREE.AmbientLight(0x888888, 0.7);
|
|
this.state.scene.add(ambientLight);
|
|
}
|
|
|
|
firstRender() {
|
|
const mergedGeometry = new THREE.Geometry();
|
|
const pointGeometry = new THREE.SphereGeometry(2, 1, 1);
|
|
const pointMaterial = new THREE.MeshBasicMaterial({
|
|
color: "#0047FF",
|
|
});
|
|
|
|
let { points } = GlobePoints;
|
|
for (let point of points) {
|
|
const { x, y, z } = convertFlatCoordsToSphereCoords({
|
|
x: point.x,
|
|
y: point.y,
|
|
globe: { radius: 188, width: 4098 / 2, height: 1968 / 2 },
|
|
});
|
|
|
|
pointGeometry.translate(x, y, z);
|
|
mergedGeometry.merge(pointGeometry);
|
|
pointGeometry.translate(-x, -y, -z);
|
|
}
|
|
|
|
const globeShape = new THREE.Mesh(mergedGeometry, pointMaterial);
|
|
this.state.mountedNodes.push(globeShape);
|
|
this.state.scene.add(globeShape);
|
|
|
|
if (this.state.countries) {
|
|
const mergedCountryGeometry = new THREE.Geometry();
|
|
const pointCountryGeometry = new THREE.SphereGeometry(4, 7, 7);
|
|
const countryMaterial = new THREE.MeshBasicMaterial({
|
|
color: "black",
|
|
});
|
|
|
|
points = CountryPoints.points;
|
|
for (let point of points) {
|
|
const { x, y, z } = convertLatLonToSphereCoords({
|
|
lat: point.lon,
|
|
lon: point.lat,
|
|
globe: { radius: 188, width: 4098 / 2, height: 1968 / 2 },
|
|
});
|
|
|
|
pointCountryGeometry.translate(x, y, z);
|
|
mergedCountryGeometry.merge(pointCountryGeometry);
|
|
pointCountryGeometry.translate(-x, -y, -z);
|
|
}
|
|
|
|
const countryShape = new THREE.Mesh(
|
|
mergedCountryGeometry,
|
|
countryMaterial
|
|
);
|
|
this.state.mountedNodes.push(countryShape);
|
|
this.state.scene.add(countryShape);
|
|
}
|
|
}
|
|
|
|
axis = new THREE.Vector3(0, 1, 0).normalize();
|
|
|
|
render() {
|
|
this.state.mountedNodes.forEach((n) => {
|
|
const object = this.state.scene.getObjectById(n.id);
|
|
object.rotateOnAxis(this.axis, Math.PI * 0.001);
|
|
});
|
|
|
|
this.state.renderer.render(this.state.scene, this.state.camera);
|
|
}
|
|
}
|