最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

three.js - cannot compute relative angle between objects in Three js - Stack Overflow

programmeradmin1浏览0评论

I have created a class to determine the angle of a point on the earth, relative to the earths center and the sun, given a tilt, and time. Time is a float number of days - the fraction is the time of day from 0 to 1.

import { Object3D, MathUtils, Scene, Vector3 } from 'three';
import { SimTimeCursor } from '../../classes/types.sim';
import { angle } from '../angle';

export class SunlightCalculator {
  private readonly daysInYear: number;
  private readonly minutesInDay: number;
  private readonly maxDeclination: number; // in radians

  private readonly earth: Object3D;
  private readonly earthRotationFrame: Object3D;
  private readonly earthTiltFrame: Object3D;
  private readonly sun: Object3D;
  private readonly scene: Scene;
  private readonly pointObject: Object3D;

  constructor(
    public name: string,
    cursor: SimTimeCursor,
    maxDeclinationDeg: number,
    private earthOrbitDistance: number = 1.496e8
  ) {
    this.daysInYear = cursor.cal.daysInYear;
    this.minutesInDay = cursor.cal.hoursInDay * 60;
    this.maxDeclination = MathUtils.degToRad(maxDeclinationDeg);

    this.scene = new Scene();
    this.sun = new Object3D();
    this.earth = new Object3D();
    this.earthRotationFrame = new Object3D();
    this.earthTiltFrame = new Object3D();
    this.earthTiltFrame.rotation.x = this.maxDeclination;

    this.pointObject = new Object3D();
    this.earth.add(this.pointObject);
    this.earthTiltFrame.add(this.earth);
    this.earthRotationFrame.add(this.earthTiltFrame);
    this.earth.position.set(this.earthOrbitDistance, 0, 0);
    this.sun.add(this.earthRotationFrame);
    this.scene.add(this.sun);
    [
      this.earth,
      this.sun,
      this.earthTiltFrame,
      this.earthRotationFrame,
      this.pointObject,
    ].forEach((o) => (o.matrixAutoUpdate = true));
  }

  public updateCelestialPositions(time: number): void {
    const minuteOfDay = this.minutesInDay * (time % 1);

    const yrot = (time * (2 * Math.PI)) / this.daysInYear;
    this.sun.rotation.y = yrot;

    this.earthRotationFrame.rotation.y = -this.sun.rotation.y;

    this.scene.updateMatrixWorld(true);

    this.earth.rotation.y = (minuteOfDay / this.minutesInDay) * (2 * Math.PI);
  }

  public computeSunAngle(time: number, point: Vector3): number {
    this.updateCelestialPositions(time);

    this.pointObject.position.copy(point);

    const earthCenter = new Vector3();
    this.earth.getWorldPosition(earthCenter);

    const pointWorld = new Vector3();
    this.pointObject.getWorldPosition(pointWorld);

    const sunVector = new Vector3();
    this.sun.getWorldPosition(sunVector);
    const vectorToSun = new Vector3()
      .subVectors(sunVector, earthCenter)
      .normalize();

    const vectorToPoint = new Vector3()
      .subVectors(pointWorld, earthCenter)
      .normalize();

    return vectorToSun.angleTo(vectorToPoint);
  }
}

The problem is that it just doesn't seem to be responsive to the tilt of the earth; tests reflect the same result regardless of the construtors' tilt angle. Is there a flaw in how I am chaining three js objects?

I have created a class to determine the angle of a point on the earth, relative to the earths center and the sun, given a tilt, and time. Time is a float number of days - the fraction is the time of day from 0 to 1.

import { Object3D, MathUtils, Scene, Vector3 } from 'three';
import { SimTimeCursor } from '../../classes/types.sim';
import { angle } from '../angle';

export class SunlightCalculator {
  private readonly daysInYear: number;
  private readonly minutesInDay: number;
  private readonly maxDeclination: number; // in radians

  private readonly earth: Object3D;
  private readonly earthRotationFrame: Object3D;
  private readonly earthTiltFrame: Object3D;
  private readonly sun: Object3D;
  private readonly scene: Scene;
  private readonly pointObject: Object3D;

  constructor(
    public name: string,
    cursor: SimTimeCursor,
    maxDeclinationDeg: number,
    private earthOrbitDistance: number = 1.496e8
  ) {
    this.daysInYear = cursor.cal.daysInYear;
    this.minutesInDay = cursor.cal.hoursInDay * 60;
    this.maxDeclination = MathUtils.degToRad(maxDeclinationDeg);

    this.scene = new Scene();
    this.sun = new Object3D();
    this.earth = new Object3D();
    this.earthRotationFrame = new Object3D();
    this.earthTiltFrame = new Object3D();
    this.earthTiltFrame.rotation.x = this.maxDeclination;

    this.pointObject = new Object3D();
    this.earth.add(this.pointObject);
    this.earthTiltFrame.add(this.earth);
    this.earthRotationFrame.add(this.earthTiltFrame);
    this.earth.position.set(this.earthOrbitDistance, 0, 0);
    this.sun.add(this.earthRotationFrame);
    this.scene.add(this.sun);
    [
      this.earth,
      this.sun,
      this.earthTiltFrame,
      this.earthRotationFrame,
      this.pointObject,
    ].forEach((o) => (o.matrixAutoUpdate = true));
  }

  public updateCelestialPositions(time: number): void {
    const minuteOfDay = this.minutesInDay * (time % 1);

    const yrot = (time * (2 * Math.PI)) / this.daysInYear;
    this.sun.rotation.y = yrot;

    this.earthRotationFrame.rotation.y = -this.sun.rotation.y;

    this.scene.updateMatrixWorld(true);

    this.earth.rotation.y = (minuteOfDay / this.minutesInDay) * (2 * Math.PI);
  }

  public computeSunAngle(time: number, point: Vector3): number {
    this.updateCelestialPositions(time);

    this.pointObject.position.copy(point);

    const earthCenter = new Vector3();
    this.earth.getWorldPosition(earthCenter);

    const pointWorld = new Vector3();
    this.pointObject.getWorldPosition(pointWorld);

    const sunVector = new Vector3();
    this.sun.getWorldPosition(sunVector);
    const vectorToSun = new Vector3()
      .subVectors(sunVector, earthCenter)
      .normalize();

    const vectorToPoint = new Vector3()
      .subVectors(pointWorld, earthCenter)
      .normalize();

    return vectorToSun.angleTo(vectorToPoint);
  }
}

The problem is that it just doesn't seem to be responsive to the tilt of the earth; tests reflect the same result regardless of the construtors' tilt angle. Is there a flaw in how I am chaining three js objects?

Share Improve this question asked Mar 14 at 23:46 Dave EdelhartDave Edelhart 1,1011 gold badge9 silver badges14 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

Looks that time calculation of minuteOfDay isn't correct

time % 1 always = 0;

Probably should be:

 // const minuteOfDay = this.minutesInDay * (time % 1);
 const minuteOfDay = time % this.minutesInDay;

Code sandbox:

https://codesandbox.io/p/sandbox/yxmnd7

发布评论

评论列表(0)

  1. 暂无评论