Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add close-up variant of the sun-earth line #32

Merged
merged 1 commit into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 53 additions & 44 deletions src/grasp-seasons/3d-models/sun-earth-line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@ import * as THREE from "three";
import { IModelParams } from "../types";
import * as c from "./constants";

const POINTER_RADIUS = 200000 * c.SF;
const POINTER_TUBE = 60000 * c.SF;
const HEIGHT = 1; // arrow will be rescaled dynamically based on earth-sun distance that changes through the year
const RADIUS = 1500000 * c.SF;
const LARGE_HEAD_RADIUS = RADIUS * 7;
const LARGE_HEAD_HEIGHT = HEIGHT * 0.2;
const SMALL_HEAD_RADIUS = RADIUS * 5;
const SMALL_HEAD_HEIGHT = HEIGHT * 0.03;
const SMALL_ARROW_SCALE = 0.15;

export default class {
_arrow!: THREE.Object3D;
_arrowHead!: THREE.Object3D;
_smallArrowHead!: THREE.Object3D;
_arrowMesh!: THREE.Object3D;
_earthRadius: number;
_pointerMesh!: THREE.Object3D;
_refVector: THREE.Vector3;
_earthPos?: THREE.Vector3;

rootObject!: THREE.Object3D;
constructor(props: IModelParams) {
const simple = props.type === "orbit-view";
Expand All @@ -19,74 +29,73 @@ export default class {
this._earthRadius = simple ? c.SIMPLE_EARTH_RADIUS : c.EARTH_RADIUS;

this._init3DObjects(simple);
this.setOrbitViewStyle();
}

setEarthPos(newPos: THREE.Vector3) {
const sunRealRadius = c.SIMPLE_SUN_RADIUS * 1.41; // match edge of the Sun PNG-based sprite
this._earthPos = newPos.clone();
// match edge of the Sun PNG-based sprite
const sunRealRadius = c.SIMPLE_SUN_RADIUS * (this._smallArrowHead.visible ? 1.1 : 1.41);
const len = newPos.length() - this._earthRadius - sunRealRadius;
let angleDiff = newPos.angleTo(this._refVector);
if (newPos.z < 0) angleDiff *= -1;
this.rootObject.rotation.y = angleDiff;
if (this._pointerMesh) {
this._pointerMesh.position.x = -len;
}
this._arrow.position.x = -len - sunRealRadius;
this._arrow.scale.x = len;
}

_init3DObjects(simple: boolean) {
this._arrow = this._initArrow(simple);

const container = new THREE.Object3D();
container.add(this._arrow);
const pivot = new THREE.Object3D();
pivot.add(container);

if (!simple) {
this._pointerMesh = this._initPointer();
container.add(this._pointerMesh);
}
pivot.add(this._arrow);

this.rootObject = pivot;
}

_initPointer() {
const container = new THREE.Object3D();

for (let i = 2; i < 8; i++) {
const radius = POINTER_RADIUS * Math.pow(i, 1.5);
const material = new THREE.MeshPhongMaterial({ color: c.SUN_COLOR, transparent: true, opacity: 1 - i * 0.125 });
const geometry = new THREE.TorusGeometry(radius, POINTER_TUBE, 6, 16 * i);
const mesh = new THREE.Mesh(geometry, material);
mesh.rotation.y = Math.PI * 0.5;
// Based on circle equation: x^2 + y^2 = r^2
mesh.position.x = Math.sqrt(Math.pow(this._earthRadius, 2) - Math.pow(radius, 2)) - this._earthRadius;
container.add(mesh);
}

return container;
}

_initArrow(simple: boolean) {
const HEIGHT = 1; // arrow will be rescaled dynamically based on earth-sun distance that changes through the year
const RADIUS = simple ? 1500000 * c.SF : 100000 * c.SF;
const HEAD_RADIUS = RADIUS * (simple ? 7 : 2);
const HEAD_HEIGHT = HEIGHT * 0.2;
const geometry = new THREE.CylinderGeometry(RADIUS, RADIUS, HEIGHT, 32);
const material = new THREE.MeshPhongMaterial({ color: 0xff0000, emissive: c.SUN_COLOR });
const mesh = new THREE.Mesh(geometry, material);
const material = new THREE.MeshPhongMaterial({ color: c.SUN_COLOR, emissive: c.SUN_COLOR });
this._arrowMesh = new THREE.Mesh(geometry, material);

const arrowHeadGeo = new THREE.CylinderGeometry(0, LARGE_HEAD_RADIUS, LARGE_HEAD_HEIGHT, 32);
this._arrowHead = new THREE.Mesh(arrowHeadGeo, material);
this._arrowHead.position.y = HEIGHT * 0.5;
this._arrowMesh.add(this._arrowHead);

const arrowHeadGeo = new THREE.CylinderGeometry(0, HEAD_RADIUS, HEAD_HEIGHT, 32);
const arrowHeadMesh = new THREE.Mesh(arrowHeadGeo, material);
arrowHeadMesh.position.y = HEIGHT * 0.5;
mesh.add(arrowHeadMesh);
const smallArrowHeadGeo = new THREE.CylinderGeometry(0, SMALL_HEAD_RADIUS, SMALL_HEAD_HEIGHT, 32);
this._smallArrowHead = new THREE.Mesh(smallArrowHeadGeo, material);
this._smallArrowHead.position.y = HEIGHT * 0.5;
this._arrowMesh.add(this._smallArrowHead);

mesh.position.x = 0.5 * HEIGHT + 0.5 * HEAD_HEIGHT;
mesh.rotation.z = Math.PI * 0.5;
this._arrowMesh.position.x = 0.5 * HEIGHT + 0.5 * LARGE_HEAD_HEIGHT;
this._arrowMesh.rotation.z = Math.PI * 0.5;

const container = new THREE.Object3D();
container.add(mesh);
container.add(this._arrowMesh);

return container;
}

setCloseUpStyle() {
this._arrowMesh.scale.z = SMALL_ARROW_SCALE;
this._arrowMesh.scale.x = SMALL_ARROW_SCALE;
this._smallArrowHead.visible = true;
this._arrowHead.visible = false;
this._arrowMesh.position.x = 0.5 * HEIGHT + 0.5 * SMALL_HEAD_HEIGHT;
if (this._earthPos) {
this.setEarthPos(this._earthPos);
}
}

setOrbitViewStyle() {
this._arrowMesh.scale.z = 1;
this._arrowMesh.scale.x = 1;
this._smallArrowHead.visible = false;
this._arrowHead.visible = true;
this._arrowMesh.position.x = 0.5 * HEIGHT + 0.5 * LARGE_HEAD_HEIGHT;
if (this._earthPos) {
this.setEarthPos(this._earthPos);
}
}
}
3 changes: 2 additions & 1 deletion src/grasp-seasons/3d-views/orbit-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ export default class OrbitView extends BaseView {

setupEarthCloseUpView() {
this.registerInteractionHandler(this.latLogDraggingInteraction);
this.sunEarthLine.rootObject.visible = false;
this.monthLabels.forEach((label) => label.visible = false);
this.sunEarthLine.setCloseUpStyle();
this.earthAxis.setCloseUpStyle();
this.latLongMarker.setCloseUpStyle();
}
Expand All @@ -142,6 +142,7 @@ export default class OrbitView extends BaseView {
this.registerInteractionHandler(this.earthDraggingInteraction);
this.sunEarthLine.rootObject.visible = true;
this.monthLabels.forEach((label) => label.visible = true);
this.sunEarthLine.setOrbitViewStyle();
this.earthAxis.setOrbitViewStyle();
this.latLongMarker.setOrbitViewStyle();
}
Expand Down
Loading