Merge branch 'master' of github.com:openglobus/openglobus

This commit is contained in:
Aigars Zeiza 2025-09-09 11:42:59 +03:00
commit 7eae2a5076
8 changed files with 170 additions and 373 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "@openglobus/og",
"version": "0.26.3",
"version": "0.27.7",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@openglobus/og",
"version": "0.26.3",
"version": "0.27.7",
"license": "MIT",
"devDependencies": {
"@babel/plugin-proposal-class-properties": "^7.18.6",

View File

@ -4,63 +4,48 @@
<title>OpenStreetMap Base Layer</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../../lib/og.css" type="text/css" />
<link rel="stylesheet" href="../../lib/og.css" type="text/css"/>
</head>
<body>
<div id="earth" style="width:100%;height:100%"></div>
<script type="module" id="og-sandbox-script">
import {
XYZ,
Globe,
Extent,
LonLat,
GlobusRgbTerrain,
control
} from "../../lib/og.es.js";
<div id="earth" style="width:100%;height:100%"></div>
<script type="module" id="og-sandbox-script">
import {
XYZ,
Globe,
Extent,
LonLat,
GlobusRgbTerrain,
control
} from "../../lib/og.es.js";
let osm = new XYZ("osm", {
isBaseLayer: true,
url: "http://tile.openstreetmap.org/{z}/{x}/{y}.png",
visibility: true,
attribution: 'Data @ OpenStreetMap contributors, ODbL',
maxNativeZoom: 19,
defaultTextures: [{ color: "#AAD3DF" }, { color: "#F2EFE9" }],
isSRGB: false,
shininess: 18,
specular: [0.00063, 0.00055, 0.00032],
ambient: [0.2, 0.2, 0.3],
diffuse: [0.9, 0.9, 0.7],
});
let osm = new XYZ("osm", {
isBaseLayer: true,
url: "http://tile.openstreetmap.org/{z}/{x}/{y}.png",
visibility: true,
attribution: 'Data @ OpenStreetMap contributors, ODbL',
maxNativeZoom: 19,
defaultTextures: [{color: "#AAD3DF"}, {color: "#F2EFE9"}],
isSRGB: false,
shininess: 18,
specular: [0.00063, 0.00055, 0.00032],
ambient: [0.2, 0.2, 0.3],
diffuse: [0.9, 0.9, 0.7],
});
var globus = new Globe({
target: "earth",
name: "Earth",
maxAltitude: 15000000,
terrain: new GlobusRgbTerrain(),
layers: [osm],
resourcesSrc: "../../external/og/lib/@openglobus/res",
fontsSrc: "../../external/og/lib/@openglobus/res/fonts"
});
var globus = new Globe({
target: "earth",
name: "Earth",
maxAltitude: 15000000,
terrain: new GlobusRgbTerrain(),
layers: [osm],
resourcesSrc: "../../external/og/lib/@openglobus/res",
fontsSrc: "../../external/og/lib/@openglobus/res/fonts"
});
globus.planet.viewExtent(new Extent(new LonLat(158.31010, 54.45445), new LonLat(158.55687, 54.56659)));
globus.planet.addControl(new control.DrawingSwitcher({
cornerStyle: {
color: "#0000FF",
},
centerStyle: {
color: "#00FF00",
},
outlineStyle: {
color: "#FF0000",
},
fillStyle: {
fillColor: "#00FFFF",
fillOpacity: 0.3,
},
}));
</script>
globus.planet.addControl(new control.DebugInfo());
globus.planet.addControl(new control.ToggleWireframe());
</script>
</body>
</html>

View File

@ -862,8 +862,8 @@ class Camera {
* @param {Vec2} pos - Screen X coordinate
* @returns {Vec3} - Direction vector
*/
public unproject2v(pos: Vec2) {
return this.unproject(pos.x, pos.y);
public unproject2v(pos: Vec2, dist?: number, outPos?: Vec3) {
return this.unproject(pos.x, pos.y, dist, outPos);
}
/**
@ -991,10 +991,15 @@ class Camera {
* @returns {number} - Size factor.
*/
public projectedSize(p: Vec3, r: number): number {
//
//@todo: orthographic
//
return Math.atan(r / this.eye.distance(p)) * this._projSizeConst;
// @todo: cleanup
if (this.isOrthographic) {
const m = this.frustums[0].projectionMatrix._m;
const orthoScale = this._height * m[5] * 0.5;
return r * orthoScale;
} else {
return Math.atan(r / this.eye.distance(p)) * this._projSizeConst;
}
}
/**

View File

@ -8,7 +8,7 @@ import {Vec2} from "../math/Vec2";
import {Vec3} from "../math/Vec3";
import {input} from "../input/input";
import {Plane} from "../math/Plane";
import { createEvents, type EventsHandler } from "../Events";
import {createEvents, type EventsHandler} from "../Events";
interface IMouseNavigationParams extends IControlParams {
fixedUp?: boolean;
@ -90,6 +90,8 @@ export class MouseNavigation extends Control {
protected _grabbedPoint: Vec3 | null;
protected _grabbedDist: number;
protected _targetZoomPoint: Vec3 | null;
protected _targetDragPoint: Vec3 | null;
@ -165,6 +167,7 @@ export class MouseNavigation extends Control {
this._lookPos = undefined;
this._grabbedPoint = null;
this._grabbedDist = 0;
this._targetZoomPoint = null;
this._targetDragPoint = null;
@ -326,24 +329,30 @@ export class MouseNavigation extends Control {
protected _onRDown = (e: IMouseState) => {
if (this.planet) {
this.planet.stopFlying();
this._targetRotationPoint = this._getTargetPoint(e.pos)!;
if (this._targetRotationPoint) {
const tp = this._getTargetPoint(e.pos);
this._targetRotationPoint = tp ? tp : null;
if (tp) {
this._targetZoomPoint = null;
this._targetDragPoint = null;
this.vel.set(0, 0, 0);
this._tUp = this._targetRotationPoint.getNormal();
this._tRad = this.planet.camera.eye.distance(this._targetRotationPoint);
this._tUp = tp.getNormal();
this._tRad = this.planet.camera.eye.distance(tp);
}
}
}
protected _getTargetPoint(p: Vec2): Vec3 | null {
if (this.planet) {
if (this.planet.camera.isOrthographic) {
return this.renderer!.getCartesianFromPixel(p) || null;
}
if (this.planet.camera.getAltitude() > 80000) {
return this.planet.getCartesianFromPixelEllipsoid(p) || null;
}
return this.planet.getCartesianFromPixelTerrain(p) || null;
}
return null;
@ -354,29 +363,58 @@ export class MouseNavigation extends Control {
this._targetRotationPoint = null;
this._targetDragPoint = null;
let _targetZoomPoint = this._getTargetPoint(e.pos);
if (!_targetZoomPoint)
return;
this._targetZoomPoint = _targetZoomPoint;
this._grabbedSphere.radius = this._targetZoomPoint.length();
let sx = e.x,
sy = e.y;
let cam = this.planet.camera;
if (cam.isOrthographic) {
//
//@todo make map coordinates under the pointer
//
sx = this.renderer!.handler.getWidth() * 0.5;
sy = this.renderer!.handler.getHeight() * 0.5;
let _targetZoomPoint = this._getTargetPoint(new Vec2(sx, sy));
if (!_targetZoomPoint) return;
this._targetZoomPoint = _targetZoomPoint;
this._grabbedSphere.radius = this._targetZoomPoint.length();
let zoomDist = cam.eye.distance(_targetZoomPoint);//this.renderer!.getDistanceFromPixel(new Vec2(sx, sy))!;
let dist = zoomDist;
let p1 = new Vec3();
let dir = cam.unproject(sx, sy, dist, p1);
const p0 = p1.sub(dir.scaleTo(dist));
_targetZoomPoint = new Ray(p0, dir).hitSphere(this._grabbedSphere);
if (!_targetZoomPoint) return;
this._targetZoomPoint = _targetZoomPoint;
} else {
let _targetZoomPoint = this._getTargetPoint(new Vec2(sx, sy));
if (!_targetZoomPoint) return;
this._targetZoomPoint = _targetZoomPoint;
this._grabbedSphere.radius = this._targetZoomPoint.length();
}
this._curPitch = cam.getPitch();
this._curYaw = cam.getYaw();
this._curRoll = cam.getRoll();
if (Math.sign(e.wheelDelta) !== this._wheelDirection) {
this.vel.scale(0.3);
this._currScreenPos.set(e.x, e.y);
this._currScreenPos.set(sx, sy);
this._wheelDirection = Math.sign(e.wheelDelta);
return;
}
this._currScreenPos.set(e.x, e.y);
this._currScreenPos.set(sx, sy);
this._wheelDirection = Math.sign(e.wheelDelta);
let scale = 20;
this._velInertia = 0.83;
@ -421,6 +459,14 @@ export class MouseNavigation extends Control {
if (!this._grabbedPoint) return;
this._targetDragPoint = this._grabbedPoint;
if (this.planet.camera.isOrthographic) {
this._grabbedDist = this.renderer!.getDistanceFromPixel(e.pos)!;
} else {
this._grabbedDist = this.renderer!.activeCamera.eye.distance(this._grabbedPoint);
}
this.renderer!.handler.canvas!.classList.add("ogGrabbingPoiner");
this._grabbedSphere.radius = this._grabbedPoint.length();
@ -441,10 +487,17 @@ export class MouseNavigation extends Control {
protected _onLHold = (e: IMouseState) => {
if (this._grabbedPoint && this.planet) {
let cam = this.planet.camera;
if (cam.slope > MIN_SLOPE) {
let _targetDragPoint = new Ray(cam.eye, e.direction).hitSphere(this._grabbedSphere);
if (cam.isOrthographic) {
const dist = this._grabbedDist;
const p1 = new Vec3();
const dir = cam.unproject(e.x, e.y, dist, p1);
const p0 = p1.sub(dir.scaleTo(dist));
const _targetDragPoint = new Ray(p0, dir).hitSphere(this._grabbedSphere);
if (!_targetDragPoint) {
return;
@ -452,15 +505,34 @@ export class MouseNavigation extends Control {
this._targetDragPoint = _targetDragPoint;
let newEye = new Vec3();
let rot = Quat.getRotationBetweenVectors(
this._targetDragPoint.getNormal(),
this._grabbedPoint.getNormal()
);
let newEye = rot.mulVec3(cam.eye);
this.force = newEye.sub(cam.eye).scale(this.dragInertia);
} else if (cam.slope > MIN_SLOPE) {
this._grabbedDist = cam.eye.distance(this._grabbedPoint);
let dir = cam.unproject(e.x, e.y, this._grabbedDist);
let _targetDragPoint = new Ray(cam.eye, dir).hitSphere(this._grabbedSphere);
if (!_targetDragPoint) {
return;
}
this._targetDragPoint = _targetDragPoint;
let rot = Quat.getRotationBetweenVectors(
this._targetDragPoint.getNormal(),
this._grabbedPoint.getNormal()
);
newEye.copy(rot.mulVec3(cam.eye));
let newEye = rot.mulVec3(cam.eye);
this.force = newEye.sub(cam.eye).scale(this.dragInertia);
} else {
let p0 = this._grabbedPoint,
p1 = Vec3.add(p0, cam.getRight()),
@ -551,22 +623,6 @@ export class MouseNavigation extends Control {
let vel_normal = this.vel.getNormal();
let velDir = Math.sign(vel_normal.dot(cam.getForward()));
//let dist = a.distance(eye);
// let mult = 50;
//
// if (dist <= 1 || cam.getAltitude() < 2) {
// mult = 1;
// } else if (dist < 10) {
// mult = 5;
// } else if (dist < 20) {
// mult = 10;
// }
// let maxVel = dist * mult;
// if (this.vel.length() > maxVel) {
// this.vel = vel_normal.scaleTo(maxVel);
// }
let d_v = this.vel.scaleTo(this.dt);
// if camera eye position under the dome of the grabbed sphere
@ -604,7 +660,7 @@ export class MouseNavigation extends Control {
cam.setPitchYawRoll(this._curPitch, this._curYaw, this._curRoll);
cam.update();
let dirCurr = cam.unproject2v(this._currScreenPos);
let dirCurr = cam.unproject2v(this._currScreenPos, cam.eye.distance(this._targetZoomPoint));
let dirNew = a.sub(cam.eye).normalize();
let px0 = new Vec3();
@ -621,7 +677,18 @@ export class MouseNavigation extends Control {
// let px0 = new Ray(cam.eye, dirCurr).hitSphere(this._grabbedSphere)!;
// let px1 = new Ray(cam.eye, dirNew).hitSphere(this._grabbedSphere)!;
}
cam.checkTerrainCollision();
if (cam.isOrthographic) {
//
//@todo make map coordinates under the pointer
//
let alt = cam.getAltitude();
if (alt) {
cam.focusDistance = Math.abs(alt);
}
}
}
}

View File

@ -1,269 +0,0 @@
// import {Sphere} from "../bv/Sphere";
// import {Key} from "../Lock";
// import {Quat} from "../math/Quat";
// import {Vec3} from "../math/Vec3";
// import {Control, IControlParams} from "./Control";
// import {IStepForward, MouseNavigation} from "./MouseNavigation";
//
// interface IMouseWheelZoomControl extends IControlParams {
// minSlope?: number;
// }
//
// export class MouseWheelZoomControl extends Control {
// protected grabbedPoint: Vec3;
// protected _eye0: Vec3;
// protected pointOnEarth: Vec3;
// protected earthUp: Vec3;
// public inertia: number;
// protected grabbedSpheroid: Sphere;
// protected qRot: Quat;
// protected scaleRot: number;
// protected distDiff: number;
// protected stepsCount: number;
// protected stepsForward: IStepForward[] | null;
// protected stepIndex: number;
// protected _lmbDoubleClickActive: boolean;
// protected minSlope: number;
// protected _keyLock: Key;
// protected _deactivate: boolean;
// protected _move: number;
//
// constructor(options: IMouseWheelZoomControl = {}) {
// super(options);
//
// this._name = "MouseWheelZoomControl";
//
// this.grabbedPoint = new Vec3();
// this._eye0 = new Vec3();
// this.pointOnEarth = new Vec3();
// this.earthUp = new Vec3();
// this.inertia = 0.007;
// this.grabbedSpheroid = new Sphere();
// this.planet = null;
// this.qRot = new Quat();
// this.scaleRot = 0.0;
//
// this.distDiff = 0.3;
// this.stepsCount = 8;
// this.stepsForward = null;
// this.stepIndex = 0;
//
// this._lmbDoubleClickActive = true;
//
// this.minSlope = options.minSlope || 0.1;
//
// this._keyLock = new Key();
//
// this._deactivate = false;
//
// this._move = 0;
// }
//
// public override oninit() {
// let zoomDiv = document.createElement("div"),
// btnZoomIn = document.createElement("button"),
// btnZoomOut = document.createElement("button");
//
// zoomDiv.className = "ogZoomControl";
// btnZoomIn.className = "ogZoomButton ogZoomIn";
// btnZoomOut.className = "ogZoomButton ogZoomOut";
//
// zoomDiv.appendChild(btnZoomIn);
// zoomDiv.appendChild(btnZoomOut);
//
// this.renderer!.div!.appendChild(zoomDiv);
//
// btnZoomIn.addEventListener("mousedown", () => this.zoomIn());
// btnZoomIn.addEventListener("mouseup", () => this.stopZoom());
//
// btnZoomOut.addEventListener("mousedown", () => this.zoomOut());
// btnZoomOut.addEventListener("mouseup", () => this.stopZoom());
//
// btnZoomIn.addEventListener("touchstart", (e: TouchEvent) => {
// e.preventDefault();
// this.zoomIn();
// });
// btnZoomIn.addEventListener("touchend", (e: TouchEvent) => {
// e.preventDefault();
// this.stopZoom();
// });
// btnZoomIn.addEventListener("touchcancel", (e: TouchEvent) => {
// e.preventDefault();
// this.stopZoom();
// });
//
// btnZoomOut.addEventListener("touchstart", (e: TouchEvent) => {
// e.preventDefault();
// this.zoomOut();
// });
// btnZoomOut.addEventListener("touchend", (e: TouchEvent) => {
// e.preventDefault();
// this.stopZoom();
// });
// btnZoomOut.addEventListener("touchcancel", (e: TouchEvent) => {
// e.preventDefault();
// this.stopZoom();
// });
//
// this.renderer!.events.on("draw", this._draw, this);
// }
//
// /**
// * Planet zoom in.
// * @public
// */
// public zoomIn() {
// if (this.stepIndex) {
// return;
// }
//
// this.planet!.stopFlying();
//
// this.stopRotation();
//
// this._deactivate = true;
//
// this.planet!.layerLock.lock(this._keyLock);
// this.planet!.terrainLock.lock(this._keyLock);
// this.planet!._normalMapCreator.lock(this._keyLock);
//
// this.stepsForward = MouseNavigation.getMovePointsFromPixelTerrain(
// this.planet!.camera,
// this.planet!,
// this.stepsCount,
// this.distDiff,
// this.renderer!.handler.getCenter(),
// true,
// null
// ) || null;
//
// if (this.stepsForward) {
// this.stepIndex = this.stepsCount;
// }
// }
//
// /**
// * Planet zoom out.
// * @public
// */
// public zoomOut() {
// if (this.stepIndex) {
// return;
// }
//
// this.planet!.stopFlying();
//
// this.stopRotation();
//
// this._deactivate = true;
//
// this.planet!.layerLock.lock(this._keyLock);
// this.planet!.terrainLock.lock(this._keyLock);
// this.planet!._normalMapCreator.lock(this._keyLock);
//
// this.stepsForward = MouseNavigation.getMovePointsFromPixelTerrain(
// this.planet!.camera,
// this.planet!,
// this.stepsCount,
// this.distDiff,
// this.renderer!.handler.getCenter(),
// false,
// null
// ) || null;
//
// if (this.stepsForward) {
// this.stepIndex = this.stepsCount;
// }
// }
//
// public stopRotation() {
// this.qRot.clear();
// this.planet!.layerLock.free(this._keyLock);
// this.planet!.terrainLock.free(this._keyLock);
// this.planet!._normalMapCreator.free(this._keyLock);
// }
//
// public stopZoom() {
// this._move = 0;
//
// this.planet!.layerLock.free(this._keyLock);
// this.planet!.terrainLock.free(this._keyLock);
// this.planet!._normalMapCreator.free(this._keyLock);
// }
//
// protected _draw() {
// if (this._active) {
// let r = this.renderer!;
// let cam = this.planet!.camera;
// let prevEye = cam.eye.clone();
//
// if (this.stepIndex) {
// r.controlsBag.scaleRot = 1.0;
// let sf = this.stepsForward![this.stepsCount - this.stepIndex--];
//
// let maxAlt = cam.maxAltitude + this.planet!.ellipsoid.equatorialSize;
// let minAlt = cam.minAltitude + this.planet!.ellipsoid.equatorialSize;
// const camAlt = sf.eye.length();
// if (camAlt > maxAlt || camAlt < minAlt) {
// return;
// }
//
// cam.eye = sf.eye;
// cam._u = sf.v;
// cam._r = sf.u;
// cam._b = sf.n;
//
// cam.checkTerrainCollision();
//
// cam.update();
// } else {
// if (this._deactivate) {
// this._deactivate = false;
//
// this.planet!.layerLock.free(this._keyLock);
// this.planet!.terrainLock.free(this._keyLock);
// this.planet!._normalMapCreator.free(this._keyLock);
// }
// }
//
// if (r.events.mouseState.leftButtonDown || !this.scaleRot) {
// return;
// }
//
// this.scaleRot -= this.inertia;
// if (this.scaleRot <= 0.0) {
// this.scaleRot = 0.0;
// } else {
//
// r.controlsBag.scaleRot = this.scaleRot;
//
// let rot = this.qRot
// .slerp(Quat.IDENTITY, 1.0 - this.scaleRot * this.scaleRot * this.scaleRot)
// .normalize();
//
// if (!(rot.x || rot.y || rot.z)) {
// this.scaleRot = 0.0;
// }
//
// cam.eye = rot.mulVec3(cam.eye);
// cam._u = rot.mulVec3(cam._u);
// cam._r = rot.mulVec3(cam._r);
// cam._b = rot.mulVec3(cam._b);
//
// cam.checkTerrainCollision();
//
// cam.update();
// }
//
// if (cam.eye.distance(prevEye) / cam.getAltitude() > 0.01) {
// this.planet!.layerLock.lock(this._keyLock);
// this.planet!.terrainLock.lock(this._keyLock);
// this.planet!._normalMapCreator.lock(this._keyLock);
// } else {
// this.planet!.layerLock.free(this._keyLock);
// this.planet!.terrainLock.free(this._keyLock);
// this.planet!._normalMapCreator.free(this._keyLock);
// }
// }
// }
// }

View File

@ -186,7 +186,6 @@ export class SimpleNavigation extends Control {
protected _onRDown = (e: IMouseState) => {
if (this.renderer) {
this.stop();
this._lookPos = undefined;
this._lookPos = this.renderer.getCartesianFromPixel(e.pos);
if (this._lookPos) {
this._up = Vec3.UP;

View File

@ -281,18 +281,28 @@ class Node {
let h = Math.abs(cam._lonLat.height);
let horizonDist = cam.eye.length2() - planet.ellipsoid.polarSizeSqr;
horizonDist = horizonDist < 106876472875.63281 * planet._heightFactor ? 106876472875.63281 * planet._heightFactor : horizonDist;
let maxDist = 106876472875.63281 * planet._heightFactor;
horizonDist = horizonDist < maxDist ? maxDist : horizonDist;
let altVis = seg.tileZoom < 2 || seg.tileZoom > 19 ||
/* Could be replaced with camera frustum always looking down check,
and not to go through nodes from the opposite of the globe*/
(seg.tileZoom < 6 && !seg.terrainReady);
altVis = altVis ||
cam.eye.distance2(seg._sw) < horizonDist ||
cam.eye.distance2(seg._nw) < horizonDist ||
cam.eye.distance2(seg._ne) < horizonDist ||
cam.eye.distance2(seg._se) < horizonDist;
if (cam.isOrthographic) {
let f = cam.getForward();
altVis = altVis ||
f.dot(seg._sw.getNormal()) < -0 ||
f.dot(seg._nw.getNormal()) < -0 ||
f.dot(seg._ne.getNormal()) < -0 ||
f.dot(seg._se.getNormal()) < -0;
} else {
altVis = altVis ||
cam.eye.distance2(seg._sw) < horizonDist ||
cam.eye.distance2(seg._nw) < horizonDist ||
cam.eye.distance2(seg._ne) < horizonDist ||
cam.eye.distance2(seg._se) < horizonDist;
}
if ((this.inFrustum && (altVis || h > 10000.0)) || this._cameraInside) {
this.quadTreeStrategy.collectVisibleNode(this);

View File

@ -250,7 +250,7 @@ export class QuadTreeStrategy {
this._renderedNodes = [];
}
protected _clearRenderNodesInFrustum() {
protected _clearRenderNodesInFrustum() {1
for (let i = 0, len = this._renderedNodesInFrustum.length; i < len; i++) {
this._renderedNodesInFrustum[i].length = 0;
this._renderedNodesInFrustum[i] = [];
@ -258,7 +258,7 @@ export class QuadTreeStrategy {
}
protected _collectRenderedNodesMaxZoom(cam: PlanetCamera) {
if (cam.slope > this.minEqualZoomCameraSlope && cam._lonLat.height < this.maxEqualZoomAltitude && cam._lonLat.height > this.minEqualZoomAltitude) {
if (cam.isOrthographic || cam.slope > this.minEqualZoomCameraSlope && cam._lonLat.height < this.maxEqualZoomAltitude && cam._lonLat.height > this.minEqualZoomAltitude) {
this.minCurrZoom = this.maxCurrZoom;