mirror of
https://github.com/openglobus/openglobus.git
synced 2025-12-08 19:25:27 +00:00
Merge branch 'master' of github.com:openglobus/openglobus
This commit is contained in:
commit
186dc0528c
@ -23,7 +23,16 @@ export default [
|
||||
|
||||
languageOptions: {
|
||||
globals: {
|
||||
window: true
|
||||
window: true,
|
||||
vi: true,
|
||||
test: true,
|
||||
expect: true,
|
||||
describe: true,
|
||||
it: true,
|
||||
beforeEach: true,
|
||||
afterEach: true,
|
||||
beforeAll: true,
|
||||
afterAll: true
|
||||
},
|
||||
|
||||
parser: tsParser,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@openglobus/og",
|
||||
"version": "0.26.6",
|
||||
"version": "0.27.7",
|
||||
"description": "[openglobus](https://www.openglobus.org/) is a javascript/typescript library designed to display interactive 3d maps and planets with map tiles, imagery and vector data, markers, and 3D objects. It uses the WebGL technology, open source, and completely free.",
|
||||
"main": "lib/og.es.js",
|
||||
"types": "lib/index.d.ts",
|
||||
|
||||
BIN
sandbox/modelLoad/amort_left_back.glb
Normal file
BIN
sandbox/modelLoad/amort_left_back.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/amort_left_front.glb
Normal file
BIN
sandbox/modelLoad/amort_left_front.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/amort_right_back.glb
Normal file
BIN
sandbox/modelLoad/amort_right_back.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/amort_right_front.glb
Normal file
BIN
sandbox/modelLoad/amort_right_front.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/cam0_base.glb
Normal file
BIN
sandbox/modelLoad/cam0_base.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/cam0_head.glb
Normal file
BIN
sandbox/modelLoad/cam0_head.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/cam0_joint.glb
Normal file
BIN
sandbox/modelLoad/cam0_joint.glb
Normal file
Binary file not shown.
@ -32,9 +32,227 @@ import {
|
||||
Easing
|
||||
} from "../../lib/og.es.js";
|
||||
|
||||
// Create HTML interface for sliders
|
||||
function createSliderControls() {
|
||||
// Main container for two columns
|
||||
const controlsContainer = document.createElement('div');
|
||||
controlsContainer.style.cssText = `
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
pointer-events: none;
|
||||
z-index: 1000;
|
||||
`;
|
||||
|
||||
// Left column (Suspension, Wheel Steering)
|
||||
const leftColumn = document.createElement('div');
|
||||
leftColumn.style.cssText = `
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
margin-left: 10px;
|
||||
pointer-events: auto;
|
||||
`;
|
||||
|
||||
// Right column (Camera, Scaner)
|
||||
const rightColumn = document.createElement('div');
|
||||
rightColumn.style.cssText = `
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
margin-right: 10px;
|
||||
align-items: flex-end;
|
||||
pointer-events: auto;
|
||||
`;
|
||||
|
||||
// Function to create slider group
|
||||
function createSliderGroup(title, sliders) {
|
||||
const groupContainer = document.createElement('div');
|
||||
groupContainer.style.cssText = `
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
min-width: 280px;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
color: white;
|
||||
font-family: Arial, sans-serif;
|
||||
`;
|
||||
|
||||
const groupTitle = document.createElement('h3');
|
||||
groupTitle.textContent = title;
|
||||
groupTitle.style.cssText = `
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
color: #ffd700;
|
||||
`;
|
||||
groupContainer.appendChild(groupTitle);
|
||||
|
||||
sliders.forEach(slider => {
|
||||
groupContainer.appendChild(slider);
|
||||
});
|
||||
|
||||
return groupContainer;
|
||||
}
|
||||
|
||||
// Function to create individual slider
|
||||
function createSlider(id, label, min, max, value, step = '0.1') {
|
||||
const mainContainer = document.createElement('div');
|
||||
mainContainer.style.cssText = `
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
`;
|
||||
|
||||
const labelElement = document.createElement('label');
|
||||
labelElement.textContent = label;
|
||||
labelElement.style.cssText = `
|
||||
font-size: 11px;
|
||||
color: #ccc;
|
||||
margin-bottom: 2px;
|
||||
`;
|
||||
|
||||
const sliderContainer = document.createElement('div');
|
||||
sliderContainer.style.cssText = `
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
`;
|
||||
|
||||
const slider = document.createElement('input');
|
||||
slider.type = 'range';
|
||||
slider.min = min;
|
||||
slider.max = max;
|
||||
slider.value = value;
|
||||
slider.step = step;
|
||||
slider.id = id;
|
||||
slider.style.cssText = `
|
||||
width: 180px;
|
||||
height: 20px;
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
const valueElement = document.createElement('span');
|
||||
valueElement.id = id + 'Value';
|
||||
valueElement.textContent = value + '°';
|
||||
valueElement.style.cssText = `
|
||||
font-size: 10px;
|
||||
color: #aaa;
|
||||
min-width: 40px;
|
||||
text-align: right;
|
||||
`;
|
||||
|
||||
mainContainer.appendChild(labelElement);
|
||||
sliderContainer.appendChild(slider);
|
||||
sliderContainer.appendChild(valueElement);
|
||||
mainContainer.appendChild(sliderContainer);
|
||||
|
||||
return mainContainer;
|
||||
}
|
||||
|
||||
// Suspension group
|
||||
const suspensionSliders = [
|
||||
createSlider('rollSlider', 'LeftFront Roll', '-90', '90', '0'),
|
||||
createSlider('pitchSlider', 'LeftFront Pitch', '-45', '45', '13'),
|
||||
createSlider('rollBackSlider', 'LeftBack Roll', '-45', '45', '0'),
|
||||
createSlider('rollRightSlider', 'RightFront Roll', '-90', '90', '0'),
|
||||
createSlider('pitchRightSlider', 'RightFront Pitch', '-45', '45', '-13'),
|
||||
createSlider('rollRightBackSlider', 'RightBack Roll', '-45', '45', '0')
|
||||
];
|
||||
|
||||
// Wheel Steering group
|
||||
const wheelSteeringSliders = [
|
||||
createSlider('wheelSteerSlider', 'Wheel Steering', '-90', '90', '0')
|
||||
];
|
||||
|
||||
// Base group
|
||||
const baseSliders = [
|
||||
createSlider('baseYawSlider', 'Base Yaw', '-180', '180', '110')
|
||||
];
|
||||
|
||||
// Camera group
|
||||
const cameraSliders = [
|
||||
createSlider('cam0PitchSlider', 'Cam0_base Pitch', '-90', '90', '0'),
|
||||
createSlider('cam0JointYawSlider', 'Cam0_joint Yaw', '-180', '180', '0'),
|
||||
createSlider('cam0HeadPitchSlider', 'Cam0_head Pitch', '-90', '90', '0')
|
||||
];
|
||||
|
||||
// Scaner group
|
||||
const scanerSliders = [
|
||||
createSlider('scanerBaseYawSlider', 'Scaner_base Yaw', '-180', '180', '90'),
|
||||
createSlider('scanerLink0PitchSlider', 'Scaner_link0 Pitch', '-90', '90', '0'),
|
||||
createSlider('scanerLink1PitchSlider', 'Scaner_link1 Pitch', '-180', '180', '90'),
|
||||
createSlider('scanerJointPitchSlider', 'Scaner_joint Pitch', '-180', '180', '90'),
|
||||
createSlider('scanerHeadYawSlider', 'Scaner_head Yaw', '-180', '180', '0')
|
||||
];
|
||||
|
||||
// Create groups
|
||||
const suspensionGroup = createSliderGroup('Suspension', suspensionSliders);
|
||||
const wheelSteeringGroup = createSliderGroup('Wheel Steering', wheelSteeringSliders);
|
||||
const baseGroup = createSliderGroup('Base', baseSliders);
|
||||
const cameraGroup = createSliderGroup('Camera', cameraSliders);
|
||||
const scanerGroup = createSliderGroup('Scaner', scanerSliders);
|
||||
|
||||
// Add groups to corresponding columns
|
||||
leftColumn.appendChild(suspensionGroup);
|
||||
leftColumn.appendChild(wheelSteeringGroup);
|
||||
leftColumn.appendChild(baseGroup);
|
||||
rightColumn.appendChild(cameraGroup);
|
||||
rightColumn.appendChild(scanerGroup);
|
||||
|
||||
// Add columns to main container
|
||||
controlsContainer.appendChild(leftColumn);
|
||||
controlsContainer.appendChild(rightColumn);
|
||||
|
||||
document.body.appendChild(controlsContainer);
|
||||
|
||||
// Return all sliders and values for event handlers
|
||||
return {
|
||||
rollSlider: document.getElementById('rollSlider'),
|
||||
pitchSlider: document.getElementById('pitchSlider'),
|
||||
wheelSteerSlider: document.getElementById('wheelSteerSlider'),
|
||||
baseYawSlider: document.getElementById('baseYawSlider'),
|
||||
rollBackSlider: document.getElementById('rollBackSlider'),
|
||||
rollRightSlider: document.getElementById('rollRightSlider'),
|
||||
pitchRightSlider: document.getElementById('pitchRightSlider'),
|
||||
rollRightBackSlider: document.getElementById('rollRightBackSlider'),
|
||||
cam0PitchSlider: document.getElementById('cam0PitchSlider'),
|
||||
cam0JointYawSlider: document.getElementById('cam0JointYawSlider'),
|
||||
cam0HeadPitchSlider: document.getElementById('cam0HeadPitchSlider'),
|
||||
scanerBaseYawSlider: document.getElementById('scanerBaseYawSlider'),
|
||||
scanerLink0PitchSlider: document.getElementById('scanerLink0PitchSlider'),
|
||||
scanerLink1PitchSlider: document.getElementById('scanerLink1PitchSlider'),
|
||||
scanerJointPitchSlider: document.getElementById('scanerJointPitchSlider'),
|
||||
scanerHeadYawSlider: document.getElementById('scanerHeadYawSlider'),
|
||||
rollValue: document.getElementById('rollSliderValue'),
|
||||
pitchValue: document.getElementById('pitchSliderValue'),
|
||||
wheelSteerValue: document.getElementById('wheelSteerSliderValue'),
|
||||
baseYawValue: document.getElementById('baseYawSliderValue'),
|
||||
rollBackValue: document.getElementById('rollBackSliderValue'),
|
||||
rollRightValue: document.getElementById('rollRightSliderValue'),
|
||||
pitchRightValue: document.getElementById('pitchRightSliderValue'),
|
||||
rollRightBackValue: document.getElementById('rollRightBackSliderValue'),
|
||||
cam0PitchValue: document.getElementById('cam0PitchSliderValue'),
|
||||
cam0JointYawValue: document.getElementById('cam0JointYawSliderValue'),
|
||||
cam0HeadPitchValue: document.getElementById('cam0HeadPitchSliderValue'),
|
||||
scanerBaseYawValue: document.getElementById('scanerBaseYawSliderValue'),
|
||||
scanerLink0PitchValue: document.getElementById('scanerLink0PitchSliderValue'),
|
||||
scanerLink1PitchValue: document.getElementById('scanerLink1PitchSliderValue'),
|
||||
scanerJointPitchValue: document.getElementById('scanerJointPitchSliderValue'),
|
||||
scanerHeadYawValue: document.getElementById('scanerHeadYawSliderValue')
|
||||
};
|
||||
}
|
||||
|
||||
let renderer = new Renderer("frame", {
|
||||
msaa: 8,
|
||||
controls: [new control.SimpleNavigation({ speed: 0.01 }), new control.GeoObjectEditor()],
|
||||
controls: [new control.SimpleNavigation({ speed: 0.01 })],
|
||||
autoActivate: true
|
||||
});
|
||||
|
||||
@ -43,7 +261,7 @@ class MyScene extends RenderNode {
|
||||
super("MyScene");
|
||||
}
|
||||
|
||||
init() {
|
||||
async init() {
|
||||
|
||||
let collection = new EntityCollection({
|
||||
entities: []
|
||||
@ -51,42 +269,528 @@ class MyScene extends RenderNode {
|
||||
|
||||
collection.addTo(this);
|
||||
|
||||
const cameraPositions = [
|
||||
[new Vec3(20, 21, 23), new Vec3(0, 2, 2), Vec3.UP, Easing.ElasticOut],
|
||||
[new Vec3(40, 10, 15), new Vec3(10, 0, 0), Vec3.LEFT, Easing.ElasticOut],
|
||||
[new Vec3(10, 30, 45), new Vec3(10, 0, 0), Vec3.DOWN, Easing.CubicInOut],
|
||||
[new Vec3(40, 10, 15), new Vec3(10, 10, 0), Vec3.RIGHT, Easing.BackInOut],
|
||||
];
|
||||
let i = 0;
|
||||
setInterval(() => {
|
||||
this.renderer.activeCamera.flyCartesian(cameraPositions[i][0], {
|
||||
look: cameraPositions[i][1],
|
||||
up: cameraPositions[i][2],
|
||||
ease: cameraPositions[i][3],
|
||||
});
|
||||
i = (i + 1) % cameraPositions.length;
|
||||
}, 1500);
|
||||
console.log(this.renderer.activeCamera);
|
||||
this.renderer.activeCamera.set(new Vec3(10, 11, 13), new Vec3(0, 2, 2));
|
||||
|
||||
DracoDecoderModule().then((decoderModule) => {
|
||||
Gltf.connectDracoDecoderModule(decoderModule);
|
||||
Gltf.loadGlb("./maxwell_the_cat.glb").then((gltf) => {
|
||||
const entities = gltf.toEntities();
|
||||
const cat = entities[0];
|
||||
cat.setScale(0.5);
|
||||
cat.setPitch(-90 * (Math.PI / 180));
|
||||
collection.add(cat);
|
||||
});
|
||||
// Load all models first
|
||||
const [
|
||||
roverBaseGltf,
|
||||
cam0BaseGltf,
|
||||
cam0JointGltf,
|
||||
cam0HeadGltf,
|
||||
scanerBaseGltf,
|
||||
scanerLink0Gltf,
|
||||
scanerLink1Gltf,
|
||||
scanerJointGltf,
|
||||
scanerHeadGltf,
|
||||
suspLeftFrontGltf,
|
||||
suspRightFrontGltf,
|
||||
amortLeftFrontGltf,
|
||||
amortRightFrontGltf,
|
||||
suspLeftBackGltf,
|
||||
suspRightBackGltf,
|
||||
amortLeftBackGltf,
|
||||
amortRightBackGltf,
|
||||
wheelFrontLeftGltf,
|
||||
wheelBackLeftGltf,
|
||||
wheelMiddleLeftGltf,
|
||||
wheelFrontRightGltf,
|
||||
wheelBackRightGltf,
|
||||
wheelMiddleRightGltf
|
||||
] = await Promise.all([
|
||||
Gltf.loadGlb("./rover_base.glb"),
|
||||
Gltf.loadGlb("./cam0_base.glb"),
|
||||
Gltf.loadGlb("./cam0_joint.glb"),
|
||||
Gltf.loadGlb("./cam0_head.glb"),
|
||||
Gltf.loadGlb("./scaner_base.glb"),
|
||||
Gltf.loadGlb("./scaner_link0.glb"),
|
||||
Gltf.loadGlb("./scaner_link1.glb"),
|
||||
Gltf.loadGlb("./scaner_joint.glb"),
|
||||
Gltf.loadGlb("./scaner_head.glb"),
|
||||
Gltf.loadGlb("./susp_left_front.glb"),
|
||||
Gltf.loadGlb("./susp_right_front.glb"),
|
||||
Gltf.loadGlb("./amort_left_front.glb"),
|
||||
Gltf.loadGlb("./amort_right_front.glb"),
|
||||
Gltf.loadGlb("./susp_left_back.glb"),
|
||||
Gltf.loadGlb("./susp_right_back.glb"),
|
||||
Gltf.loadGlb("./amort_left_back.glb"),
|
||||
Gltf.loadGlb("./amort_right_back.glb"),
|
||||
Gltf.loadGlb("./wheel_left.glb"),
|
||||
Gltf.loadGlb("./wheel_left.glb"),
|
||||
Gltf.loadGlb("./wheel_left.glb"),
|
||||
Gltf.loadGlb("./wheel_left.glb"),
|
||||
Gltf.loadGlb("./wheel_left.glb"),
|
||||
Gltf.loadGlb("./wheel_left.glb")
|
||||
]);
|
||||
|
||||
let base = new Entity({
|
||||
cartesian: new Vec3(6, 8, 9),
|
||||
yaw: 110 * Math.PI / 180,
|
||||
relativePosition: true,
|
||||
});
|
||||
window.base = base;
|
||||
|
||||
const roverBaseEntities = roverBaseGltf.toEntities();
|
||||
for (let i = 0; i < roverBaseEntities.length; i++) {
|
||||
base.appendChild(roverBaseEntities[i]);
|
||||
}
|
||||
|
||||
//
|
||||
let cam0_base = new Entity({
|
||||
cartesian: [0.751, 0.349, 0.521],
|
||||
relativePosition: true,
|
||||
yaw: 145 * Math.PI / 180
|
||||
});
|
||||
window.cam0_base = cam0_base;
|
||||
|
||||
const cam0BaseEntities = cam0BaseGltf.toEntities();
|
||||
cam0_base.appendChildren(cam0BaseEntities, true);
|
||||
base.appendChild(cam0_base);
|
||||
//
|
||||
|
||||
//
|
||||
let cam0_joint = new Entity({
|
||||
cartesian: [0, 0.515, 0],
|
||||
relativePosition: true,
|
||||
});
|
||||
window.cam0_joint = cam0_joint;
|
||||
|
||||
const cam0JointEntities = cam0JointGltf.toEntities();
|
||||
cam0_joint.appendChildren(cam0JointEntities, true);
|
||||
cam0_base.appendChild(cam0_joint);
|
||||
//
|
||||
|
||||
//
|
||||
let cam0_head = new Entity({
|
||||
cartesian: [-0.035, 0.16, 0],
|
||||
relativePosition: true,
|
||||
});
|
||||
window.cam0_head = cam0_head;
|
||||
|
||||
const cam0HeadEntities = cam0HeadGltf.toEntities();
|
||||
cam0_head.appendChildren(cam0HeadEntities, true);
|
||||
cam0_joint.appendChild(cam0_head);
|
||||
//
|
||||
|
||||
//
|
||||
let scaner_base = new Entity({
|
||||
cartesian: [1.213, 0.022, -0.485],
|
||||
yaw: 90 * Math.PI / 180,
|
||||
relativePosition: true,
|
||||
});
|
||||
window.scaner_base = scaner_base;
|
||||
|
||||
const scanerBaseEntities = scanerBaseGltf.toEntities();
|
||||
scaner_base.appendChildren(scanerBaseEntities, true);
|
||||
base.appendChild(scaner_base);
|
||||
//
|
||||
|
||||
//
|
||||
let scaner_link0 = new Entity({
|
||||
cartesian: [0.17, -0.09, -0.18],
|
||||
relativePosition: true,
|
||||
});
|
||||
window.scaner_link0 = scaner_link0;
|
||||
|
||||
const scanerLink0Entities = scanerLink0Gltf.toEntities();
|
||||
scaner_link0.appendChildren(scanerLink0Entities, true);
|
||||
scaner_base.appendChild(scaner_link0);
|
||||
//
|
||||
|
||||
//
|
||||
let scaner_link1 = new Entity({
|
||||
cartesian: [0, 0.0, -0.838],
|
||||
relativePosition: true,
|
||||
pitch: 90 * Math.PI / 180
|
||||
});
|
||||
window.scaner_link1 = scaner_link1;
|
||||
|
||||
const scanerLink1Entities = scanerLink1Gltf.toEntities();
|
||||
scaner_link1.appendChildren(scanerLink1Entities, true);
|
||||
scaner_link0.appendChild(scaner_link1);
|
||||
//
|
||||
|
||||
//
|
||||
let scaner_joint = new Entity({
|
||||
cartesian: [-0.035, -0.005, -0.755],
|
||||
relativePosition: true,
|
||||
pitch: 90 * Math.PI / 180
|
||||
});
|
||||
window.scaner_joint = scaner_joint;
|
||||
|
||||
const scanerJointEntities = scanerJointGltf.toEntities();
|
||||
scaner_joint.appendChildren(scanerJointEntities, true);
|
||||
scaner_link1.appendChild(scaner_joint);
|
||||
//
|
||||
|
||||
//
|
||||
let scaner_head = new Entity({
|
||||
cartesian: [0.042, -.15, -0.175],
|
||||
relativePosition: true,
|
||||
pitch: 180 * Math.PI / 180
|
||||
});
|
||||
window.scaner_head = scaner_head;
|
||||
|
||||
const scanerHeadEntities = scanerHeadGltf.toEntities();
|
||||
scaner_head.appendChildren(scanerHeadEntities, true);
|
||||
scaner_joint.appendChild(scaner_head);
|
||||
//
|
||||
|
||||
let suspLeftFront = new Entity({
|
||||
cartesian: new Vec3(0.26, -0.0, -0.78),
|
||||
pitch: 13 * Math.PI / 180,
|
||||
relativePosition: true,
|
||||
});
|
||||
|
||||
Gltf.loadGlb("./f22.glb").then((gltf) => {
|
||||
const entity = gltf.toEntities()[0];
|
||||
entity.setScale(1);
|
||||
entity.setCartesian(20, 5, 0);
|
||||
entity.setPitch(-90 * (Math.PI / 180));
|
||||
collection.add(entity);
|
||||
window.suspLeftFront = suspLeftFront;
|
||||
|
||||
const suspLeftFrontEntities = suspLeftFrontGltf.toEntities();
|
||||
for (let i = 0; i < suspLeftFrontEntities.length; i++) {
|
||||
suspLeftFrontEntities[i].relativePosition = true;
|
||||
suspLeftFront.appendChild(suspLeftFrontEntities[i]);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
let suspRightFront = new Entity({
|
||||
cartesian: new Vec3(0.253, 0.01, 0.711),
|
||||
pitch: -13 * Math.PI / 180,
|
||||
relativePosition: true,
|
||||
});
|
||||
|
||||
window.suspRightFront = suspRightFront;
|
||||
|
||||
const suspRightFrontEntities = suspRightFrontGltf.toEntities();
|
||||
for (let i = 0; i < suspRightFrontEntities.length; i++) {
|
||||
suspRightFrontEntities[i].relativePosition = true;
|
||||
suspRightFront.appendChild(suspRightFrontEntities[i]);
|
||||
}
|
||||
//
|
||||
|
||||
let amortLeftFront = new Entity({
|
||||
cartesian: new Vec3(0.876, -0.3, -0.26),
|
||||
relativePosition: true,
|
||||
pitch: -103 * Math.PI / 180,
|
||||
});
|
||||
|
||||
window.amortLeftFront = amortLeftFront;
|
||||
|
||||
const amortLeftFrontEntities = amortLeftFrontGltf.toEntities();
|
||||
amortLeftFront.appendChildren(amortLeftFrontEntities, true);
|
||||
|
||||
suspLeftFront.appendChild(amortLeftFront);
|
||||
|
||||
//
|
||||
let amortRightFront = new Entity({
|
||||
cartesian: new Vec3(0.876, -0.3, 0.26),
|
||||
relativePosition: true,
|
||||
pitch: -77 * Math.PI / 180,
|
||||
});
|
||||
|
||||
window.amortRightFront = amortRightFront;
|
||||
|
||||
const amortRightFrontEntities = amortRightFrontGltf.toEntities();
|
||||
amortRightFront.appendChildren(amortRightFrontEntities, true);
|
||||
|
||||
suspRightFront.appendChild(amortRightFront);
|
||||
//
|
||||
|
||||
|
||||
let suspLeftBack = new Entity({
|
||||
cartesian: new Vec3(-0.757, -0.222, -0.008),
|
||||
relativePosition: true,
|
||||
pitch: -13 * Math.PI / 180
|
||||
});
|
||||
|
||||
window.suspLeftBack = suspLeftBack;
|
||||
|
||||
const suspLeftBackEntities = suspLeftBackGltf.toEntities();
|
||||
for (let i = 0; i < suspLeftBackEntities.length; i++) {
|
||||
suspLeftBackEntities[i].relativePosition = true;
|
||||
suspLeftBack.appendChild(suspLeftBackEntities[i]);
|
||||
}
|
||||
|
||||
suspLeftFront.appendChild(suspLeftBack);
|
||||
|
||||
//
|
||||
let suspRightBack = new Entity({
|
||||
cartesian: new Vec3(-0.756, -0.243, 0.008),
|
||||
relativePosition: true,
|
||||
pitch: 13 * Math.PI / 180
|
||||
});
|
||||
|
||||
window.suspRightBack = suspRightBack;
|
||||
|
||||
const suspRightBackEntities = suspRightBackGltf.toEntities();
|
||||
for (let i = 0; i < suspRightBackEntities.length; i++) {
|
||||
suspRightBackEntities[i].relativePosition = true;
|
||||
suspRightBack.appendChild(suspRightBackEntities[i]);
|
||||
}
|
||||
|
||||
suspRightFront.appendChild(suspRightBack);
|
||||
//
|
||||
|
||||
let amortLeftBack = new Entity({
|
||||
cartesian: new Vec3(-0.625, -0.01, -0.263),
|
||||
relativePosition: true,
|
||||
});
|
||||
|
||||
window.amortLeftBack = amortLeftBack;
|
||||
|
||||
const amortLeftBackEntities = amortLeftBackGltf.toEntities()[0];
|
||||
amortLeftBackEntities.relativePosition = true;
|
||||
amortLeftBack.appendChild(amortLeftBackEntities);
|
||||
|
||||
suspLeftBack.appendChild(amortLeftBack);
|
||||
|
||||
//
|
||||
let amortRightBack = new Entity({
|
||||
cartesian: new Vec3(-0.622, -0.0, 0.263),
|
||||
relativePosition: true,
|
||||
});
|
||||
|
||||
window.amortRightBack = amortRightBack;
|
||||
|
||||
const amortRightBackEntities = amortRightBackGltf.toEntities()[0];
|
||||
amortRightBackEntities.relativePosition = true;
|
||||
amortRightBack.appendChild(amortRightBackEntities);
|
||||
|
||||
suspRightBack.appendChild(amortRightBack);
|
||||
//
|
||||
|
||||
suspLeftFront.appendChild(amortLeftFront);
|
||||
|
||||
base.appendChild(suspLeftFront);
|
||||
base.appendChild(suspRightFront);
|
||||
|
||||
|
||||
let wheelFrontLeft = new Entity({
|
||||
cartesian: new Vec3(0, -0.05, -0.395),
|
||||
relativePosition: true,
|
||||
pitch: 90 * Math.PI / 180
|
||||
});
|
||||
|
||||
let wheelBackLeft = new Entity({
|
||||
cartesian: new Vec3(0, -0.392, 0.065),
|
||||
relativePosition: true,
|
||||
});
|
||||
|
||||
let wheelMiddleLeft = new Entity({
|
||||
cartesian: new Vec3(0.45, -0.4, -0.3),
|
||||
relativePosition: true,
|
||||
});
|
||||
|
||||
const wheelFrontLeftEntities = wheelFrontLeftGltf.toEntities();
|
||||
wheelFrontLeftEntities[0].relativePosition = true;
|
||||
wheelFrontLeft.appendChild(wheelFrontLeftEntities[0]);
|
||||
|
||||
const wheelBackLeftEntities = wheelBackLeftGltf.toEntities();
|
||||
wheelBackLeftEntities[0].relativePosition = true;
|
||||
wheelBackLeft.appendChild(wheelBackLeftEntities[0]);
|
||||
|
||||
const wheelMiddleLeftEntities = wheelMiddleLeftGltf.toEntities();
|
||||
wheelMiddleLeftEntities[0].relativePosition = true;
|
||||
wheelMiddleLeft.appendChild(wheelMiddleLeftEntities[0]);
|
||||
|
||||
amortLeftFront.appendChild(wheelFrontLeft);
|
||||
amortLeftBack.appendChild(wheelBackLeft);
|
||||
suspLeftBack.appendChild(wheelMiddleLeft);
|
||||
|
||||
//
|
||||
let wheelFrontRight = new Entity({
|
||||
cartesian: new Vec3(0.003, 0.065, -0.391),
|
||||
relativePosition: true,
|
||||
pitch: -90 * Math.PI / 180,
|
||||
yaw: 180 * Math.PI / 180
|
||||
});
|
||||
|
||||
let wheelBackRight = new Entity({
|
||||
cartesian: new Vec3(0, -0.392, -0.065),
|
||||
relativePosition: true,
|
||||
yaw: 180 * Math.PI / 180
|
||||
});
|
||||
|
||||
let wheelMiddleRight = new Entity({
|
||||
cartesian: new Vec3(.45, -0.4, 0.319),
|
||||
relativePosition: true,
|
||||
yaw: 180 * Math.PI / 180
|
||||
});
|
||||
|
||||
const wheelFrontRightEntities = wheelFrontRightGltf.toEntities();
|
||||
wheelFrontRightEntities[0].relativePosition = true;
|
||||
wheelFrontRight.appendChild(wheelFrontRightEntities[0]);
|
||||
|
||||
const wheelBackRightEntities = wheelBackRightGltf.toEntities();
|
||||
wheelBackRightEntities[0].relativePosition = true;
|
||||
wheelBackRight.appendChild(wheelBackRightEntities[0]);
|
||||
|
||||
const wheelMiddleRightEntities = wheelMiddleRightGltf.toEntities();
|
||||
wheelMiddleRightEntities[0].relativePosition = true;
|
||||
wheelMiddleRight.appendChild(wheelMiddleRightEntities[0]);
|
||||
|
||||
amortRightFront.appendChild(wheelFrontRight);
|
||||
amortRightBack.appendChild(wheelBackRight);
|
||||
suspRightBack.appendChild(wheelMiddleRight);
|
||||
|
||||
window.wheelFrontRight = wheelFrontRight;
|
||||
window.wheelBackRight = wheelBackRight;
|
||||
window.wheelMiddleRight = wheelMiddleRight;
|
||||
//
|
||||
|
||||
let wheelRoll = 0;
|
||||
this.renderer.events.on("draw", () => {
|
||||
wheelFrontLeft.setRoll(wheelRoll * Math.PI / 180);
|
||||
wheelBackLeft.setRoll(wheelRoll * Math.PI / 180);
|
||||
wheelMiddleLeft.setRoll(wheelRoll * Math.PI / 180);
|
||||
|
||||
wheelFrontRight.setRoll(-wheelRoll * Math.PI / 180);
|
||||
wheelBackRight.setRoll(-wheelRoll * Math.PI / 180);
|
||||
wheelMiddleRight.setRoll(-wheelRoll * Math.PI / 180);
|
||||
|
||||
wheelRoll -= 0.3;
|
||||
});
|
||||
|
||||
collection.add(base);
|
||||
|
||||
// Create sliders after model loading
|
||||
const sliders = createSliderControls();
|
||||
|
||||
// Setup event handlers for sliders
|
||||
sliders.rollSlider.addEventListener('input', (e) => {
|
||||
const rollDegrees = parseFloat(e.target.value);
|
||||
const rollRadians = rollDegrees * (Math.PI / 180);
|
||||
suspLeftFront.setRoll(rollRadians);
|
||||
sliders.rollValue.textContent = rollDegrees.toFixed(1) + '°';
|
||||
});
|
||||
|
||||
sliders.pitchSlider.addEventListener('input', (e) => {
|
||||
const pitchDegrees = parseFloat(e.target.value);
|
||||
const pitchRadians = pitchDegrees * (Math.PI / 180);
|
||||
suspLeftFront.setPitch(pitchRadians);
|
||||
sliders.pitchValue.textContent = pitchDegrees.toFixed(1) + '°';
|
||||
});
|
||||
|
||||
sliders.wheelSteerSlider.addEventListener('input', (e) => {
|
||||
const wheelSteerDegrees = parseFloat(e.target.value);
|
||||
const wheelSteerRadians = wheelSteerDegrees * (Math.PI / 180);
|
||||
// Front shock absorbers use setRoll
|
||||
amortLeftFront.setRoll(wheelSteerRadians);
|
||||
amortRightFront.setRoll(wheelSteerRadians);
|
||||
// Rear shock absorbers use setYaw
|
||||
amortLeftBack.setYaw(wheelSteerRadians);
|
||||
amortRightBack.setYaw(wheelSteerRadians);
|
||||
sliders.wheelSteerValue.textContent = wheelSteerDegrees.toFixed(1) + '°';
|
||||
});
|
||||
|
||||
sliders.baseYawSlider.addEventListener('input', (e) => {
|
||||
const baseYawDegrees = parseFloat(e.target.value);
|
||||
const baseYawRadians = baseYawDegrees * (Math.PI / 180);
|
||||
base.setYaw(baseYawRadians);
|
||||
sliders.baseYawValue.textContent = baseYawDegrees.toFixed(1) + '°';
|
||||
});
|
||||
|
||||
sliders.rollBackSlider.addEventListener('input', (e) => {
|
||||
const rollBackDegrees = parseFloat(e.target.value);
|
||||
const rollBackRadians = rollBackDegrees * (Math.PI / 180);
|
||||
suspLeftBack.setRoll(rollBackRadians);
|
||||
sliders.rollBackValue.textContent = rollBackDegrees.toFixed(1) + '°';
|
||||
});
|
||||
|
||||
sliders.rollRightSlider.addEventListener('input', (e) => {
|
||||
const rollRightDegrees = parseFloat(e.target.value);
|
||||
const rollRightRadians = rollRightDegrees * (Math.PI / 180);
|
||||
suspRightFront.setRoll(rollRightRadians);
|
||||
sliders.rollRightValue.textContent = rollRightDegrees.toFixed(1) + '°';
|
||||
});
|
||||
|
||||
sliders.pitchRightSlider.addEventListener('input', (e) => {
|
||||
const pitchRightDegrees = parseFloat(e.target.value);
|
||||
const pitchRightRadians = pitchRightDegrees * (Math.PI / 180);
|
||||
suspRightFront.setPitch(pitchRightRadians);
|
||||
sliders.pitchRightValue.textContent = pitchRightDegrees.toFixed(1) + '°';
|
||||
});
|
||||
|
||||
sliders.rollRightBackSlider.addEventListener('input', (e) => {
|
||||
const rollRightBackDegrees = parseFloat(e.target.value);
|
||||
const rollRightBackRadians = rollRightBackDegrees * (Math.PI / 180);
|
||||
suspRightBack.setRoll(rollRightBackRadians);
|
||||
sliders.rollRightBackValue.textContent = rollRightBackDegrees.toFixed(1) + '°';
|
||||
});
|
||||
|
||||
sliders.cam0PitchSlider.addEventListener('input', (e) => {
|
||||
const cam0PitchDegrees = parseFloat(e.target.value);
|
||||
const cam0PitchRadians = cam0PitchDegrees * (Math.PI / 180);
|
||||
cam0_base.setPitch(cam0PitchRadians);
|
||||
sliders.cam0PitchValue.textContent = cam0PitchDegrees.toFixed(1) + '°';
|
||||
});
|
||||
|
||||
// Set initial values for camera
|
||||
cam0_base.setYaw(145 * Math.PI / 180);
|
||||
|
||||
// Update slider value display
|
||||
sliders.pitchValue.textContent = '13.0°';
|
||||
sliders.pitchRightValue.textContent = '-13.0°';
|
||||
sliders.baseYawValue.textContent = '110.0°';
|
||||
sliders.scanerBaseYawValue.textContent = '90.0°';
|
||||
sliders.scanerLink1PitchValue.textContent = '90.0°';
|
||||
sliders.scanerJointPitchValue.textContent = '90.0°';
|
||||
|
||||
sliders.cam0JointYawSlider.addEventListener('input', (e) => {
|
||||
const cam0JointYawDegrees = parseFloat(e.target.value);
|
||||
const cam0JointYawRadians = cam0JointYawDegrees * (Math.PI / 180);
|
||||
cam0_joint.setYaw(cam0JointYawRadians);
|
||||
sliders.cam0JointYawValue.textContent = cam0JointYawDegrees.toFixed(1) + '°';
|
||||
});
|
||||
|
||||
sliders.cam0HeadPitchSlider.addEventListener('input', (e) => {
|
||||
const cam0HeadPitchDegrees = parseFloat(e.target.value);
|
||||
const cam0HeadPitchRadians = cam0HeadPitchDegrees * (Math.PI / 180);
|
||||
cam0_head.setPitch(cam0HeadPitchRadians);
|
||||
sliders.cam0HeadPitchValue.textContent = cam0HeadPitchDegrees.toFixed(1) + '°';
|
||||
});
|
||||
|
||||
sliders.scanerBaseYawSlider.addEventListener('input', (e) => {
|
||||
const scanerBaseYawDegrees = parseFloat(e.target.value);
|
||||
const scanerBaseYawRadians = scanerBaseYawDegrees * (Math.PI / 180);
|
||||
scaner_base.setYaw(scanerBaseYawRadians);
|
||||
sliders.scanerBaseYawValue.textContent = scanerBaseYawDegrees.toFixed(1) + '°';
|
||||
});
|
||||
|
||||
sliders.scanerLink0PitchSlider.addEventListener('input', (e) => {
|
||||
const scanerLink0PitchDegrees = parseFloat(e.target.value);
|
||||
const scanerLink0PitchRadians = scanerLink0PitchDegrees * (Math.PI / 180);
|
||||
scaner_link0.setPitch(scanerLink0PitchRadians);
|
||||
sliders.scanerLink0PitchValue.textContent = scanerLink0PitchDegrees.toFixed(1) + '°';
|
||||
});
|
||||
|
||||
sliders.scanerLink1PitchSlider.addEventListener('input', (e) => {
|
||||
const scanerLink1PitchDegrees = parseFloat(e.target.value);
|
||||
const scanerLink1PitchRadians = scanerLink1PitchDegrees * (Math.PI / 180);
|
||||
scaner_link1.setPitch(scanerLink1PitchRadians);
|
||||
sliders.scanerLink1PitchValue.textContent = scanerLink1PitchDegrees.toFixed(1) + '°';
|
||||
});
|
||||
|
||||
sliders.scanerJointPitchSlider.addEventListener('input', (e) => {
|
||||
const scanerJointPitchDegrees = parseFloat(e.target.value);
|
||||
const scanerJointPitchRadians = scanerJointPitchDegrees * (Math.PI / 180);
|
||||
scaner_joint.setPitch(scanerJointPitchRadians);
|
||||
sliders.scanerJointPitchValue.textContent = scanerJointPitchDegrees.toFixed(1) + '°';
|
||||
});
|
||||
|
||||
sliders.scanerHeadYawSlider.addEventListener('input', (e) => {
|
||||
const scanerHeadYawDegrees = parseFloat(e.target.value);
|
||||
const scanerHeadYawRadians = scanerHeadYawDegrees * (Math.PI / 180);
|
||||
scaner_head.setYaw(scanerHeadYawRadians);
|
||||
sliders.scanerHeadYawValue.textContent = scanerHeadYawDegrees.toFixed(1) + '°';
|
||||
});
|
||||
|
||||
// Set initial values for scaner objects
|
||||
scaner_base.setYaw(90 * Math.PI / 180);
|
||||
scaner_link1.setPitch(90 * Math.PI / 180);
|
||||
scaner_joint.setPitch(90 * Math.PI / 180);
|
||||
scaner_head.setPitch(180 * Math.PI / 180);
|
||||
}
|
||||
}
|
||||
|
||||
renderer.addNodes([new scene.Axes(), new MyScene()]);
|
||||
|
||||
window.renderer = renderer;
|
||||
|
||||
BIN
sandbox/modelLoad/rover_base.glb
Normal file
BIN
sandbox/modelLoad/rover_base.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/scaner_base.glb
Normal file
BIN
sandbox/modelLoad/scaner_base.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/scaner_head.glb
Normal file
BIN
sandbox/modelLoad/scaner_head.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/scaner_joint.glb
Normal file
BIN
sandbox/modelLoad/scaner_joint.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/scaner_link0.glb
Normal file
BIN
sandbox/modelLoad/scaner_link0.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/scaner_link1.glb
Normal file
BIN
sandbox/modelLoad/scaner_link1.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/susp_left_back.glb
Normal file
BIN
sandbox/modelLoad/susp_left_back.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/susp_left_front.glb
Normal file
BIN
sandbox/modelLoad/susp_left_front.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/susp_right_back.glb
Normal file
BIN
sandbox/modelLoad/susp_right_back.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/susp_right_front.glb
Normal file
BIN
sandbox/modelLoad/susp_right_front.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/wheel_left.glb
Normal file
BIN
sandbox/modelLoad/wheel_left.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/wheel_left_front.glb
Normal file
BIN
sandbox/modelLoad/wheel_left_front.glb
Normal file
Binary file not shown.
BIN
sandbox/modelLoad/wheel_right.glb
Normal file
BIN
sandbox/modelLoad/wheel_right.glb
Normal file
Binary file not shown.
@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-undef */
|
||||
import {
|
||||
control,
|
||||
Entity,
|
||||
@ -13,39 +12,41 @@ import {
|
||||
|
||||
let renderer = new Renderer("frame", {
|
||||
msaa: 8,
|
||||
controls: [new control.SimpleNavigation({ speed: 0.01 }), new control.GeoObjectEditor()],
|
||||
controls: [new control.SimpleNavigation({ speed: 0.01 })],
|
||||
autoActivate: true
|
||||
});
|
||||
|
||||
window.renderer = renderer;
|
||||
|
||||
class MyScene extends RenderNode {
|
||||
constructor() {
|
||||
super("MyScene");
|
||||
}
|
||||
|
||||
init() {
|
||||
const baseObj = Object3d.createCube(0.4, 2, 0.4).translate(new Vec3(0, 1, 0)).setMaterial({
|
||||
ambient: "#882a2a",
|
||||
diffuse: "#fb3434",
|
||||
const baseObj = Object3d.createCube(10, 10, 10).translate(new Vec3(0, 0, 0)).setMaterial({
|
||||
ambient: "#c2c2c2",
|
||||
diffuse: "#ffffff",
|
||||
shininess: 1
|
||||
});
|
||||
|
||||
const frustumObj = Object3d.createFrustum(3, 2, 1).setMaterial({
|
||||
ambient: "#236028",
|
||||
diffuse: "#1cdd23",
|
||||
shininess: 1
|
||||
});
|
||||
window.test = () => {
|
||||
parentEntity.setPitch(0);
|
||||
cube2.setPitch(0);
|
||||
cube3.setPitch(0);
|
||||
|
||||
const cylinderObj = Object3d.createCylinder(1, 0, 1)
|
||||
.applyMat4(new Mat4().setRotation(new Vec3(1, 0, 0), (90 * Math.PI) / 180))
|
||||
.setMaterial({
|
||||
ambient: "#773381",
|
||||
diffuse: "#ef00ff",
|
||||
shininess: 1
|
||||
});
|
||||
parentEntity.setYaw(0);
|
||||
cube2.setYaw(0);
|
||||
cube3.setYaw(0);
|
||||
|
||||
this.renderer.activeCamera.set(new Vec3(10.5, 0, 0), new Vec3(0, 0, 0), new Vec3(0, 1, 0));
|
||||
}
|
||||
|
||||
let parentEntity = new Entity({
|
||||
cartesian: new Vec3(0, 0, 0),
|
||||
independentPicking: true,
|
||||
//yaw: 45 * Math.PI / 180,
|
||||
//pitch: 45 * Math.PI / 180,
|
||||
geoObject: {
|
||||
color: "rgb(90,90,90)",
|
||||
scale: 1,
|
||||
@ -55,42 +56,58 @@ class MyScene extends RenderNode {
|
||||
}
|
||||
});
|
||||
|
||||
let childEntity = new Entity({
|
||||
cartesian: new Vec3(0, 1, 0),
|
||||
let cube2 = new Entity({
|
||||
cartesian: new Vec3(45, 0, 5),
|
||||
independentPicking: true,
|
||||
relativePosition: true,
|
||||
//yaw: 45 * Math.PI / 180,
|
||||
//pitch: 45 * Math.PI / 180,
|
||||
geoObject: {
|
||||
color: "rgb(90,90,90)",
|
||||
scale: 1,
|
||||
instanced: true,
|
||||
tag: `frustumObj`,
|
||||
object3d: frustumObj
|
||||
tag: `baseObj`,
|
||||
object3d: baseObj
|
||||
}
|
||||
});
|
||||
|
||||
let childChildEntity = new Entity({
|
||||
cartesian: new Vec3(0, 3, -1),
|
||||
let cube3 = new Entity({
|
||||
cartesian: new Vec3(-1, 3, 1),
|
||||
independentPicking: true,
|
||||
relativePosition: true,
|
||||
//yaw: 45 * Math.PI / 180,
|
||||
pitch: 45 * Math.PI / 180,
|
||||
geoObject: {
|
||||
color: "rgb(90,90,90)",
|
||||
scale: 1,
|
||||
instanced: true,
|
||||
tag: `cylinderObj`,
|
||||
object3d: cylinderObj
|
||||
tag: `baseObj`,
|
||||
object3d: baseObj
|
||||
}
|
||||
});
|
||||
|
||||
childEntity.appendChild(childChildEntity);
|
||||
parentEntity.appendChild(childEntity);
|
||||
|
||||
let collection = new EntityCollection({
|
||||
entities: [parentEntity]
|
||||
entities: [parentEntity, cube2]
|
||||
});
|
||||
|
||||
collection.addTo(this);
|
||||
|
||||
this.renderer.activeCamera.set(new Vec3(-4, 11, 13), new Vec3(1, 0, 0));
|
||||
|
||||
this.renderer.activeCamera.set(new Vec3(0, 100, 100), new Vec3(0, 0, 0));
|
||||
this.renderer.activeCamera.update();
|
||||
this.renderer.activeCamera.isOrthographic = true;
|
||||
|
||||
this.renderer.getDepthMinDistanceAsync().then((dist) => {
|
||||
if (!dist) {
|
||||
dist = this.renderer.activeCamera.eye.length();
|
||||
}
|
||||
this.renderer.activeCamera.focusDistance = dist;
|
||||
this.renderer.activeCamera.isOrthographic = true;
|
||||
});
|
||||
|
||||
|
||||
this.renderer.events.on("rclick", (e) => {
|
||||
//let dist = this.renderer.getDistanceFromPixel(e.pos);
|
||||
//let dir = this.renderer.activeCamera.unproject(e.x, e.y, dist);
|
||||
//console.log(dir);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -87,24 +87,19 @@ globus.planet.addControl(new control.KeyboardNavigation({
|
||||
})
|
||||
);
|
||||
|
||||
let toneMappingFramebufferPreview = new control.FramebufferPreview({
|
||||
title: "toneMappingFramebuffer",
|
||||
framebuffer: globus.renderer.toneMappingFramebuffer,
|
||||
flippedUV: true
|
||||
});
|
||||
globus.planet.addControl(toneMappingFramebufferPreview);
|
||||
// let toneMappingFramebufferPreview = new control.FramebufferPreview({
|
||||
// title: "toneMappingFramebuffer",
|
||||
// framebuffer: globus.renderer.toneMappingFramebuffer,
|
||||
// flippedUV: true
|
||||
// });
|
||||
// globus.planet.addControl(toneMappingFramebufferPreview);
|
||||
|
||||
let pickingFramebufferPreview = new control.FramebufferPreview({
|
||||
title: "pickingFramebuffer",
|
||||
framebuffer: globus.renderer.pickingFramebuffer,
|
||||
flippedUV: true
|
||||
});
|
||||
globus.planet.addControl(pickingFramebufferPreview);
|
||||
|
||||
|
||||
globus.planet.addControl(new control.KeyboardNavigation({
|
||||
camera: depthHandler.camera
|
||||
}));
|
||||
// let pickingFramebufferPreview = new control.FramebufferPreview({
|
||||
// title: "pickingFramebuffer",
|
||||
// framebuffer: globus.renderer.pickingFramebuffer,
|
||||
// flippedUV: true
|
||||
// });
|
||||
// globus.planet.addControl(pickingFramebufferPreview);
|
||||
|
||||
globus.planet.renderer.controls.SimpleSkyBackground.colorOne = "black";
|
||||
globus.planet.renderer.controls.SimpleSkyBackground.colorTwo = "black";
|
||||
@ -20,6 +20,7 @@ import {ZoomControl} from "./control/ZoomControl";
|
||||
import {Extent} from "./Extent";
|
||||
import type {IAtmosphereParams} from "./control/atmosphere/Atmosphere";
|
||||
import {CameraFrameComposer} from "./control/CameraFrameComposer";
|
||||
import {QuadTreeStrategy} from "./quadTree";
|
||||
|
||||
export interface IGlobeParams {
|
||||
attributionContainer?: HTMLElement;
|
||||
@ -38,7 +39,7 @@ export interface IGlobeParams {
|
||||
maxEqualZoomAltitude?: number;
|
||||
minEqualZoomAltitude?: number;
|
||||
minEqualZoomCameraSlope?: number;
|
||||
quadTreeStrategyPrototype?: any;
|
||||
quadTreeStrategyPrototype?: typeof QuadTreeStrategy;
|
||||
maxLoadingRequests?: number;
|
||||
atmosphereEnabled?: boolean;
|
||||
transitionOpacityEnabled?: boolean;
|
||||
|
||||
@ -1,21 +1,19 @@
|
||||
import * as math from "../math";
|
||||
import { type EventsHandler, createEvents } from "../Events";
|
||||
import { Frustum } from "./Frustum";
|
||||
import { Mat3 } from "../math/Mat3";
|
||||
import type { NumberArray9 } from "../math/Mat3";
|
||||
import { Mat4 } from "../math/Mat4";
|
||||
import type { NumberArray16 } from "../math/Mat4";
|
||||
import { Renderer } from "../renderer/Renderer";
|
||||
import { Vec2 } from "../math/Vec2";
|
||||
import type { NumberArray2 } from "../math/Vec2";
|
||||
import { Vec3 } from "../math/Vec3";
|
||||
import { Vec4 } from "../math/Vec4";
|
||||
import { Sphere } from "../bv/Sphere";
|
||||
import { Quat } from "../math/Quat";
|
||||
import { DEGREES_DOUBLE, RADIANS, RADIANS_HALF } from "../math";
|
||||
import { Easing, EasingFunction } from "../utils/easing";
|
||||
import { LonLat } from "../LonLat";
|
||||
import { Ray } from "../math/Ray";
|
||||
import {type EventsHandler, createEvents} from "../Events";
|
||||
import {Frustum} from "./Frustum";
|
||||
import {Mat3} from "../math/Mat3";
|
||||
import type {NumberArray9} from "../math/Mat3";
|
||||
import {Mat4} from "../math/Mat4";
|
||||
import type {NumberArray16} from "../math/Mat4";
|
||||
import {Renderer} from "../renderer/Renderer";
|
||||
import {Vec2} from "../math/Vec2";
|
||||
import type {NumberArray2} from "../math/Vec2";
|
||||
import {Vec3} from "../math/Vec3";
|
||||
import {Vec4} from "../math/Vec4";
|
||||
import {Sphere} from "../bv/Sphere";
|
||||
import {Quat} from "../math/Quat";
|
||||
import {DEGREES_DOUBLE, RADIANS, RADIANS_HALF} from "../math";
|
||||
import {Easing, EasingFunction} from "../utils/easing";
|
||||
import {LonLat} from "../LonLat";
|
||||
|
||||
export type CameraEvents = ["viewchange", "moveend", "flystart", "flyend", "flystop"];
|
||||
|
||||
@ -59,6 +57,8 @@ export interface ICameraParams {
|
||||
frustums?: NumberArray2[];
|
||||
width?: number;
|
||||
height?: number;
|
||||
isOrthographic?: boolean;
|
||||
focusDistance?: number;
|
||||
}
|
||||
|
||||
export interface IFlyCartesianParams extends IFlyBaseParams {
|
||||
@ -120,6 +120,10 @@ class Camera {
|
||||
*/
|
||||
public events: EventsHandler<CameraEvents>;
|
||||
|
||||
protected _isOrthographic: boolean;
|
||||
|
||||
protected _focusDistance: number;
|
||||
|
||||
/**
|
||||
* Camera position.
|
||||
* @public
|
||||
@ -237,6 +241,10 @@ class Camera {
|
||||
|
||||
this.events = createEvents<CameraEvents>(EVENT_NAMES, this);
|
||||
|
||||
this._isOrthographic = options.isOrthographic ?? false;
|
||||
|
||||
this._focusDistance = options.focusDistance != undefined ? options.focusDistance : 10;
|
||||
|
||||
this._width = options.width || 1;
|
||||
|
||||
this._height = options.height || 1;
|
||||
@ -301,8 +309,8 @@ class Camera {
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let near = 0.1,
|
||||
far = 1000.0;
|
||||
let near = 1,
|
||||
far = 500.0;
|
||||
|
||||
let fr = new Frustum({
|
||||
fov: this._viewAngle,
|
||||
@ -336,6 +344,30 @@ class Camera {
|
||||
);
|
||||
}
|
||||
|
||||
public get isOrthographic(): boolean {
|
||||
return this._isOrthographic;
|
||||
}
|
||||
|
||||
public set isOrthographic(isOrthographic: boolean) {
|
||||
if (this._isOrthographic !== isOrthographic) {
|
||||
this._isOrthographic = isOrthographic;
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public get focusDistance(): number {
|
||||
return this._focusDistance;
|
||||
}
|
||||
|
||||
public set focusDistance(dist: number) {
|
||||
if (dist !== this._focusDistance) {
|
||||
this._focusDistance = dist;
|
||||
if (this._isOrthographic) {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get id(): number {
|
||||
return this.__id;
|
||||
}
|
||||
@ -542,49 +574,22 @@ class Camera {
|
||||
* @virtual
|
||||
*/
|
||||
public update() {
|
||||
let u = this._r,
|
||||
v = this._u,
|
||||
n = this._b,
|
||||
eye = this.eye;
|
||||
let u = this._r, v = this._u, n = this._b, eye = this.eye;
|
||||
|
||||
Vec3.doubleToTwoFloat32Array(eye, this.eyeHigh, this.eyeLow);
|
||||
|
||||
this._viewMatrix.set([
|
||||
u.x,
|
||||
v.x,
|
||||
n.x,
|
||||
0.0,
|
||||
u.y,
|
||||
v.y,
|
||||
n.y,
|
||||
0.0,
|
||||
u.z,
|
||||
v.z,
|
||||
n.z,
|
||||
0.0,
|
||||
-eye.dot(u),
|
||||
-eye.dot(v),
|
||||
-eye.dot(n),
|
||||
1.0
|
||||
u.x, v.x, n.x, 0.0,
|
||||
u.y, v.y, n.y, 0.0,
|
||||
u.z, v.z, n.z, 0.0,
|
||||
-eye.dot(u), -eye.dot(v), -eye.dot(n), 1.0
|
||||
]);
|
||||
|
||||
this._viewMatrixRTE.set([
|
||||
u.x,
|
||||
v.x,
|
||||
n.x,
|
||||
0.0,
|
||||
u.y,
|
||||
v.y,
|
||||
n.y,
|
||||
0.0,
|
||||
u.z,
|
||||
v.z,
|
||||
n.z,
|
||||
0.0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1.0
|
||||
u.x, v.x, n.x, 0.0,
|
||||
u.y, v.y, n.y, 0.0,
|
||||
u.z, v.z, n.z, 0.0,
|
||||
0, 0, 0, 1.0
|
||||
]);
|
||||
|
||||
// do not clean up, someday it will be using
|
||||
@ -633,34 +638,24 @@ class Camera {
|
||||
/**
|
||||
* Sets up camera projection
|
||||
* @public
|
||||
* @param {number} angle - Camera view angle
|
||||
* @param {number} viewAngle - Camera view angle
|
||||
* @param {number} aspect - Screen aspect ratio
|
||||
*/
|
||||
protected _setProj(angle: number, aspect: number) {
|
||||
this._viewAngle = angle;
|
||||
protected _setProj(viewAngle: number, aspect: number) {
|
||||
this._viewAngle = viewAngle;
|
||||
for (let i = 0, len = this.frustums.length; i < len; i++) {
|
||||
this.frustums[i].setProjectionMatrix(
|
||||
angle,
|
||||
aspect,
|
||||
this.frustums[i].near,
|
||||
this.frustums[i].far
|
||||
);
|
||||
let fi = this.frustums[i];
|
||||
fi.setProjectionMatrix(viewAngle, aspect, fi.near, fi.far, this._isOrthographic, this._focusDistance);
|
||||
}
|
||||
|
||||
this._horizontalViewAngle = getHorizontalViewAngleByFov(angle, aspect);
|
||||
|
||||
this._horizontalViewAngle = getHorizontalViewAngleByFov(viewAngle, aspect);
|
||||
this._updateViewportParameters();
|
||||
}
|
||||
|
||||
protected _updateViewportParameters() {
|
||||
this._tanViewAngle_hrad = Math.tan(this._viewAngle * math.RADIANS_HALF);
|
||||
this._tanViewAngle_hrad = Math.tan(this._viewAngle * RADIANS_HALF);
|
||||
this._tanViewAngle_hradOneByHeight = this._tanViewAngle_hrad * (1.0 / this._height);
|
||||
this._projSizeConst =
|
||||
Math.min(
|
||||
this._width < 512 ? 512 : this._width,
|
||||
this._height < 512 ? 512 : this._height
|
||||
) /
|
||||
(this._viewAngle * RADIANS);
|
||||
Math.min(this._width < 512 ? 512 : this._width, this._height < 512 ? 512 : this._height) / (this._viewAngle * RADIANS);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -878,21 +873,43 @@ class Camera {
|
||||
* @param {number} y - Screen Y coordinate
|
||||
* @returns {Vec3} - Direction vector
|
||||
*/
|
||||
public unproject(x: number, y: number) {
|
||||
public unproject(x: number, y: number, dist?: number, outPos?: Vec3) {
|
||||
let w = this._width * 0.5,
|
||||
h = this._height * 0.5;
|
||||
|
||||
let px = (x - w) / w,
|
||||
py = -(y - h) / h;
|
||||
|
||||
let world1 = this.frustums[0].inverseProjectionViewMatrix
|
||||
.mulVec4(new Vec4(px, py, -1.0, 1.0))
|
||||
.affinity(),
|
||||
world2 = this.frustums[0].inverseProjectionViewMatrix
|
||||
.mulVec4(new Vec4(px, py, 0.0, 1.0))
|
||||
.affinity();
|
||||
let f = this.frustums[0];
|
||||
|
||||
return world2.subA(world1).toVec3().normalize();
|
||||
if (this.isOrthographic) {
|
||||
if (dist) {
|
||||
let dx = 0.5 * (f.right - f.left) * px,
|
||||
dy = 0.5 * (f.top - f.bottom) * py;
|
||||
|
||||
let wdy = this.getUp().scale(dy),
|
||||
wdx = this.getRight().scale(dx);
|
||||
|
||||
let wd = wdy.addA(wdx);
|
||||
let p0 = this.eye.add(wd);
|
||||
|
||||
let dir = this.getForward();
|
||||
let p1 = p0.addA(dir.scaleTo(dist));
|
||||
|
||||
if (outPos) {
|
||||
outPos.copy(p1);
|
||||
}
|
||||
|
||||
return p1.sub(this.eye).normalize();
|
||||
} else {
|
||||
return this.getForward();
|
||||
}
|
||||
} else {
|
||||
let invPV = f.inverseProjectionViewMatrix;
|
||||
let nearPoint = invPV.mulVec4(new Vec4(px, py, -1.0, 1.0)).affinity(),
|
||||
farPoint = invPV.mulVec4(new Vec4(px, py, 0.0, 1.0)).affinity();
|
||||
return farPoint.subA(nearPoint).toVec3().normalize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -967,12 +984,16 @@ class Camera {
|
||||
|
||||
/**
|
||||
* Gets 3d size factor. Uses in LOD distance calculation.
|
||||
* It is very important function used in Node.ts
|
||||
* @public
|
||||
* @param {Vec3} p - Far point.
|
||||
* @param {Vec3} r - Far point.
|
||||
* @param {Vec3} p - Point in 3d.
|
||||
* @param {Vec3} r - size.
|
||||
* @returns {number} - Size factor.
|
||||
*/
|
||||
public projectedSize(p: Vec3, r: number): number {
|
||||
//
|
||||
//@todo: orthographic
|
||||
//
|
||||
return Math.atan(r / this.eye.distance(p)) * this._projSizeConst;
|
||||
}
|
||||
|
||||
@ -1085,4 +1106,4 @@ class Camera {
|
||||
}
|
||||
}
|
||||
|
||||
export { Camera };
|
||||
export {Camera};
|
||||
|
||||
@ -174,28 +174,35 @@ class Frustum {
|
||||
/**
|
||||
* Sets up camera projection matrix.
|
||||
* @public
|
||||
* @param {number} angle - Camera's vertical fov view angle.
|
||||
* @param {number} viewAngle - Camera's vertical fov view angle.
|
||||
* @param {number} aspect - Screen aspect ratio.
|
||||
* @param {number} near - Near camera distance.
|
||||
* @param {number} far - Far camera distance.
|
||||
*/
|
||||
public setProjectionMatrix(angle: number, aspect: number, near: number, far: number) {
|
||||
this.top = near * Math.tan(angle * RADIANS_HALF);
|
||||
public setProjectionMatrix(viewAngle: number, aspect: number, near: number, far: number, isOrthographic?: boolean, focusDistance: number = 10) {
|
||||
|
||||
if (isOrthographic) {
|
||||
let h = focusDistance * Math.tan(viewAngle * RADIANS_HALF);
|
||||
let w = h * aspect;
|
||||
this._setFrustumParams(h, w, near, far);
|
||||
this.projectionMatrix.setOrthographic(this.left, this.right, this.bottom, this.top, this.near, this.far);
|
||||
} else {
|
||||
let h = near * Math.tan(viewAngle * RADIANS_HALF);
|
||||
let w = h * aspect;
|
||||
this._setFrustumParams(h, w, near, far);
|
||||
this.projectionMatrix.setPerspective(this.left, this.right, this.bottom, this.top, this.near, this.far);
|
||||
}
|
||||
|
||||
this.projectionMatrix.inverseTo(this.inverseProjectionMatrix);
|
||||
}
|
||||
|
||||
protected _setFrustumParams(top: number, right: number, near: number, far: number) {
|
||||
this.top = top;
|
||||
this.right = right;
|
||||
this.bottom = -this.top;
|
||||
this.right = this.top * aspect;
|
||||
this.left = -this.right;
|
||||
this.near = near;
|
||||
this.far = far;
|
||||
|
||||
this.projectionMatrix.setPerspective(
|
||||
this.left,
|
||||
this.right,
|
||||
this.bottom,
|
||||
this.top,
|
||||
near,
|
||||
far
|
||||
);
|
||||
this.projectionMatrix.inverseTo(this.inverseProjectionMatrix);
|
||||
}
|
||||
|
||||
public setProjectionViewRTEMatrix(viewRTEMatrix: Mat4) {
|
||||
|
||||
@ -455,7 +455,7 @@ class PlanetCamera extends Camera {
|
||||
// camera path and orientations calculation
|
||||
let g_i = ground_a.smerp(ground_b, d).normalize();
|
||||
let ground_i = this.planet.getRayIntersectionEllipsoid(new Ray(zero, g_i));
|
||||
|
||||
|
||||
let height_i =
|
||||
this._lonLat.height * d * d * d +
|
||||
max_h * 3 * d * d * t +
|
||||
|
||||
@ -200,11 +200,11 @@ export class DebugInfo extends Control {
|
||||
this.addWatches([
|
||||
{
|
||||
label: "Nodes count",
|
||||
frame: () => p!._renderedNodes.length
|
||||
frame: () => p!.quadTreeStrategy._renderedNodes.length
|
||||
},
|
||||
{
|
||||
label: "Planet._fadingNodes",
|
||||
frame: () => p._fadingNodes.size
|
||||
frame: () => p.quadTreeStrategy._fadingNodes.size
|
||||
},
|
||||
{
|
||||
label: "createdNodes",
|
||||
@ -220,7 +220,7 @@ export class DebugInfo extends Control {
|
||||
},
|
||||
{
|
||||
label: "maxZoom/minZoom",
|
||||
frame: () => p.maxCurrZoom + " / " + p?.minCurrZoom
|
||||
frame: () => p.quadTreeStrategy.maxCurrZoom + " / " + p?.quadTreeStrategy.minCurrZoom
|
||||
},
|
||||
{
|
||||
label: "viewExtent",
|
||||
@ -238,7 +238,7 @@ export class DebugInfo extends Control {
|
||||
},
|
||||
{
|
||||
label: "lodSize",
|
||||
frame: () => Math.round(p.lodSize)
|
||||
frame: () => Math.round(p.quadTreeStrategy.lodSize)
|
||||
},
|
||||
{
|
||||
label: "deltaTime/FPS",
|
||||
@ -285,11 +285,11 @@ export class DebugInfo extends Control {
|
||||
},
|
||||
{
|
||||
label: "_renderCompleted / renderCompletedActivated",
|
||||
frame: () => `${p._renderCompleted} / ${p._renderCompletedActivated}`
|
||||
frame: () => `${p.quadTreeStrategy._renderCompleted} / ${p.quadTreeStrategy._renderCompletedActivated}`
|
||||
},
|
||||
{
|
||||
label: "_terrainCompleted / terrainCompletedActivated",
|
||||
frame: () => `${p._terrainCompleted} / ${p._terrainCompletedActivated}`
|
||||
frame: () => `${p.quadTreeStrategy._terrainCompleted} / ${p.quadTreeStrategy._terrainCompletedActivated}`
|
||||
},
|
||||
{
|
||||
label: "PlainWorker",
|
||||
|
||||
@ -33,8 +33,8 @@ export class SegmentBoundVisualization extends Control {
|
||||
|
||||
protected _draw() {
|
||||
const planet = this.planet!;
|
||||
for (let i = 0; i < planet._renderedNodes.length; i++) {
|
||||
let si = planet._renderedNodes[i].segment as SegmentExt;
|
||||
for (let i = 0; i < planet.quadTreeStrategy._renderedNodes.length; i++) {
|
||||
let si = planet.quadTreeStrategy._renderedNodes[i].segment as SegmentExt;
|
||||
if (!si._sphereEntity) {
|
||||
si._sphereEntity = new Entity({
|
||||
billboard: {
|
||||
|
||||
@ -2,10 +2,12 @@ import {Control} from "./Control";
|
||||
import type {IControlParams} from "./Control";
|
||||
import {input} from "../input/input";
|
||||
import type {IMouseState} from "../renderer/RendererEvents";
|
||||
import {Vec2} from "../math/Vec2";
|
||||
import {Vec3} from "../math/Vec3";
|
||||
import * as math from "../math";
|
||||
import {Ray} from "../math/Ray";
|
||||
import {Plane} from "../math/Plane";
|
||||
import {Camera} from "../camera/Camera";
|
||||
|
||||
interface ISimpleNavigationParams extends IControlParams {
|
||||
speed?: number;
|
||||
@ -20,11 +22,19 @@ export class SimpleNavigation extends Control {
|
||||
public vel: Vec3;
|
||||
public mass: number;
|
||||
|
||||
public focusVel: number = 0;
|
||||
public focusForce: number = 0;
|
||||
|
||||
protected _lookPos: Vec3 | undefined;
|
||||
protected _up: Vec3 | null;
|
||||
|
||||
protected _grabbedPoint: Vec3 | undefined;
|
||||
protected _grabbedScreenPoint: Vec2;
|
||||
protected _eye0: Vec3;
|
||||
protected _wheelDist: number;
|
||||
protected _wheelPos: Vec3;
|
||||
protected _nx: number = 0;
|
||||
protected _ny: number = 0;
|
||||
|
||||
constructor(options: ISimpleNavigationParams = {}) {
|
||||
super({
|
||||
@ -38,19 +48,28 @@ export class SimpleNavigation extends Control {
|
||||
|
||||
this._lookPos = undefined;
|
||||
this._grabbedPoint = undefined;
|
||||
this._grabbedScreenPoint = new Vec2();
|
||||
this._up = null;
|
||||
|
||||
this._eye0 = new Vec3();
|
||||
this._wheelDist = 0;
|
||||
this._wheelPos = new Vec3();
|
||||
}
|
||||
|
||||
override oninit() {
|
||||
|
||||
}
|
||||
|
||||
public override onactivate() {
|
||||
super.onactivate();
|
||||
|
||||
let r = this.renderer!;
|
||||
|
||||
if (r.activeCamera.isOrthographic) {
|
||||
r.getDepthMinDistanceAsync().then((dist) => {
|
||||
r.activeCamera.focusDistance = dist;
|
||||
});
|
||||
}
|
||||
|
||||
r.events.on("mousewheel", this._onMouseWheel);
|
||||
r.events.on("keypress", input.KEY_W, this.onCameraMoveForward, this);
|
||||
r.events.on("keypress", input.KEY_S, this.onCameraMoveBackward, this);
|
||||
@ -66,8 +85,8 @@ export class SimpleNavigation extends Control {
|
||||
r.events.on("rhold", this._onRHold, this);
|
||||
r.events.on("rdown", this._onRDown, this);
|
||||
|
||||
r.events.on("lhold", this._onMouseLeftButtonDown);
|
||||
r.events.on("ldown", this._onMouseLeftButtonClick);
|
||||
r.events.on("lhold", this._onMouseLeftButtonHold);
|
||||
r.events.on("ldown", this._onMouseLeftButtonDown);
|
||||
r.events.on("lup", this._onMouseLeftButtonUp);
|
||||
|
||||
r.events.on("draw", this.onDraw, this, -1000);
|
||||
@ -91,17 +110,19 @@ export class SimpleNavigation extends Control {
|
||||
r.events.off("rhold", this._onRHold);
|
||||
r.events.off("rdown", this._onRDown);
|
||||
|
||||
r.events.off("lhold", this._onMouseLeftButtonDown);
|
||||
r.events.off("ldown", this._onMouseLeftButtonClick);
|
||||
r.events.off("lhold", this._onMouseLeftButtonHold);
|
||||
r.events.off("ldown", this._onMouseLeftButtonDown);
|
||||
r.events.off("lup", this._onMouseLeftButtonUp);
|
||||
|
||||
r.events.off("draw", this.onDraw);
|
||||
}
|
||||
|
||||
protected _onMouseLeftButtonClick = (e: IMouseState) => {
|
||||
protected _onMouseLeftButtonDown = (e: IMouseState) => {
|
||||
if (this._active && this.renderer) {
|
||||
this.stop();
|
||||
this.renderer.handler.canvas!.classList.add("ogGrabbingPoiner");
|
||||
this._grabbedPoint = this.renderer.getCartesianFromPixel(e);
|
||||
this._grabbedScreenPoint.set(e.nx, e.ny);
|
||||
if (this._grabbedPoint) {
|
||||
this._eye0.copy(this.renderer.activeCamera.eye);
|
||||
}
|
||||
@ -115,19 +136,21 @@ export class SimpleNavigation extends Control {
|
||||
}
|
||||
}
|
||||
|
||||
protected _onMouseLeftButtonDown = (e: IMouseState) => {
|
||||
if (this._active && this.renderer) {
|
||||
if (!this._grabbedPoint) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.moving) {
|
||||
let cam = this.renderer.activeCamera;
|
||||
|
||||
protected _onMouseLeftButtonHold = (e: IMouseState) => {
|
||||
if (this.renderer && this._grabbedPoint && e.moving) {
|
||||
let cam = this.renderer.activeCamera;
|
||||
if (cam.isOrthographic) {
|
||||
let nx = e.nx - this._grabbedScreenPoint.x;
|
||||
let ny = e.ny - this._grabbedScreenPoint.y;
|
||||
let f = cam.frustum;
|
||||
let dx = -(f.right - f.left) * nx,
|
||||
dy = (f.top - f.bottom) * ny;
|
||||
let cam_sy = cam.getUp().scale(dy),
|
||||
cam_sx = cam.getRight().scale(dx);
|
||||
cam.eye = this._eye0.add(cam_sx.add(cam_sy));
|
||||
} else {
|
||||
let camSlope = Math.abs(cam.getForward().dot(Vec3.UP));
|
||||
|
||||
let p0 = this._grabbedPoint, p1, p2;
|
||||
|
||||
if (camSlope > 0.7) {
|
||||
p1 = Vec3.add(p0, Vec3.LEFT);
|
||||
p2 = Vec3.add(p0, cam.getRight());
|
||||
@ -135,12 +158,12 @@ export class SimpleNavigation extends Control {
|
||||
p1 = Vec3.add(p0, cam.getRight());
|
||||
p2 = Vec3.add(p0, Vec3.UP);
|
||||
}
|
||||
|
||||
let px = new Vec3();
|
||||
if (new Ray(cam.eye, e.direction).hitPlaneRes(Plane.fromPoints(p0, p1, p2), px) === Ray.INSIDE) {
|
||||
cam.eye = this._eye0.addA(px.subA(p0).negate());
|
||||
cam.eye = cam.eye.add(p0.sub(px));
|
||||
}
|
||||
}
|
||||
cam.update();
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,26 +179,56 @@ export class SimpleNavigation extends Control {
|
||||
}
|
||||
cam.rotateHorizontal(l * (e.x - e.prev_x), false, this._lookPos, this._up!);
|
||||
cam.rotateVertical(l * (e.y - e.prev_y), this._lookPos);
|
||||
cam.update();
|
||||
}
|
||||
}
|
||||
|
||||
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;//this.renderer.activeCamera.getUp();
|
||||
this._up = Vec3.UP;
|
||||
} else {
|
||||
const cam = this.renderer.activeCamera;
|
||||
let pl = new Plane(Vec3.ZERO, Vec3.UP);
|
||||
let ray = new Ray(cam.eye, e.direction);
|
||||
this._lookPos = new Vec3();
|
||||
ray.hitPlaneRes(pl, this._lookPos)
|
||||
this._up = Vec3.UP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected _onMouseWheel = (e: IMouseState) => {
|
||||
if (this.renderer) {
|
||||
let pos = this.renderer.getCartesianFromPixel(e),
|
||||
dist = 10;
|
||||
if (pos) {
|
||||
dist = this.renderer.activeCamera.eye.distance(pos);
|
||||
let cam = this.renderer.activeCamera;
|
||||
|
||||
if (cam.isOrthographic) {
|
||||
let f = cam.frustums[0];
|
||||
let dx = -(f.right - f.left) * (0.5 - e.nx),
|
||||
dy = (f.top - f.bottom) * (0.5 - e.ny);
|
||||
let wdy = cam.getUp().scale(dy),
|
||||
wdx = cam.getRight().scale(dx);
|
||||
let p = cam.eye.add(wdx.add(wdy));
|
||||
this._wheelPos = p.add(cam.getForward());
|
||||
this._wheelDist = 1;
|
||||
this._nx = e.nx;
|
||||
this._ny = e.ny;
|
||||
this.focusForce = 0.05 * e.wheelDelta;
|
||||
} else {
|
||||
let pos = this.renderer.getCartesianFromPixel(e);
|
||||
if (!pos) {
|
||||
pos = new Vec3();
|
||||
let pl = new Plane(Vec3.ZERO, Vec3.UP);
|
||||
let ray = new Ray(cam.eye, e.direction);
|
||||
ray.hitPlaneRes(pl, pos);
|
||||
}
|
||||
let dir = pos.sub(cam.eye).normalize();
|
||||
let dist = cam.eye.distance(pos) * 8;
|
||||
this.force.addA(dir.scale(e.wheelDelta)).normalize().scale(dist);
|
||||
}
|
||||
this.force.addA(e.direction.scale(e.wheelDelta)).normalize().scale(dist);
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,55 +250,77 @@ export class SimpleNavigation extends Control {
|
||||
|
||||
protected onCameraLookUp = () => {
|
||||
let cam = this.renderer!.activeCamera!;
|
||||
cam.setPitch(0.5);
|
||||
cam.update();
|
||||
}
|
||||
|
||||
protected onCameraLookDown = () => {
|
||||
let cam = this.renderer!.activeCamera!;
|
||||
cam.setPitch(-0.5);
|
||||
cam.update();
|
||||
}
|
||||
|
||||
protected onCameraTurnLeft = () => {
|
||||
let cam = this.renderer!.activeCamera!;
|
||||
cam.setYaw(0.5);
|
||||
cam.update();
|
||||
}
|
||||
|
||||
protected onCameraTurnRight = () => {
|
||||
let cam = this.renderer!.activeCamera!;
|
||||
cam.setYaw(-0.5);
|
||||
cam.update();
|
||||
}
|
||||
|
||||
protected onCameraRollLeft = () => {
|
||||
let cam = this.renderer!.activeCamera!;
|
||||
cam.setRoll(-0.5);
|
||||
cam.update();
|
||||
}
|
||||
|
||||
protected onCameraRollRight = () => {
|
||||
let cam = this.renderer!.activeCamera!;
|
||||
cam.setRoll(0.5);
|
||||
cam.update();
|
||||
}
|
||||
|
||||
protected _handleMouseWheel() {
|
||||
let cam = this.renderer!.activeCamera;
|
||||
|
||||
if (cam.isOrthographic && Math.abs(this.focusVel) > 0.01) {
|
||||
cam.eye = this._wheelPos.add(cam.getBackward().scale(this._wheelDist));
|
||||
cam.focusDistance -= cam.focusDistance * this.focusVel * this.dt;
|
||||
|
||||
let f = cam.frustums[0];
|
||||
let dx = (f.right - f.left) * (0.5 - this._nx),
|
||||
dy = -(f.top - f.bottom) * (0.5 - this._ny);
|
||||
let wdy = cam.getUp().scale(dy),
|
||||
wdx = cam.getRight().scale(dx);
|
||||
|
||||
cam.eye.addA(wdx.add(wdy));
|
||||
cam.update();
|
||||
} else if (this.vel.length() > 0.01) {
|
||||
cam.eye = cam.eye.add(this.vel.scaleTo(this.dt));
|
||||
cam.update();
|
||||
}
|
||||
}
|
||||
|
||||
protected onDraw() {
|
||||
this._updateVel();
|
||||
this._handleMouseWheel();
|
||||
}
|
||||
|
||||
protected get dt(): number {
|
||||
return 0.001 * this.renderer!.handler.deltaTime;
|
||||
}
|
||||
|
||||
protected onDraw() {
|
||||
if (this.renderer) {
|
||||
protected _updateVel() {
|
||||
let acc = this.force.scale(1.0 / this.mass);
|
||||
this.vel.addA(acc);
|
||||
this.vel.scale(0.77);
|
||||
this.force.set(0, 0, 0);
|
||||
|
||||
let acc = this.force.scale(1.0 / this.mass);
|
||||
this.vel.addA(acc);
|
||||
this.vel.scale(0.96);
|
||||
this.force.set(0, 0, 0);
|
||||
this.focusVel += this.focusForce;
|
||||
this.focusVel *= 0.77;
|
||||
this.focusForce = 0;
|
||||
}
|
||||
|
||||
let cam = this.renderer.activeCamera;
|
||||
cam.eye = cam.eye.add(this.vel.scaleTo(this.dt));
|
||||
cam.update();
|
||||
}
|
||||
public stop() {
|
||||
this.focusVel = 0;
|
||||
this.vel.clear();
|
||||
}
|
||||
}
|
||||
@ -106,14 +106,14 @@ export class Atmosphere extends Control {
|
||||
|
||||
public initLookupTexturesShaders() {
|
||||
if (this.renderer) {
|
||||
this.renderer.handler.addProgram(transmittance(this._parameters), true);
|
||||
this.renderer.handler.addProgram(scattering(this._parameters), true);
|
||||
this.renderer.handler.addProgram(transmittance(this._parameters));
|
||||
this.renderer.handler.addProgram(scattering(this._parameters));
|
||||
}
|
||||
}
|
||||
|
||||
public initBackgroundShader() {
|
||||
if (this.renderer) {
|
||||
this.renderer.handler.addProgram(atmosphereBackgroundShader(this._parameters), true);
|
||||
this.renderer.handler.addProgram(atmosphereBackgroundShader(this._parameters));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ import {Vec4} from "../../math/Vec4";
|
||||
import {Vec3} from "../../math/Vec3";
|
||||
import {LonLat} from "../../LonLat";
|
||||
import {GeoImage} from "../../layer/GeoImage";
|
||||
import {QuadTreeStrategy} from "../../quadTree";
|
||||
|
||||
|
||||
function getDistanceFromPixel(x: number, y: number, camera: Camera, framebuffer: Framebuffer): number {
|
||||
@ -45,22 +46,26 @@ function getDistanceFromPixel(x: number, y: number, camera: Camera, framebuffer:
|
||||
const CAM_WIDTH = 640;
|
||||
const CAM_HEIGHT = 480;
|
||||
|
||||
export interface ICameraDepthhandlerParams extends IControlParams {
|
||||
export interface ICameraDepthHandlerParams extends IControlParams {
|
||||
|
||||
}
|
||||
|
||||
export class CameraDepthHandler extends Control {
|
||||
|
||||
protected _depthHandler: CameraFrameHandler | null;
|
||||
protected _frameHandler: CameraFrameHandler | null;
|
||||
protected _frameComposer: CameraFrameComposer;
|
||||
|
||||
public readonly cameraGeoImage: GeoImage;
|
||||
|
||||
constructor(params: ICameraDepthhandlerParams) {
|
||||
protected _quadTreeStrategy: QuadTreeStrategy | null;
|
||||
|
||||
protected _skipPreRender = false;
|
||||
|
||||
constructor(params: ICameraDepthHandlerParams) {
|
||||
super(params);
|
||||
|
||||
this._frameComposer = new CameraFrameComposer();
|
||||
this._depthHandler = null;
|
||||
this._frameHandler = null;
|
||||
|
||||
this.cameraGeoImage = new GeoImage(`cameraGeoImage:${this.__id}`, {
|
||||
src: "test4.jpg",
|
||||
@ -69,19 +74,21 @@ export class CameraDepthHandler extends Control {
|
||||
isBaseLayer: false,
|
||||
opacity: 0.7
|
||||
});
|
||||
|
||||
this._quadTreeStrategy = null;
|
||||
}
|
||||
|
||||
protected _createCamera(): Camera {
|
||||
if (this.planet) {
|
||||
return new PlanetCamera(this.planet, {
|
||||
frustums: [[10, 10000]],
|
||||
frustums: [[100, 1000000000]],
|
||||
width: CAM_WIDTH,
|
||||
height: CAM_HEIGHT,
|
||||
viewAngle: 45
|
||||
})
|
||||
} else {
|
||||
return new Camera({
|
||||
frustums: [[10, 10000]],
|
||||
frustums: [[100, 1000000000]],
|
||||
width: CAM_WIDTH,
|
||||
height: CAM_HEIGHT,
|
||||
viewAngle: 45
|
||||
@ -90,8 +97,8 @@ export class CameraDepthHandler extends Control {
|
||||
}
|
||||
|
||||
public get camera(): Camera | undefined {
|
||||
if (this._depthHandler) {
|
||||
return this._depthHandler.camera;
|
||||
if (this._frameHandler) {
|
||||
return this._frameHandler.camera;
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,7 +125,7 @@ export class CameraDepthHandler extends Control {
|
||||
useDepth: true
|
||||
});
|
||||
|
||||
this._depthHandler = new CameraFrameHandler({
|
||||
this._frameHandler = new CameraFrameHandler({
|
||||
camera: this._createCamera(),
|
||||
frameBuffer: depthFramebuffer,
|
||||
frameHandler: this._depthHandlerCallback
|
||||
@ -130,12 +137,32 @@ export class CameraDepthHandler extends Control {
|
||||
this.renderer.addControl(this._frameComposer);
|
||||
}
|
||||
|
||||
this._frameComposer.add(this._depthHandler);
|
||||
this._frameComposer.add(this._frameHandler);
|
||||
|
||||
if (this.planet) {
|
||||
|
||||
const quadTreeParams = {
|
||||
planet: this.planet,
|
||||
maxEqualZoomAltitude: this.planet.quadTreeStrategy.maxEqualZoomAltitude,
|
||||
minEqualZoomAltitude: this.planet.quadTreeStrategy.minEqualZoomAltitude,
|
||||
minEqualZoomCameraSlope: this.planet.quadTreeStrategy.minEqualZoomCameraSlope,
|
||||
transitionOpacityEnabled: false,
|
||||
};
|
||||
|
||||
this._quadTreeStrategy = new this.planet.quadTreeStrategyPrototype(quadTreeParams);
|
||||
|
||||
this._quadTreeStrategy.init(this.camera as PlanetCamera);
|
||||
|
||||
this._quadTreeStrategy.preRender();
|
||||
this._quadTreeStrategy.clearRenderedNodes();
|
||||
this._skipPreRender = false;
|
||||
this._quadTreeStrategy.preLoad();
|
||||
}
|
||||
}
|
||||
|
||||
public get framebuffer(): Framebuffer | undefined {
|
||||
if (this._depthHandler) {
|
||||
return this._depthHandler.frameBuffer;
|
||||
if (this._frameHandler) {
|
||||
return this._frameHandler.frameBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,12 +170,24 @@ export class CameraDepthHandler extends Control {
|
||||
|
||||
if (!this.planet) return;
|
||||
|
||||
let cam = frameHandler.camera,
|
||||
framebuffer = frameHandler.frameBuffer,
|
||||
let framebuffer = frameHandler.frameBuffer,
|
||||
gl = framebuffer.handler.gl!;
|
||||
|
||||
framebuffer.activate();
|
||||
|
||||
if (this._quadTreeStrategy) {
|
||||
let cam = frameHandler.camera as PlanetCamera;
|
||||
|
||||
if (this._skipPreRender) {
|
||||
this._quadTreeStrategy.collectRenderNodes(cam);
|
||||
}
|
||||
|
||||
this._skipPreRender = true;
|
||||
|
||||
console.log(this._quadTreeStrategy._renderedNodes);
|
||||
//this.planet.renderDepthFramebuffer(cam, this._quadTreeStrategy);
|
||||
}
|
||||
/*
|
||||
gl.clearColor(0.0, 0.0, 0.0, 1.0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
gl.disable(gl.BLEND);
|
||||
@ -165,7 +204,7 @@ export class CameraDepthHandler extends Control {
|
||||
gl.uniform3fv(shu.eyePositionLow, cam.eyeLow);
|
||||
|
||||
// drawing planet nodes
|
||||
let rn = this.planet._renderedNodes;
|
||||
let rn = this.planet.quadTreeStrategy._renderedNodes;
|
||||
|
||||
let i = rn.length;
|
||||
while (i--) {
|
||||
@ -174,11 +213,10 @@ export class CameraDepthHandler extends Control {
|
||||
}
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
for (let i = 0; i < this.planet._fadingOpaqueSegments.length; ++i) {
|
||||
//@ts-ignore
|
||||
this.planet._fadingOpaqueSegments[i].depthRendering(sh);
|
||||
for (let i = 0; i < this.planet.quadTreeStrategy._fadingOpaqueSegments.length; ++i) {
|
||||
this.planet.quadTreeStrategy._fadingOpaqueSegments[i].depthRendering(sh);
|
||||
}
|
||||
*/
|
||||
|
||||
framebuffer.deactivate();
|
||||
|
||||
@ -194,38 +232,12 @@ export class CameraDepthHandler extends Control {
|
||||
if (lt && rt && rb && lb) {
|
||||
this.cameraGeoImage.setCorners([[lt.lon, lt.lat], [rt.lon, rt.lat], [rb.lon, rb.lat], [lb.lon, lb.lat]]);
|
||||
}
|
||||
|
||||
// let r = globus.renderer;
|
||||
//
|
||||
// // PASS to depth visualization
|
||||
// r.screenDepthFramebuffer.activate();
|
||||
// sh = h.programs.depth;
|
||||
// let p = sh._program;
|
||||
//
|
||||
// gl.bindBuffer(gl.ARRAY_BUFFER, r.screenFramePositionBuffer);
|
||||
// gl.vertexAttribPointer(p.attributes.corners, 2, gl.FLOAT, false, 0, 0);
|
||||
//
|
||||
// sh.activate();
|
||||
//
|
||||
// gl.activeTexture(gl.TEXTURE0);
|
||||
// gl.bindTexture(gl.TEXTURE_2D, framebuffer.textures[0]);
|
||||
// gl.uniform1i(p.uniforms.depthTexture, 0);
|
||||
//
|
||||
// gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||||
//
|
||||
// r.screenDepthFramebuffer.deactivate();
|
||||
// gl.enable(gl.BLEND);
|
||||
|
||||
// frameHandler.cameraEntity.setCartesian3v(cam.eye);
|
||||
// frameHandler.cameraEntity.setPitch(cam.getPitch());
|
||||
// frameHandler.cameraEntity.setYaw(cam.getYaw());
|
||||
// frameHandler.cameraEntity.setRoll(cam.getRoll());
|
||||
}
|
||||
|
||||
public getCartesianFromPixelTerrain(x: number, y: number): Vec3 | undefined {
|
||||
if (this._depthHandler) {
|
||||
let framebuffer = this._depthHandler.frameBuffer;
|
||||
let camera = this._depthHandler.camera;
|
||||
if (this._frameHandler) {
|
||||
let framebuffer = this._frameHandler.frameBuffer;
|
||||
let camera = this._frameHandler.camera;
|
||||
let distance = getDistanceFromPixel(x, y, camera, framebuffer);
|
||||
if (distance === 0) {
|
||||
return;
|
||||
|
||||
@ -440,7 +440,7 @@ class PolygonDrawingScene extends RenderNode {
|
||||
|
||||
protected _checkTerrainCollision(entity: Entity) {
|
||||
let _tempTerrPoint = new Vec3();
|
||||
let nodes = this._planet!._renderedNodes;
|
||||
let nodes = this._planet!.quadTreeStrategy._renderedNodes;
|
||||
for (let j = 0; j < nodes.length; j++) {
|
||||
let seg = nodes[j].segment;
|
||||
if (seg && seg._extentLonLat.isInside(entity.getLonLat())) {
|
||||
|
||||
@ -678,7 +678,7 @@ class ElevationProfileScene extends RenderNode {
|
||||
public override frame() {
|
||||
if (this._clampToGround) {
|
||||
let __tempVec__ = new Vec3();
|
||||
const nodes = this._planet!._renderedNodes;
|
||||
const nodes = this._planet!.quadTreeStrategy._renderedNodes;
|
||||
const entities = this._groundPointersLayer.getEntities();
|
||||
for (let i = 0; i < entities.length; i++) {
|
||||
let ei = entities[i];
|
||||
|
||||
@ -117,6 +117,8 @@ class Entity {
|
||||
|
||||
static __counter__: number = 0;
|
||||
|
||||
protected _name: string;
|
||||
|
||||
/**
|
||||
* Uniq identifier.
|
||||
* @public
|
||||
@ -311,9 +313,11 @@ class Entity {
|
||||
|
||||
this.__id = Entity.__counter__++;
|
||||
|
||||
this._name = options.name || `entity:${this.__id}`;
|
||||
|
||||
this.properties = options.properties || {};
|
||||
|
||||
this.properties.name = this.properties.name != undefined ? this.properties.name : "";
|
||||
//this.properties.name = this.properties.name != undefined ? this.properties.name : "";
|
||||
|
||||
this.childEntities = [];
|
||||
|
||||
@ -395,6 +399,17 @@ class Entity {
|
||||
|
||||
}
|
||||
|
||||
public get name(): string {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
public set name(name: string) {
|
||||
if (name !== this._name) {
|
||||
this._name = name;
|
||||
//ec && ec.events.dispatch(ec.events.entityname, this);
|
||||
}
|
||||
}
|
||||
|
||||
public get isEmpty(): boolean {
|
||||
return !(this.strip
|
||||
|| this.polyline
|
||||
@ -531,11 +546,10 @@ class Entity {
|
||||
* Adds current entity into the specified entity collection.
|
||||
* @public
|
||||
* @param {EntityCollection | Vector} collection - Specified entity collection or vector layer.
|
||||
* @param {boolean} [rightNow=false] - Entity insertion option for vector layer.
|
||||
* @returns {Entity} - This object.
|
||||
*/
|
||||
public addTo(collection: EntityCollection | Vector, rightNow: boolean = false): Entity {
|
||||
collection.add(this, rightNow);
|
||||
public addTo(collection: EntityCollection | Vector): Entity {
|
||||
collection.add(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -722,6 +736,9 @@ class Entity {
|
||||
this._rollRad = this._qRot.getRoll();
|
||||
|
||||
this._updateAbsolutePosition();
|
||||
|
||||
// ?
|
||||
//this._useDirectQuaternion = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -972,7 +989,13 @@ class Entity {
|
||||
this._rootCartesian.copy(parent._rootCartesian);
|
||||
|
||||
if (!this._useDirectQuaternion) {
|
||||
this._qRot.setPitchYawRoll(this._pitchRad, this._yawRad, this._rollRad);
|
||||
//this._qRot.setPitchYawRoll(this._pitchRad, this._yawRad, this._rollRad);
|
||||
|
||||
if (parent && this.forceGlobalRotation) {
|
||||
this._qRot.setPitchYawRoll(parent._pitchRad, parent._yawRad, parent._rollRad);
|
||||
} else {
|
||||
this._qRot.setPitchYawRoll(this._pitchRad, this._yawRad, this._rollRad);
|
||||
}
|
||||
}
|
||||
parent._absoluteQRot.mulRes(this._qRot, this._absoluteQRot);
|
||||
|
||||
@ -1306,6 +1329,21 @@ class Entity {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append child entity.
|
||||
* @public
|
||||
* @param {Entity[]} entities - Child entities.
|
||||
* @param {boolean} [forceRelativePosition] - Force relative position property.
|
||||
*/
|
||||
public appendChildren(entities: Entity[], forceRelativePosition?: boolean) {
|
||||
for (let i = 0; i < entities.length; i++) {
|
||||
if (forceRelativePosition !== undefined) {
|
||||
entities[i].relativePosition = forceRelativePosition;
|
||||
}
|
||||
this.appendChild(entities[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append child entity.
|
||||
* @public
|
||||
|
||||
@ -105,7 +105,7 @@ class GeoObject {
|
||||
|
||||
this._position = utils.createVector3(options.position);
|
||||
|
||||
this._rtcPositionHigh = new Vec3();
|
||||
this._rtcPositionHigh = new Vec3();``
|
||||
this._rtcPositionLow = new Vec3();
|
||||
|
||||
this._scale = utils.createVector3(options.scale, new Vec3(1, 1, 1));
|
||||
@ -113,11 +113,11 @@ class GeoObject {
|
||||
|
||||
this._localPosition = new Vec3();
|
||||
|
||||
this._color = utils.createColorRGBA(
|
||||
options.color, options.object3d?.color
|
||||
? new Vec4(...Array.from(options.object3d.color))
|
||||
: new Vec4(0.15, 0.15, 0.15, 1.0)
|
||||
);
|
||||
const [r = 0.15, g = 0.15, b = 0.15, a = 1.0] = options.object3d?.color
|
||||
? Array.from(options.object3d.color)
|
||||
: [];
|
||||
|
||||
this._color = utils.createColorRGBA(options.color, new Vec4(r, g, b, a));
|
||||
|
||||
this._handler = null;
|
||||
this._handlerIndex = -1;
|
||||
|
||||
@ -53,8 +53,8 @@ export interface IPolylineParams {
|
||||
pathColors?: SegmentPathColor[];
|
||||
path3v?: SegmentPath3vExt[];
|
||||
pathLonLat?: SegmentPathLonLatExt[];
|
||||
visibleSpherePosition?: Cartesian,
|
||||
visibleSphereRadius?: number
|
||||
visibleSpherePosition?: Cartesian;
|
||||
visibleSphereRadius?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -122,7 +122,7 @@ class CanvasTiles extends Layer {
|
||||
}
|
||||
|
||||
public _onLoadend() {
|
||||
if (this._planet && this._planet._terrainCompletedActivated) {
|
||||
if (this._planet && this._planet.quadTreeStrategy._terrainCompletedActivated) {
|
||||
this._planet.events.dispatch(this._planet.events.layerloadend, this);
|
||||
}
|
||||
}
|
||||
@ -241,7 +241,7 @@ class CanvasTiles extends Layer {
|
||||
this._exec(pmat);
|
||||
}
|
||||
}
|
||||
} else if (this._counter === 0 && this._planet && this._planet._terrainCompletedActivated) {
|
||||
} else if (this._counter === 0 && this._planet && this._planet.quadTreeStrategy._terrainCompletedActivated) {
|
||||
this.events.dispatch(this.events.loadend);
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,11 +123,15 @@ export class KML extends Vector {
|
||||
|
||||
} else {
|
||||
return new Entity({
|
||||
name,
|
||||
polyline: {
|
||||
pathLonLat: [lonLats],
|
||||
thickness: lineWidth,
|
||||
color: lineColor,
|
||||
isClosed: false
|
||||
},
|
||||
properties: {
|
||||
name: name
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -507,7 +507,7 @@ class Layer {
|
||||
}
|
||||
|
||||
public get isIdle(): boolean {
|
||||
return this._planet && this._planet._terrainCompletedActivated || false;
|
||||
return this._planet && this._planet.quadTreeStrategy._terrainCompletedActivated || false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -703,7 +703,8 @@ class Layer {
|
||||
}
|
||||
|
||||
if (!m.isReady) {
|
||||
this._planet!._renderCompleted = false;
|
||||
//this._planet!._renderCompleted = false;
|
||||
segment.quadTreeStrategy._renderCompleted = false;
|
||||
}
|
||||
|
||||
this.applyMaterial(m, true);
|
||||
@ -846,12 +847,12 @@ class Layer {
|
||||
return this._fading ? this._fadingOpacity : this._opacity;
|
||||
}
|
||||
|
||||
public _refreshFadingOpacity() {
|
||||
public _refreshFadingOpacity(minCurrZoom: number, maxCurrZoom: number) {
|
||||
let p = this._planet!;
|
||||
if (
|
||||
this._visibility && p.getViewExtent().overlaps(this._extent) &&
|
||||
p.maxCurrZoom >= this.minZoom &&
|
||||
p.minCurrZoom <= this.maxZoom
|
||||
maxCurrZoom >= this.minZoom &&
|
||||
minCurrZoom <= this.maxZoom
|
||||
) {
|
||||
this._fadingOpacity += this._fadingFactor;
|
||||
|
||||
|
||||
@ -270,7 +270,6 @@ class Vector extends Layer {
|
||||
* Adds layer to the planet.
|
||||
* @public
|
||||
* @param {Planet} planet - Planet scene object.
|
||||
* @returns {Vector} -
|
||||
*/
|
||||
public override addTo(planet: Planet) {
|
||||
if (!this._planet) {
|
||||
@ -314,16 +313,15 @@ class Vector extends Layer {
|
||||
* Adds entity to the layer.
|
||||
* @public
|
||||
* @param {Entity} entity - Entity.
|
||||
* @param {boolean} [rightNow=false] - Entity insertion option. False is default.
|
||||
* @returns {Vector} - Returns this layer.
|
||||
*/
|
||||
public add(entity: Entity, rightNow: boolean = false): this {
|
||||
public add(entity: Entity): this {
|
||||
if (!(entity._layer || entity._entityCollection)) {
|
||||
entity._layer = this;
|
||||
entity._layerIndex = this._entities.length;
|
||||
//this._fitExtent(entity);
|
||||
this._entities.push(entity);
|
||||
this._proceedEntity(entity, rightNow);
|
||||
this._proceedEntity(entity);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -333,10 +331,9 @@ class Vector extends Layer {
|
||||
* @public
|
||||
* @param {Entity} entity - Entity.
|
||||
* @param {Number} index - Index position.
|
||||
* @param {boolean} [rightNow] - Entity insertion option. False is default.
|
||||
* @returns {Vector} - Returns this layer.
|
||||
*/
|
||||
public insert(entity: Entity, index: number, rightNow: boolean = false): this {
|
||||
public insert(entity: Entity, index: number): this {
|
||||
if (!(entity._layer || entity._entityCollection)) {
|
||||
entity._layer = this;
|
||||
entity._layerIndex = index;
|
||||
@ -346,13 +343,13 @@ class Vector extends Layer {
|
||||
this._entities[i]._layerIndex = i;
|
||||
}
|
||||
|
||||
this._proceedEntity(entity, rightNow);
|
||||
this._proceedEntity(entity);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected _proceedEntity(entity: Entity, rightNow: boolean = false) {
|
||||
protected _proceedEntity(entity: Entity) {
|
||||
let temp = this._hasImageryTiles;
|
||||
|
||||
if (entity.strip) {
|
||||
@ -409,13 +406,12 @@ class Vector extends Layer {
|
||||
* Adds entity array to the layer.
|
||||
* @public
|
||||
* @param {Array.<Entity>} entities - Entities array.
|
||||
* @param {boolean} [rightNow=false] - Entity insertion option. False is default.
|
||||
* @returns {Vector} - Returns this layer.
|
||||
*/
|
||||
public addEntities(entities: Entity[], rightNow: boolean = false) {
|
||||
public addEntities(entities: Entity[]): Vector {
|
||||
let i = entities.length;
|
||||
while (i--) {
|
||||
this.add(entities[i], rightNow);
|
||||
this.add(entities[i]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -625,7 +621,7 @@ class Vector extends Layer {
|
||||
|
||||
protected _createEntityCollectionsTree(entitiesForTree: Entity[]) {
|
||||
if (this._planet) {
|
||||
this._entityCollectionsTreeStrategy = this._planet.quadTreeStrategy.createEntitiCollectionsTreeStrategy(this, this._nodeCapacity);
|
||||
this._entityCollectionsTreeStrategy = this._planet.quadTreeStrategy.createEntityCollectionsTreeStrategy(this, this._nodeCapacity);
|
||||
this._entityCollectionsTreeStrategy.insertEntities(entitiesForTree);
|
||||
}
|
||||
}
|
||||
@ -745,7 +741,7 @@ class Vector extends Layer {
|
||||
if (this.clampToGround || this.relativeToGround) {
|
||||
let rtg = Number(this.relativeToGround);
|
||||
|
||||
const nodes = this._planet!._renderedNodes;
|
||||
const nodes = this._planet!.quadTreeStrategy._renderedNodes;
|
||||
const visibleExtent = this._planet!.getViewExtent();
|
||||
let e = ec._entities;
|
||||
let e_i = e.length;
|
||||
@ -769,9 +765,7 @@ class Vector extends Layer {
|
||||
if (seg._extent.isInside(ll)) {
|
||||
let cart = p._path3v[c_j][c_j_h] as Vec3;
|
||||
seg.getTerrainPoint(cart, ll, res);
|
||||
let alt = (rtg && p.altitude) || 0.0;
|
||||
alt += p._pathLonLatMerc[c_j][c_j_h].height || 0.0;
|
||||
alt += altModifier;
|
||||
let alt = (rtg && p.altitude) || altModifier;
|
||||
if (alt) {
|
||||
let n = this._planet!.ellipsoid.getSurfaceNormal3v(res);
|
||||
p.setPoint3v(res.addA(n.scale(alt)), c_j_h, c_j, true);
|
||||
@ -845,7 +839,7 @@ class Vector extends Layer {
|
||||
|
||||
if (
|
||||
(this._fading && this._fadingOpacity > 0.0) ||
|
||||
(this.minZoom <= p.maxCurrZoom && this.maxZoom >= p.maxCurrZoom)
|
||||
(this.minZoom <= p.quadTreeStrategy.maxCurrZoom && this.maxZoom >= p.quadTreeStrategy.maxCurrZoom)
|
||||
) {
|
||||
// Common collections first
|
||||
this._collectStripCollectionPASS(outArr);
|
||||
@ -891,7 +885,7 @@ class Vector extends Layer {
|
||||
material.isReady = false;
|
||||
}
|
||||
|
||||
public override applyMaterial(material: Material, isForced: boolean = false): NumberArray4 {
|
||||
public override applyMaterial(material: Material): NumberArray4 {
|
||||
if (material.isReady) {
|
||||
return [0, 0, 1, 1];
|
||||
} else {
|
||||
|
||||
@ -657,7 +657,7 @@ export class Mat4 {
|
||||
* @param {number} far -
|
||||
* @return {Mat4} -
|
||||
*/
|
||||
public setOrtho(left: number, right: number, bottom: number, top: number, near: number, far: number): Mat4 {
|
||||
public setOrthographic(left: number, right: number, bottom: number, top: number, near: number, far: number): Mat4 {
|
||||
|
||||
let lr = 1.0 / (left - right),
|
||||
bt = 1.0 / (bottom - top),
|
||||
|
||||
@ -320,6 +320,16 @@ export class Vec3 {
|
||||
return tangent.subA(normal).normalize();
|
||||
}
|
||||
|
||||
static isOrthogonal(a: Vec3, b: Vec3, epsilon = 1e-6): boolean {
|
||||
const dot = a.x * b.x + a.y * b.y + a.z * b.z;
|
||||
return Math.abs(dot) < epsilon;
|
||||
}
|
||||
|
||||
public isOrthogonal(b: Vec3, epsilon = 1e-6): boolean {
|
||||
const dot = this.x * b.x + this.y * b.y + this.z * b.z;
|
||||
return Math.abs(dot) < epsilon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns vector components division product one to another.
|
||||
* @static
|
||||
|
||||
@ -1,21 +1,22 @@
|
||||
import * as quadTree from "../quadTree";
|
||||
import {Extent} from "../../Extent";
|
||||
import {EPSG4326} from "../../proj/EPSG4326";
|
||||
import {Node} from "../Node";
|
||||
import {Planet} from "../../scene/Planet";
|
||||
import {QuadTreeStrategy} from "../QuadTreeStrategy";
|
||||
import {QuadTreeStrategy, QuadTreeStrategyParams} from "../QuadTreeStrategy";
|
||||
import {SegmentLonLatEqui} from "../../segment/SegmentLonLatEqui";
|
||||
import {PlanetCamera} from "../../camera";
|
||||
|
||||
export class EPSG4326QuadTreeStrategy extends QuadTreeStrategy {
|
||||
constructor(planet: Planet) {
|
||||
super(planet, "EPSG4326", EPSG4326);
|
||||
constructor(params: QuadTreeStrategyParams) {
|
||||
super({name: "EPSG4326", proj: EPSG4326, ...params});
|
||||
}
|
||||
|
||||
public override init() {
|
||||
public override init(camera: PlanetCamera) {
|
||||
|
||||
this._quadTreeList = [
|
||||
new Node(
|
||||
SegmentLonLatEqui,
|
||||
this.planet,
|
||||
this,
|
||||
0,
|
||||
null,
|
||||
0,
|
||||
@ -23,12 +24,14 @@ export class EPSG4326QuadTreeStrategy extends QuadTreeStrategy {
|
||||
),
|
||||
new Node(
|
||||
SegmentLonLatEqui,
|
||||
this.planet,
|
||||
this,
|
||||
0,
|
||||
null,
|
||||
0,
|
||||
Extent.createFromArray([0, -90, 180, 90])
|
||||
)
|
||||
];
|
||||
|
||||
super.init(camera);
|
||||
}
|
||||
}
|
||||
@ -36,7 +36,14 @@ class EntityCollectionNode {
|
||||
|
||||
public _inTheQueue: boolean;
|
||||
|
||||
constructor(strategy: EntityCollectionsTreeStrategy, partId: number, parent: EntityCollectionNode | null, extent: Extent, planet: Planet, zoom: number) {
|
||||
constructor(
|
||||
strategy: EntityCollectionsTreeStrategy,
|
||||
partId: number,
|
||||
parent: EntityCollectionNode | null,
|
||||
extent: Extent,
|
||||
planet: Planet,
|
||||
zoom: number
|
||||
) {
|
||||
this.strategy = strategy;
|
||||
this.layer = strategy._layer;
|
||||
this.parentNode = parent;
|
||||
@ -281,7 +288,7 @@ class EntityCollectionNode {
|
||||
this.alignEntityToTheGround(ei, visibleNodes[renderingNodeId].segment);
|
||||
}
|
||||
} else {
|
||||
const n = l._planet!._renderedNodes;
|
||||
const n = this.strategy.quadTreeStrategy._renderedNodes;
|
||||
while (i--) {
|
||||
let ei = e[i];
|
||||
let j = n.length;
|
||||
|
||||
@ -3,6 +3,7 @@ import {EntityCollectionNode} from "./EntityCollectionNode";
|
||||
import {Entity} from "../entity/Entity";
|
||||
import {EntityCollection} from "../entity/EntityCollection";
|
||||
import {QueueArray} from "../QueueArray";
|
||||
import {QuadTreeStrategy} from "./QuadTreeStrategy";
|
||||
|
||||
export class EntityCollectionsTreeStrategy {
|
||||
|
||||
@ -21,7 +22,10 @@ export class EntityCollectionsTreeStrategy {
|
||||
|
||||
public _renderingNodes: Record<number, boolean>;
|
||||
|
||||
constructor(layer: Vector, nodeCapacity: number) {
|
||||
public quadTreeStrategy: QuadTreeStrategy;
|
||||
|
||||
constructor(quadTreeStrategy: QuadTreeStrategy, layer: Vector, nodeCapacity: number) {
|
||||
this.quadTreeStrategy = quadTreeStrategy;
|
||||
this._layer = layer;
|
||||
this._nodeCapacity = nodeCapacity;
|
||||
this._secondPASS = [];
|
||||
|
||||
@ -3,8 +3,8 @@ import {EPSG3857} from "../proj/EPSG3857";
|
||||
import {binaryInsert, getMatrixSubArray32, getMatrixSubArray64, getMatrixSubArrayBoundsExt} from "../utils/shared";
|
||||
import {LonLat} from "../LonLat";
|
||||
import {MAX, MIN} from "../math";
|
||||
import {Planet} from "../scene/Planet";
|
||||
import {Segment} from "../segment/Segment";
|
||||
import {QuadTreeStrategy} from "./QuadTreeStrategy";
|
||||
|
||||
import {Vec2} from "../math/Vec2";
|
||||
import {Vec3} from "../math/Vec3";
|
||||
@ -61,17 +61,17 @@ let __staticCounter = 0;
|
||||
* Quad tree planet segment node.
|
||||
* @constructor
|
||||
* @param {Segment} segmentPrototype - Planet segment node constructor.
|
||||
* @param {Planet} planet - Planet scene instance.
|
||||
* @param {QuadTreeStrategy} quadTreeStrategy - Quad tree strategy handler.
|
||||
* @param {number} partId - NorthEast, SouthWest etc.
|
||||
* @param {Node} parent - Parent of this node.
|
||||
* @param {number} id - Tree node identifier (id * 4 + 1);
|
||||
* @param {number} tileZoom - Deep index of the quad tree.
|
||||
* @param {Extent} extent - Planet segment extent.
|
||||
* @param {Extent} extent - Segment extent.
|
||||
*/
|
||||
class Node {
|
||||
public __id: number;
|
||||
public SegmentPrototype: typeof Segment;
|
||||
public planet: Planet;
|
||||
public quadTreeStrategy: QuadTreeStrategy;
|
||||
public parentNode: Node | null;
|
||||
public partId: number;
|
||||
public nodeId: number;
|
||||
@ -90,18 +90,18 @@ class Node {
|
||||
|
||||
constructor(
|
||||
SegmentPrototype: typeof Segment,
|
||||
planet: Planet,
|
||||
quadTreeStrategy: QuadTreeStrategy,
|
||||
partId: number,
|
||||
parent: Node | null,
|
||||
tileZoom: number,
|
||||
extent: Extent
|
||||
) {
|
||||
planet._createdNodesCount++;
|
||||
quadTreeStrategy.planet._createdNodesCount++;
|
||||
|
||||
this.__id = __staticCounter++;
|
||||
|
||||
this.SegmentPrototype = SegmentPrototype;
|
||||
this.planet = planet;
|
||||
this.quadTreeStrategy = quadTreeStrategy;
|
||||
this.parentNode = parent;
|
||||
this.partId = partId;
|
||||
this.nodeId = partId + (parent ? parent.nodeId * 4 + 1 : 0);
|
||||
@ -112,9 +112,8 @@ class Node {
|
||||
this.ready = false;
|
||||
this.neighbors = [[], [], [], []];
|
||||
this.equalizedSideWithNodeId = [this.nodeId, this.nodeId, this.nodeId, this.nodeId];
|
||||
// @todo: this.nodes = null;
|
||||
this.nodes = [];
|
||||
this.segment = new SegmentPrototype(this, planet, tileZoom, extent);
|
||||
this.segment = new SegmentPrototype(this, quadTreeStrategy, tileZoom, extent);
|
||||
this._cameraInside = false;
|
||||
this.inFrustum = 0;
|
||||
this._fadingNodes = [];
|
||||
@ -123,7 +122,7 @@ class Node {
|
||||
|
||||
public createChildNodes() {
|
||||
this.ready = true;
|
||||
const p = this.planet;
|
||||
const qts = this.quadTreeStrategy;
|
||||
const ps = this.segment;
|
||||
const ext = ps._extent;
|
||||
const z = ps.tileZoom + 1;
|
||||
@ -134,10 +133,10 @@ class Node {
|
||||
const c = new LonLat(sw.lon + size_x, sw.lat + size_y);
|
||||
const nd = this.nodes;
|
||||
|
||||
nd[NW] = new Node(this.SegmentPrototype, p, NW, this, z, new Extent(new LonLat(sw.lon, sw.lat + size_y), new LonLat(sw.lon + size_x, ne.lat)));
|
||||
nd[NE] = new Node(this.SegmentPrototype, p, NE, this, z, new Extent(c, new LonLat(ne.lon, ne.lat)));
|
||||
nd[SW] = new Node(this.SegmentPrototype, p, SW, this, z, new Extent(new LonLat(sw.lon, sw.lat), c));
|
||||
nd[SE] = new Node(this.SegmentPrototype, p, SE, this, z, new Extent(new LonLat(sw.lon + size_x, sw.lat), new LonLat(ne.lon, sw.lat + size_y)));
|
||||
nd[NW] = new Node(this.SegmentPrototype, qts, NW, this, z, new Extent(new LonLat(sw.lon, sw.lat + size_y), new LonLat(sw.lon + size_x, ne.lat)));
|
||||
nd[NE] = new Node(this.SegmentPrototype, qts, NE, this, z, new Extent(c, new LonLat(ne.lon, ne.lat)));
|
||||
nd[SW] = new Node(this.SegmentPrototype, qts, SW, this, z, new Extent(new LonLat(sw.lon, sw.lat), c));
|
||||
nd[SE] = new Node(this.SegmentPrototype, qts, SE, this, z, new Extent(new LonLat(sw.lon + size_x, sw.lat), new LonLat(ne.lon, sw.lat + size_y)));
|
||||
}
|
||||
|
||||
public createBounds() {
|
||||
@ -209,10 +208,6 @@ class Node {
|
||||
}
|
||||
}
|
||||
|
||||
// public isBrother(node: Node): boolean {
|
||||
// return !(this.parentNode || node.parentNode) || (this.parentNode!.nodeId === node.parentNode!.nodeId);
|
||||
// }
|
||||
|
||||
public traverseNodes(cam: PlanetCamera, maxZoom?: number | null, terrainReadySegment?: Segment | null, stopLoading?: boolean, zoomPassNode?: Node) {
|
||||
if (!this.ready) {
|
||||
this.createChildNodes();
|
||||
@ -227,7 +222,7 @@ class Node {
|
||||
}
|
||||
|
||||
public renderTree(cam: PlanetCamera, maxZoom?: number | null, terrainReadySegment?: Segment | null, stopLoading?: boolean, zoomPassNode?: Node) {
|
||||
if (this.planet._renderedNodes.length >= MAX_RENDERED_NODES) {
|
||||
if (this.quadTreeStrategy._renderedNodes.length >= MAX_RENDERED_NODES) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -239,7 +234,7 @@ class Node {
|
||||
this.clearNeighbors();
|
||||
|
||||
let seg = this.segment,
|
||||
planet = this.planet;
|
||||
planet = this.quadTreeStrategy.planet;
|
||||
|
||||
this._cameraInside = false;
|
||||
|
||||
@ -300,13 +295,13 @@ class Node {
|
||||
cam.eye.distance2(seg._se) < horizonDist;
|
||||
|
||||
if ((this.inFrustum && (altVis || h > 10000.0)) || this._cameraInside) {
|
||||
planet.quadTreeStrategy.collectVisibleNode(this);
|
||||
this.quadTreeStrategy.collectVisibleNode(this);
|
||||
}
|
||||
|
||||
if (seg.tileZoom < 2) {
|
||||
this.traverseNodes(cam, maxZoom, terrainReadySegment, stopLoading, zoomPassNode);
|
||||
} else if (
|
||||
seg.terrainReady && (!maxZoom && cam.projectedSize(seg.bsphere.center, seg._plainRadius) < planet.lodSize
|
||||
seg.terrainReady && (!maxZoom && cam.projectedSize(seg.bsphere.center, seg._plainRadius) < this.quadTreeStrategy.lodSize
|
||||
|| maxZoom && ((seg.tileZoom === maxZoom) || !altVis))
|
||||
) {
|
||||
|
||||
@ -317,7 +312,7 @@ class Node {
|
||||
this.state = NOTRENDERING;
|
||||
}
|
||||
|
||||
} else if (seg.terrainReady && seg.checkZoom() && (!maxZoom || cam.projectedSize(seg.bsphere.center, seg.bsphere.radius) > this.planet._maxLodSize)) {
|
||||
} else if (seg.terrainReady && seg.checkZoom() && (!maxZoom || cam.projectedSize(seg.bsphere.center, seg.bsphere.radius) > this.quadTreeStrategy._maxLodSize)) {
|
||||
this.traverseNodes(cam, maxZoom, seg, stopLoading, zoomPassNode);
|
||||
} else if (altVis) {
|
||||
seg.passReady = maxZoom ? seg.terrainReady : false;
|
||||
@ -361,12 +356,12 @@ class Node {
|
||||
}
|
||||
|
||||
// Calculate minimal and maximal zoom index on the screen
|
||||
if (!this._cameraInside && seg.tileZoom > this.planet.maxCurrZoom) {
|
||||
this.planet.maxCurrZoom = seg.tileZoom;
|
||||
if (!this._cameraInside && seg.tileZoom > this.quadTreeStrategy.maxCurrZoom) {
|
||||
this.quadTreeStrategy.maxCurrZoom = seg.tileZoom;
|
||||
}
|
||||
|
||||
if (seg.tileZoom < this.planet.minCurrZoom) {
|
||||
this.planet.minCurrZoom = seg.tileZoom;
|
||||
if (seg.tileZoom < this.quadTreeStrategy.minCurrZoom) {
|
||||
this.quadTreeStrategy.minCurrZoom = seg.tileZoom;
|
||||
}
|
||||
|
||||
seg._addViewExtent();
|
||||
@ -421,7 +416,7 @@ class Node {
|
||||
pn = pn.parentNode;
|
||||
}
|
||||
|
||||
// not sure it's necessary here
|
||||
// not sure that it's necessary here
|
||||
this.parentNode.whileTerrainLoading();
|
||||
|
||||
this._fadingNodes.push(this.parentNode);
|
||||
@ -433,7 +428,7 @@ class Node {
|
||||
for (let i = 0; i < this.nodes.length; i++) {
|
||||
let ni = this.nodes[i];
|
||||
|
||||
// not sure it's necessary here
|
||||
// not sure that it's necessary here
|
||||
ni.whileTerrainLoading();
|
||||
|
||||
this._fadingNodes.push(ni);
|
||||
@ -488,10 +483,10 @@ class Node {
|
||||
public addToRender(inFrustum: number) {
|
||||
this.state = RENDERING;
|
||||
|
||||
let nodes = this.planet._renderedNodes;
|
||||
let nodes = this.quadTreeStrategy._renderedNodes;
|
||||
|
||||
//@ts-ignore
|
||||
if (!this.planet._transitionOpacityEnabled) {
|
||||
if (!this.quadTreeStrategy._transitionOpacityEnabled) {
|
||||
this.getRenderedNodesNeighbors(nodes);
|
||||
nodes.push(this);
|
||||
} else {
|
||||
@ -502,12 +497,12 @@ class Node {
|
||||
}
|
||||
|
||||
if (!this.segment.terrainReady) {
|
||||
this.planet._renderCompleted = false;
|
||||
this.planet._terrainCompleted = false;
|
||||
this.quadTreeStrategy._renderCompleted = false;
|
||||
this.quadTreeStrategy._terrainCompleted = false;
|
||||
}
|
||||
|
||||
let k = 0,
|
||||
rf = this.planet._renderedNodesInFrustum;
|
||||
rf = this.quadTreeStrategy._renderedNodesInFrustum;
|
||||
while (inFrustum) {
|
||||
if (inFrustum & 1) {
|
||||
rf[k].push(this);
|
||||
|
||||
@ -5,14 +5,41 @@ import {Node} from "../quadTree/Node";
|
||||
import {Planet} from "../scene/Planet";
|
||||
import {Proj} from "../proj/Proj";
|
||||
import {LonLat} from "../LonLat";
|
||||
import {getTileCellExtent, getTileCellIndex, TILEGROUP_COMMON} from "../segment/Segment";
|
||||
import {getTileCellExtent, getTileCellIndex, Segment, TILEGROUP_COMMON} from "../segment/Segment";
|
||||
import {Extent} from "../Extent";
|
||||
import {EntityCollectionsTreeStrategy} from "./EntityCollectionsTreeStrategy";
|
||||
import {PlanetCamera} from "../camera";
|
||||
import * as math from "../math";
|
||||
import {createEvents, EventsHandler} from "../Events";
|
||||
|
||||
export type QuadTreeStrategyEventsList = [
|
||||
"rendercompleted",
|
||||
"terraincompleted",
|
||||
];
|
||||
|
||||
const CUR_LOD_SIZE = 256; //px
|
||||
const MIN_LOD_SIZE = 512; //px
|
||||
const MAX_LOD_SIZE = 256; //px
|
||||
|
||||
const HORIZON_TANGENT = 0.81;
|
||||
|
||||
export interface QuadTreeStrategyParams {
|
||||
planet: Planet;
|
||||
name?: string;
|
||||
proj?: Proj;
|
||||
maxEqualZoomAltitude?: number;
|
||||
minEqualZoomAltitude?: number;
|
||||
minEqualZoomCameraSlope?: number;
|
||||
transitionOpacityEnabled?: boolean;
|
||||
}
|
||||
|
||||
export class QuadTreeStrategy {
|
||||
|
||||
public events: EventsHandler<QuadTreeStrategyEventsList>;
|
||||
|
||||
public name: string;
|
||||
public projection: Proj;
|
||||
protected _planet: Planet;
|
||||
public readonly planet: Planet;
|
||||
|
||||
/**
|
||||
* grid tree list.
|
||||
@ -28,19 +55,121 @@ export class QuadTreeStrategy {
|
||||
*/
|
||||
public _visibleNodes: Record<number, Node>;
|
||||
|
||||
constructor(planet: Planet, name: string = "", proj: Proj = EPSG3857) {
|
||||
this.name = name;
|
||||
this.projection = proj;
|
||||
this._planet = planet;
|
||||
/**
|
||||
* Planet's segments collected for rendering frame.
|
||||
* @public
|
||||
* @type {Node}
|
||||
*/
|
||||
public _renderedNodes: Node[];
|
||||
|
||||
public _renderedNodesInFrustum: Node[][];
|
||||
|
||||
public _fadingNodes: Map<number, Node>;
|
||||
|
||||
public _fadingNodesInFrustum: Node[][];
|
||||
|
||||
public _fadingOpaqueSegments: Segment[];
|
||||
|
||||
/**
|
||||
* Current visible minimal zoom index planet segment.
|
||||
* @public
|
||||
* @type {number}
|
||||
*/
|
||||
public minCurrZoom: number;
|
||||
|
||||
/**
|
||||
* Current visible maximal zoom index planet segment.
|
||||
* @public
|
||||
* @type {number}
|
||||
*/
|
||||
public maxCurrZoom: number;
|
||||
|
||||
protected _transitionOpacityEnabled: boolean;
|
||||
|
||||
public _viewExtent: Extent;
|
||||
|
||||
/**
|
||||
* Level of details of visible segments.
|
||||
* @protected
|
||||
* @type {number}
|
||||
*/
|
||||
protected _lodSize: number;
|
||||
protected _curLodSize: number;
|
||||
protected _minLodSize: number;
|
||||
public _maxLodSize: number;
|
||||
|
||||
public maxEqualZoomAltitude: number;
|
||||
public minEqualZoomAltitude: number;
|
||||
public minEqualZoomCameraSlope: number;
|
||||
|
||||
public _renderCompleted: boolean
|
||||
public _renderCompletedActivated: boolean;
|
||||
|
||||
public _terrainCompleted: boolean;
|
||||
public _terrainCompletedActivated: boolean;
|
||||
|
||||
protected _skipPreRender: boolean = false;
|
||||
|
||||
constructor(params: QuadTreeStrategyParams) {
|
||||
|
||||
this.events = createEvents<QuadTreeStrategyEventsList>(QUADTREESTRATEGY_EVENTS);
|
||||
|
||||
this.name = params.name || "";
|
||||
this.projection = params.proj || EPSG3857;
|
||||
this.planet = params.planet;
|
||||
this._quadTreeList = [];
|
||||
this._visibleNodes = {};
|
||||
|
||||
this._renderedNodes = [];
|
||||
this._renderedNodesInFrustum = [];
|
||||
|
||||
this._fadingNodes = new Map<number, Node>;
|
||||
this._fadingNodesInFrustum = [];
|
||||
this._fadingOpaqueSegments = [];
|
||||
|
||||
this.minCurrZoom = math.MAX;
|
||||
|
||||
this.maxCurrZoom = math.MIN;
|
||||
|
||||
this._viewExtent = new Extent(new LonLat(180, 180), new LonLat(-180, -180));
|
||||
|
||||
this._lodSize = CUR_LOD_SIZE;
|
||||
this._curLodSize = CUR_LOD_SIZE;
|
||||
this._minLodSize = MIN_LOD_SIZE;
|
||||
this._maxLodSize = MAX_LOD_SIZE;
|
||||
|
||||
this.maxEqualZoomAltitude = params.maxEqualZoomAltitude || 15000000.0;
|
||||
this.minEqualZoomAltitude = params.minEqualZoomAltitude || 10000.0;
|
||||
this.minEqualZoomCameraSlope = params.minEqualZoomCameraSlope || 0.8;
|
||||
|
||||
this._renderCompleted = false;
|
||||
this._renderCompletedActivated = false;
|
||||
|
||||
this._terrainCompleted = false;
|
||||
this._terrainCompletedActivated = false;
|
||||
|
||||
this._transitionOpacityEnabled = params.transitionOpacityEnabled != undefined ? params.transitionOpacityEnabled : true;
|
||||
}
|
||||
|
||||
public createEntitiCollectionsTreeStrategy(layer: Vector, nodeCapacity: number): EntityCollectionsTreeStrategy {
|
||||
return new EntityCollectionsTreeStrategy(layer, nodeCapacity);
|
||||
public get lodSize(): number {
|
||||
return this._lodSize;
|
||||
}
|
||||
|
||||
public setLodSize(currentLodSize: number, minLodSize?: number, maxLodSize?: number) {
|
||||
this._maxLodSize = maxLodSize || this._maxLodSize;
|
||||
this._minLodSize = minLodSize || this._minLodSize;
|
||||
this._curLodSize = currentLodSize;
|
||||
this._renderCompletedActivated = false;
|
||||
this._terrainCompletedActivated = false;
|
||||
}
|
||||
|
||||
public createEntityCollectionsTreeStrategy(layer: Vector, nodeCapacity: number): EntityCollectionsTreeStrategy {
|
||||
return new EntityCollectionsTreeStrategy(this, layer, nodeCapacity);
|
||||
}
|
||||
|
||||
public destroyBranches() {
|
||||
this._renderCompletedActivated = false;
|
||||
this._terrainCompletedActivated = false;
|
||||
for (let i = 0, len = this._quadTreeList.length; i < len; i++) {
|
||||
this._quadTreeList[i].destroyBranches();
|
||||
}
|
||||
@ -61,15 +190,181 @@ export class QuadTreeStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
public get planet() {
|
||||
return this._planet;
|
||||
public get terrainReady(): boolean {
|
||||
return this._terrainCompleted && this._terrainCompletedActivated;
|
||||
}
|
||||
|
||||
public init() {
|
||||
protected _checkRendercompleted() {
|
||||
if (this._renderCompleted) {
|
||||
if (!this._renderCompletedActivated) {
|
||||
this._renderCompletedActivated = true;
|
||||
this.events.dispatch(this.events.rendercompleted, true);
|
||||
}
|
||||
} else {
|
||||
this._renderCompletedActivated = false;
|
||||
}
|
||||
this._renderCompleted = true;
|
||||
|
||||
if (this._terrainCompleted) {
|
||||
if (!this._terrainCompletedActivated) {
|
||||
this._terrainCompletedActivated = true;
|
||||
this.events.dispatch(this.events.terraincompleted, true);
|
||||
}
|
||||
} else {
|
||||
this._terrainCompletedActivated = false;
|
||||
}
|
||||
|
||||
this._terrainCompleted = true;
|
||||
}
|
||||
|
||||
protected _initEvents() {
|
||||
this.planet.renderer!.events.on("resize", () => {
|
||||
this._renderCompletedActivated = false;
|
||||
this._terrainCompletedActivated = false;
|
||||
});
|
||||
|
||||
this.planet.renderer!.events.on("postdraw", () => {
|
||||
this._checkRendercompleted();
|
||||
});
|
||||
}
|
||||
|
||||
public init(camera: PlanetCamera) {
|
||||
this._initEvents();
|
||||
this._renderedNodesInFrustum = new Array(camera.frustums.length);
|
||||
for (let i = 0, len = this._renderedNodesInFrustum.length; i < len; i++) {
|
||||
this._renderedNodesInFrustum[i] = [];
|
||||
}
|
||||
|
||||
this.preRender();
|
||||
this.clearRenderedNodes();
|
||||
this.preLoad();
|
||||
}
|
||||
|
||||
public clearRenderedNodes() {
|
||||
this._clearRenderedNodeList();
|
||||
this._clearRenderNodesInFrustum();
|
||||
}
|
||||
|
||||
protected _clearRenderedNodeList() {
|
||||
this._renderedNodes.length = 0;
|
||||
this._renderedNodes = [];
|
||||
}
|
||||
|
||||
protected _clearRenderNodesInFrustum() {
|
||||
for (let i = 0, len = this._renderedNodesInFrustum.length; i < len; i++) {
|
||||
this._renderedNodesInFrustum[i].length = 0;
|
||||
this._renderedNodesInFrustum[i] = [];
|
||||
}
|
||||
}
|
||||
|
||||
protected _collectRenderedNodesMaxZoom(cam: PlanetCamera) {
|
||||
if (cam.slope > this.minEqualZoomCameraSlope && cam._lonLat.height < this.maxEqualZoomAltitude && cam._lonLat.height > this.minEqualZoomAltitude) {
|
||||
|
||||
this.minCurrZoom = this.maxCurrZoom;
|
||||
|
||||
let temp = this._renderedNodes,
|
||||
rf = this._renderedNodesInFrustum,
|
||||
temp2 = [];
|
||||
|
||||
this._clearRenderNodesInFrustum();
|
||||
this._renderedNodes = [];
|
||||
|
||||
for (let i = 0, len = temp.length; i < len; i++) {
|
||||
let ri = temp[i];
|
||||
let ht = ri.segment.centerNormal.dot(cam.getBackward());
|
||||
if (ri.segment.tileZoom === this.maxCurrZoom || ht < HORIZON_TANGENT) {
|
||||
this._renderedNodes.push(ri);
|
||||
let k = 0, inFrustum = ri.inFrustum;
|
||||
while (inFrustum) {
|
||||
if (inFrustum & 1) {
|
||||
rf[k].push(ri);
|
||||
}
|
||||
k++;
|
||||
inFrustum >>= 1;
|
||||
}
|
||||
} else {
|
||||
temp2.push(ri);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0, len = temp2.length; i < len; i++) {
|
||||
temp2[i].renderTree(cam, this.maxCurrZoom, null, false, temp2[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public set transitionOpacityEnabled(isEnabled: boolean) {
|
||||
this._transitionOpacityEnabled = isEnabled;
|
||||
//@todo: set render nodes transition opacity to one
|
||||
}
|
||||
|
||||
public get transitionOpacityEnabled(): boolean {
|
||||
return this._transitionOpacityEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects visible quad nodes.
|
||||
* @protected
|
||||
*/
|
||||
public collectRenderNodes(cam: PlanetCamera) {
|
||||
|
||||
if (this._skipPreRender) {
|
||||
|
||||
this._lodSize = math.lerp(cam.slope < 0.0 ? 0.0 : cam.slope, this._curLodSize, this._minLodSize);
|
||||
cam._insideSegment = null;
|
||||
|
||||
// clear first
|
||||
this._clearRenderedNodeList();
|
||||
this._clearRenderNodesInFrustum();
|
||||
|
||||
this._viewExtent.southWest.set(180, 180);
|
||||
this._viewExtent.northEast.set(-180, -180);
|
||||
|
||||
// todo: replace to camera
|
||||
this.minCurrZoom = math.MAX;
|
||||
this.maxCurrZoom = math.MIN;
|
||||
|
||||
this._collectRenderNodes(cam);
|
||||
|
||||
this._collectRenderedNodesMaxZoom(cam);
|
||||
|
||||
// main camera effect
|
||||
this._fadingNodes.clear();
|
||||
|
||||
if (this._transitionOpacityEnabled) {
|
||||
|
||||
let opaqueNodes: Node[] = [];
|
||||
|
||||
for (let i = 0; i < this._renderedNodes.length; i++) {
|
||||
let ri = this._renderedNodes[i];
|
||||
// it's not impossible to move the code into Node.addToRender, because
|
||||
// we can't know actual state before _collectRenderedNodesMaxZoom pass
|
||||
ri._collectFadingNodes();
|
||||
ri._refreshTransitionOpacity();
|
||||
|
||||
if (ri.segment._transitionOpacity >= 1.0) {
|
||||
ri.clearNeighbors();
|
||||
ri.getRenderedNodesNeighbors(opaqueNodes);
|
||||
opaqueNodes.push(ri);
|
||||
} else {
|
||||
for (let j = 0; j < ri._fadingNodes.length; j++) {
|
||||
let rij = ri._fadingNodes[j];
|
||||
if (rij.segment && rij.segment._transitionOpacity >= 1.0) {
|
||||
rij.clearNeighbors();
|
||||
rij.getRenderedNodesNeighbors(opaqueNodes);
|
||||
opaqueNodes.push(rij);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._skipPreRender = true;
|
||||
}
|
||||
|
||||
public preRender() {
|
||||
this._skipPreRender = false;
|
||||
for (let i = 0; i < this._quadTreeList.length; i++) {
|
||||
|
||||
let quadTree = this._quadTreeList[i];
|
||||
@ -89,12 +384,12 @@ export class QuadTreeStrategy {
|
||||
let quadTree = this._quadTreeList[i];
|
||||
quadTree.segment.passReady = true;
|
||||
quadTree.renderNode(1);
|
||||
this._planet.normalMapCreator.drawSingle(quadTree.segment);
|
||||
this.planet.normalMapCreator.drawSingle(quadTree.segment);
|
||||
|
||||
for (let j = 0; j < quadTree.nodes.length; j++) {
|
||||
quadTree.nodes[j].segment.passReady = true;
|
||||
quadTree.nodes[j].renderNode(1);
|
||||
this._planet._normalMapCreator.drawSingle(quadTree.nodes[j].segment);
|
||||
this.planet._normalMapCreator.drawSingle(quadTree.nodes[j].segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -103,10 +398,10 @@ export class QuadTreeStrategy {
|
||||
this._visibleNodes = {};
|
||||
}
|
||||
|
||||
public collectRenderNodes() {
|
||||
protected _collectRenderNodes(camera: PlanetCamera) {
|
||||
this._clearVisibleNodes();
|
||||
for (let i = 0; i < this._quadTreeList.length; i++) {
|
||||
this._quadTreeList[i].renderTree(this._planet.camera, 0, null);
|
||||
this._quadTreeList[i].renderTree(camera, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,8 +417,8 @@ export class QuadTreeStrategy {
|
||||
|
||||
public getTileXY(lonLat: LonLat, zoom: number): [number, number, number, number] {
|
||||
let z = zoom,
|
||||
x = -1,
|
||||
y = -1,
|
||||
x: number,
|
||||
y: number,
|
||||
pz = (1 << z);
|
||||
|
||||
x = getTileCellIndex(lonLat.lon, 360 / pz, -180);
|
||||
@ -133,8 +428,7 @@ export class QuadTreeStrategy {
|
||||
}
|
||||
|
||||
public getLonLatTileOffset(lonLat: LonLat, x: number, y: number, z: number, gridSize: number): [number, number] {
|
||||
let coords = lonLat;
|
||||
let extent = new Extent();
|
||||
let extent: Extent;
|
||||
|
||||
let worldExtent = Extent.createFromArray([-180, -90, 180, 90]);
|
||||
extent = getTileCellExtent(x, y, z, worldExtent);
|
||||
@ -142,8 +436,8 @@ export class QuadTreeStrategy {
|
||||
let sizeImgW = extent.getWidth() / (gridSize - 1),
|
||||
sizeImgH = extent.getHeight() / (gridSize - 1);
|
||||
|
||||
let i = gridSize - Math.ceil((coords.lat - extent.southWest.lat) / sizeImgH) - 1,
|
||||
j = Math.floor((coords.lon - extent.southWest.lon) / sizeImgW);
|
||||
let i = gridSize - Math.ceil((lonLat.lat - extent.southWest.lat) / sizeImgH) - 1,
|
||||
j = Math.floor((lonLat.lon - extent.southWest.lon) / sizeImgW);
|
||||
|
||||
return [i, j];
|
||||
}
|
||||
@ -151,4 +445,9 @@ export class QuadTreeStrategy {
|
||||
public collectVisibleNode(node: Node) {
|
||||
this._visibleNodes[node.nodeId] = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const QUADTREESTRATEGY_EVENTS: QuadTreeStrategyEventsList = [
|
||||
"rendercompleted",
|
||||
"terraincompleted"
|
||||
]
|
||||
@ -8,6 +8,7 @@ import {Entity} from "../../entity/Entity";
|
||||
import {EntityCollection} from "../../entity/EntityCollection";
|
||||
import {EarthQuadTreeStrategy} from "./EarthQuadTreeStrategy";
|
||||
import {EntityCollectionsTreeStrategy} from "../EntityCollectionsTreeStrategy";
|
||||
import {QuadTreeStrategy} from "../QuadTreeStrategy";
|
||||
|
||||
export class EarthEntityCollectionsTreeStrategy extends EntityCollectionsTreeStrategy {
|
||||
|
||||
@ -18,8 +19,8 @@ export class EarthEntityCollectionsTreeStrategy extends EntityCollectionsTreeStr
|
||||
public _renderingNodesNorth: Record<number, boolean>;
|
||||
public _renderingNodesSouth: Record<number, boolean>;
|
||||
|
||||
constructor(layer: Vector, nodeCapacity: number) {
|
||||
super(layer, nodeCapacity);
|
||||
constructor(quadTreeStrategy: QuadTreeStrategy, layer: Vector, nodeCapacity: number) {
|
||||
super(quadTreeStrategy, layer, nodeCapacity);
|
||||
|
||||
let planet = layer._planet!;
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ import * as mercator from "../../mercator";
|
||||
import {Extent} from "../../Extent";
|
||||
import {Node} from "../Node";
|
||||
import {Planet} from "../../scene/Planet";
|
||||
import {QuadTreeStrategy} from "../QuadTreeStrategy";
|
||||
import {QuadTreeStrategy, QuadTreeStrategyParams} from "../QuadTreeStrategy";
|
||||
import {
|
||||
Segment,
|
||||
TILEGROUP_NORTH,
|
||||
@ -15,6 +15,7 @@ import {SegmentLonLat} from "../../segment/SegmentLonLat";
|
||||
import {LonLat} from "../../LonLat";
|
||||
import {Vector} from "../../layer/Vector";
|
||||
import {EarthEntityCollectionsTreeStrategy} from "./EarthEntityCollectionsTreeStrategy";
|
||||
import {PlanetCamera} from "../../camera";
|
||||
|
||||
export class EarthQuadTreeStrategy extends QuadTreeStrategy {
|
||||
|
||||
@ -32,8 +33,8 @@ export class EarthQuadTreeStrategy extends QuadTreeStrategy {
|
||||
*/
|
||||
public _visibleNodesSouth: Record<number, Node>;
|
||||
|
||||
constructor(planet: Planet) {
|
||||
super(planet, "Earth");
|
||||
constructor(params: QuadTreeStrategyParams) {
|
||||
super({name: "Earth", ...params});
|
||||
|
||||
this._visibleNodesNorth = {};
|
||||
this._visibleNodesSouth = {};
|
||||
@ -56,29 +57,32 @@ export class EarthQuadTreeStrategy extends QuadTreeStrategy {
|
||||
this._visibleNodesSouth = {};
|
||||
}
|
||||
|
||||
public override createEntitiCollectionsTreeStrategy(layer: Vector, nodeCapacity: number): EarthEntityCollectionsTreeStrategy {
|
||||
return new EarthEntityCollectionsTreeStrategy(layer, nodeCapacity);
|
||||
public override createEntityCollectionsTreeStrategy(layer: Vector, nodeCapacity: number): EarthEntityCollectionsTreeStrategy {
|
||||
return new EarthEntityCollectionsTreeStrategy(this, layer, nodeCapacity);
|
||||
}
|
||||
|
||||
public override init() {
|
||||
public override init(camera: PlanetCamera) {
|
||||
|
||||
this._quadTreeList = [
|
||||
new Node(Segment, this.planet, 0, null, 0,
|
||||
new Node(Segment, this, 0, null, 0,
|
||||
Extent.createFromArray([-20037508.34, -20037508.34, 20037508.34, 20037508.34])
|
||||
),
|
||||
new Node(SegmentLonLat, this.planet, 0, null, 0,
|
||||
new Node(SegmentLonLat, this, 0, null, 0,
|
||||
Extent.createFromArray([-180, mercator.MAX_LAT, 180, 90])
|
||||
),
|
||||
new Node(SegmentLonLat, this.planet, 0, null, 0,
|
||||
new Node(SegmentLonLat, this, 0, null, 0,
|
||||
Extent.createFromArray([-180, -90, 180, mercator.MIN_LAT])
|
||||
)
|
||||
];
|
||||
|
||||
super.init(camera);
|
||||
}
|
||||
|
||||
public override getTileXY(lonLat: LonLat, zoom: number): [number, number, number, number] {
|
||||
let tileGroup = getTileGroupByLat(lonLat.lat, mercator.MAX_LAT),
|
||||
z = zoom,
|
||||
x = -1,
|
||||
y = -1,
|
||||
x: number,
|
||||
y: number,
|
||||
pz = (1 << z)/*Math.pow(2, z)*/;
|
||||
|
||||
if (tileGroup === TILEGROUP_NORTH) {
|
||||
@ -98,7 +102,7 @@ export class EarthQuadTreeStrategy extends QuadTreeStrategy {
|
||||
|
||||
public override getLonLatTileOffset(lonLat: LonLat, x: number, y: number, z: number, gridSize: number): [number, number] {
|
||||
let coords = lonLat;
|
||||
let extent = new Extent();
|
||||
let extent: Extent;
|
||||
|
||||
if (lonLat.lat > mercator.MAX_LAT) {
|
||||
let worldExtent = Extent.createFromArray([-180, mercator.MAX_LAT, 180, 90]);
|
||||
|
||||
@ -6,6 +6,7 @@ import {EntityCollection} from "../../entity/EntityCollection";
|
||||
import {EquiQuadTreeStrategy} from "./EquiQuadTreeStrategy";
|
||||
import {EntityCollectionsTreeStrategy} from "../EntityCollectionsTreeStrategy";
|
||||
import {EquiEntityCollectionNodeLonLat} from "./EquiEntityCollectionNodeLonLat";
|
||||
import {QuadTreeStrategy} from "../QuadTreeStrategy";
|
||||
|
||||
export class EquiEntityCollectionsTreeStrategy extends EntityCollectionsTreeStrategy {
|
||||
|
||||
@ -15,8 +16,8 @@ export class EquiEntityCollectionsTreeStrategy extends EntityCollectionsTreeStra
|
||||
public _renderingNodesWest: Record<number, boolean>;
|
||||
public _renderingNodesEast: Record<number, boolean>;
|
||||
|
||||
constructor(layer: Vector, nodeCapacity: number) {
|
||||
super(layer, nodeCapacity);
|
||||
constructor(quadTreeStrategy: QuadTreeStrategy, layer: Vector, nodeCapacity: number) {
|
||||
super(quadTreeStrategy, layer, nodeCapacity);
|
||||
|
||||
let planet = layer._planet!;
|
||||
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import * as quadTree from "../quadTree";
|
||||
import {Extent} from "../../Extent";
|
||||
import {equi} from "../../proj/equi";
|
||||
import {Node} from "../Node";
|
||||
import {Planet} from "../../scene/Planet";
|
||||
import {SegmentLonLatEqui} from "../../segment/SegmentLonLatEqui";
|
||||
import {QuadTreeStrategy} from "../QuadTreeStrategy";
|
||||
import {QuadTreeStrategy, QuadTreeStrategyParams} from "../QuadTreeStrategy";
|
||||
import {LonLat} from "../../LonLat";
|
||||
import {
|
||||
getTileCellExtent,
|
||||
@ -14,17 +13,18 @@ import {
|
||||
import {Vector} from "../../layer/Vector";
|
||||
import {EntityCollectionsTreeStrategy} from "../EntityCollectionsTreeStrategy";
|
||||
import {EquiEntityCollectionsTreeStrategy} from "./EquiEntityCollectionsTreeStrategy";
|
||||
import {PlanetCamera} from "../../camera";
|
||||
|
||||
export class EquiQuadTreeStrategy extends QuadTreeStrategy {
|
||||
|
||||
private _westExtent: Extent;
|
||||
private _eastExtent: Extent;
|
||||
private readonly _westExtent: Extent;
|
||||
private readonly _eastExtent: Extent;
|
||||
|
||||
public _visibleNodesWest: Record<number, Node>;
|
||||
public _visibleNodesEast: Record<number, Node>;
|
||||
|
||||
constructor(planet: Planet) {
|
||||
super(planet, "Mars", equi);
|
||||
constructor(params: QuadTreeStrategyParams) {
|
||||
super({name: "Mars", proj: equi, ...params});
|
||||
this._westExtent = Extent.createFromArray([-180, -90, 0, 90]);
|
||||
this._eastExtent = Extent.createFromArray([0, -90, 180, 90]);
|
||||
|
||||
@ -32,11 +32,12 @@ export class EquiQuadTreeStrategy extends QuadTreeStrategy {
|
||||
this._visibleNodesEast = {};
|
||||
}
|
||||
|
||||
public override init() {
|
||||
public override init(camera: PlanetCamera) {
|
||||
|
||||
this._quadTreeList = [
|
||||
new Node(
|
||||
SegmentLonLatEqui,
|
||||
this.planet,
|
||||
this,
|
||||
0,
|
||||
null,
|
||||
0,
|
||||
@ -44,19 +45,21 @@ export class EquiQuadTreeStrategy extends QuadTreeStrategy {
|
||||
),
|
||||
new Node(
|
||||
SegmentLonLatEqui,
|
||||
this.planet,
|
||||
this,
|
||||
0,
|
||||
null,
|
||||
0,
|
||||
this._eastExtent
|
||||
)
|
||||
];
|
||||
|
||||
super.init(camera);
|
||||
}
|
||||
|
||||
public override getTileXY(lonLat: LonLat, zoom: number): [number, number, number, number] {
|
||||
let z = zoom,
|
||||
x = -1,
|
||||
y = -1,
|
||||
x: number,
|
||||
y: number,
|
||||
pz = (1 << z);
|
||||
|
||||
if (lonLat.lon > 0) {
|
||||
@ -71,8 +74,7 @@ export class EquiQuadTreeStrategy extends QuadTreeStrategy {
|
||||
}
|
||||
|
||||
public override getLonLatTileOffset(lonLat: LonLat, x: number, y: number, z: number, gridSize: number): [number, number] {
|
||||
let coords = lonLat;
|
||||
let extent = new Extent();
|
||||
let extent: Extent;
|
||||
|
||||
if (lonLat.lon > 0) {
|
||||
extent = getTileCellExtent(x - (1 << z), y, z, this._eastExtent);
|
||||
@ -83,14 +85,14 @@ export class EquiQuadTreeStrategy extends QuadTreeStrategy {
|
||||
let sizeImgW = extent.getWidth() / (gridSize - 1),
|
||||
sizeImgH = extent.getHeight() / (gridSize - 1);
|
||||
|
||||
let i = gridSize - Math.ceil((coords.lat - extent.southWest.lat) / sizeImgH) - 1,
|
||||
j = Math.floor((coords.lon - extent.southWest.lon) / sizeImgW);
|
||||
let i = gridSize - Math.ceil((lonLat.lat - extent.southWest.lat) / sizeImgH) - 1,
|
||||
j = Math.floor((lonLat.lon - extent.southWest.lon) / sizeImgW);
|
||||
|
||||
return [i, j];
|
||||
}
|
||||
|
||||
public override createEntitiCollectionsTreeStrategy(layer: Vector, nodeCapacity: number): EntityCollectionsTreeStrategy {
|
||||
return new EquiEntityCollectionsTreeStrategy(layer, nodeCapacity);
|
||||
public override createEntityCollectionsTreeStrategy(layer: Vector, nodeCapacity: number): EntityCollectionsTreeStrategy {
|
||||
return new EquiEntityCollectionsTreeStrategy(this, layer, nodeCapacity);
|
||||
}
|
||||
|
||||
public override collectVisibleNode(node: Node) {
|
||||
|
||||
@ -1,25 +1,28 @@
|
||||
import * as quadTree from "../quadTree";
|
||||
import {Extent} from "../../Extent";
|
||||
import {EPSG4326} from "../../proj/EPSG4326";
|
||||
import {Node} from "../Node";
|
||||
import {Planet} from "../../scene/Planet";
|
||||
import {SegmentLonLatEqui} from "../../segment/SegmentLonLatEqui";
|
||||
import {QuadTreeStrategy} from "../QuadTreeStrategy";
|
||||
import {QuadTreeStrategy, QuadTreeStrategyParams} from "../QuadTreeStrategy";
|
||||
import {PlanetCamera} from "../../camera";
|
||||
|
||||
export class Wgs84QuadTreeStrategy extends QuadTreeStrategy {
|
||||
constructor(planet: Planet) {
|
||||
super(planet, "wgs84", EPSG4326);
|
||||
constructor(params: QuadTreeStrategyParams) {
|
||||
super({name: "wgs84", proj: EPSG4326, ...params});
|
||||
}
|
||||
|
||||
public override init() {
|
||||
public override init(camera: PlanetCamera) {
|
||||
|
||||
this._quadTreeList = [
|
||||
new Node(
|
||||
SegmentLonLatEqui,
|
||||
this.planet,
|
||||
this,
|
||||
0, null,
|
||||
0,
|
||||
Extent.createFromArray([-180, -90, 180, 90])
|
||||
)
|
||||
];
|
||||
|
||||
super.init(camera);
|
||||
}
|
||||
}
|
||||
@ -12,7 +12,7 @@ import type {WebGLBufferExt} from "../webgl/Handler";
|
||||
import {input} from "../input/input";
|
||||
import {isEmpty} from "../utils/shared";
|
||||
import {LabelWorker} from "../entity/LabelWorker";
|
||||
import {randomi} from "../math";
|
||||
import {MAX_FLOAT, randomi} from "../math";
|
||||
import {RenderNode} from "../scene/RenderNode";
|
||||
import {screenFrame} from "../shaders/screenFrame";
|
||||
import {toneMapping} from "../shaders/tone_mapping/toneMapping";
|
||||
@ -1250,9 +1250,8 @@ class Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
protected _readDepthBuffer() {
|
||||
this.depthFramebuffer!.readPixelBuffersAsync();
|
||||
//console.log("read depth");
|
||||
protected _readDepthBuffer(callback?: () => void) {
|
||||
this.depthFramebuffer!.readPixelBuffersAsync(callback);
|
||||
}
|
||||
|
||||
protected _readPickingBuffer_webgl1() {
|
||||
@ -1283,26 +1282,6 @@ class Renderer {
|
||||
|
||||
public readDepth(x: number, y: number, outDepth: NumberArray3 | Float32Array) {
|
||||
|
||||
// let depthFramebuffer = this.depthFramebuffer!;
|
||||
//
|
||||
// let w = depthFramebuffer.width;
|
||||
// let h = depthFramebuffer.height;
|
||||
//
|
||||
// let sx = Math.round(x * w);
|
||||
// let sy = Math.round(y * h);
|
||||
//
|
||||
// let ind = (sy * w + sx) * 4;
|
||||
//
|
||||
// let _tempDepthPix_ = depthFramebuffer.pixelBuffers[1].data;
|
||||
// let _tempFrustumPix_ = depthFramebuffer.pixelBuffers[0].data!;
|
||||
//
|
||||
// if (_tempDepthPix_) {
|
||||
// outDepth[0] = _tempDepthPix_[ind];
|
||||
// outDepth[1] = Math.round(_tempFrustumPix_[ind] / 10.0) - 1.0; // See Camera.frustumColorIndex
|
||||
// }
|
||||
|
||||
//////
|
||||
|
||||
let ddd = new Float32Array(4);
|
||||
let fff = new Uint8Array(4);
|
||||
|
||||
@ -1330,25 +1309,26 @@ class Renderer {
|
||||
|
||||
_tempDepth_[0] = _tempDepth_[1] = 0.0;
|
||||
|
||||
let dist = 0;
|
||||
|
||||
this.readDepth(nx, ny, _tempDepth_);
|
||||
|
||||
if (_tempDepth_[1] === -1) {
|
||||
return;
|
||||
}
|
||||
if (_tempDepth_[1] === -1) return;
|
||||
|
||||
let depth = _tempDepth_[0],
|
||||
frustum = camera.frustums[_tempDepth_[1]];
|
||||
|
||||
if (!frustum) return;
|
||||
|
||||
let screenPos = new Vec4(nx * 2.0 - 1.0, ny * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
||||
let viewPosition = frustum.inverseProjectionMatrix.mulVec4(screenPos);
|
||||
let dir = (px as IBaseInputState).direction || camera.unproject(px.x, px.y);
|
||||
dist = -(viewPosition.z / viewPosition.w) / dir.dot(camera.getForward());
|
||||
let ndc = new Vec4(nx * 2.0 - 1.0, ny * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
||||
let view = frustum.inverseProjectionMatrix.mulVec4(ndc);
|
||||
let zView = -view.z / view.w;
|
||||
|
||||
return dist;
|
||||
//
|
||||
// todo: maybe lets calculate distance to camera eye????? No?
|
||||
//
|
||||
if (camera.isOrthographic) return zView;
|
||||
|
||||
let dir = (px as IBaseInputState).direction || camera.unproject(px.x, px.y);
|
||||
return zView / Math.max(1e-6, dir.dot(camera.getForward()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1358,10 +1338,61 @@ class Renderer {
|
||||
* @returns {Vec3 | undefined} -
|
||||
*/
|
||||
public getCartesianFromPixel(px: Vec2 | IBaseInputState): Vec3 | undefined {
|
||||
let distance = this.getDistanceFromPixel(px);
|
||||
if (distance) {
|
||||
let direction = (px as IBaseInputState).direction || this.activeCamera.unproject(px.x, px.y);
|
||||
return direction.scaleTo(distance).addA(this.activeCamera.eye);
|
||||
let dist = this.getDistanceFromPixel(px);
|
||||
if (dist) {
|
||||
if (this.activeCamera.isOrthographic) {
|
||||
let res = new Vec3();
|
||||
this.activeCamera.unproject(px.x, px.y, dist, res);
|
||||
return res;
|
||||
} else {
|
||||
let direction = (px as IBaseInputState).direction || this.activeCamera.unproject(px.x, px.y);
|
||||
return direction.scaleTo(dist).addA(this.activeCamera.eye);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getCartesianFromPixelAsync(px: Vec2 | IBaseInputState): Promise<Vec3 | undefined> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this._readDepthBuffer(() => {
|
||||
resolve(this.getCartesianFromPixel(px));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public getDepthMinDistance(): number {
|
||||
let cnv = this.handler!.canvas!;
|
||||
let w = cnv.width,
|
||||
h = cnv.height,
|
||||
min = MAX_FLOAT;
|
||||
let size = h * w;
|
||||
let p = new Vec2();
|
||||
for (let i = 0; i < size; i++) {
|
||||
p.x = i % w;
|
||||
p.y = Math.floor(i / w);
|
||||
let d = this.getDistanceFromPixel(p);
|
||||
if (d && (d < min)) {
|
||||
min = d;
|
||||
}
|
||||
}
|
||||
return min < MAX_FLOAT ? min : 0;
|
||||
}
|
||||
|
||||
public getDepthMinDistanceAsync(): Promise<number> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this._readDepthBuffer(() => {
|
||||
resolve(this.getDepthMinDistance());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async setOrthographicProjection(isOrtho: boolean) {
|
||||
if (isOrtho !== this.activeCamera.isOrthographic) {
|
||||
let dist = await this.getDepthMinDistanceAsync();
|
||||
if (dist && isOrtho) {
|
||||
this.activeCamera.focusDistance = dist;
|
||||
}
|
||||
this.activeCamera.isOrthographic = isOrtho;
|
||||
this.events.dispatch(this.events.projchanged, this.activeCamera);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@ export function createRendererEvents(renderer: Renderer) {
|
||||
}
|
||||
|
||||
export type RendererEventsType = [
|
||||
"projchanged",
|
||||
"changerelativecenter",
|
||||
"draw",
|
||||
"drawtransparent",
|
||||
@ -1027,6 +1028,16 @@ class RendererEvents extends Events<RendererEventsType> implements RendererEvent
|
||||
}
|
||||
|
||||
const RENDERER_EVENTS: RendererEventsType = [
|
||||
/**
|
||||
* Triggered when camera projection is changed
|
||||
* @event og.RendererEvents#projchanged
|
||||
*/
|
||||
"projchanged",
|
||||
|
||||
/**
|
||||
* Triggered when relative center is changed
|
||||
* @event og.RendererEvents#changerelativecenter
|
||||
*/
|
||||
"changerelativecenter",
|
||||
|
||||
/**
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import * as math from "../math";
|
||||
import * as segmentHelper from "../segment/segmentHelper";
|
||||
import * as shaders from "../shaders/drawnode/drawnode";
|
||||
import * as utils from "../utils/shared";
|
||||
@ -42,8 +41,8 @@ import type {WebGLBufferExt, WebGLTextureExt, IDefaultTextureParams} from "../we
|
||||
import {Program} from "../webgl/Program";
|
||||
import {Segment} from "../segment/Segment";
|
||||
import type {AtmosphereParameters} from "../shaders/atmos/atmos";
|
||||
import { EasingFunction } from "../utils/easing";
|
||||
import { DEFAULT_EASING, DEFAULT_FLIGHT_DURATION } from "../camera/Camera";
|
||||
import {Easing, EasingFunction} from "../utils/easing";
|
||||
|
||||
export interface IPlanetParams {
|
||||
name?: string;
|
||||
@ -82,10 +81,6 @@ export type PlanetEventsList = [
|
||||
"layerloadend"
|
||||
];
|
||||
|
||||
const CUR_LOD_SIZE = 256; //px
|
||||
const MIN_LOD_SIZE = 512; //px
|
||||
const MAX_LOD_SIZE = 256; //px
|
||||
|
||||
/**
|
||||
* Maximum created nodes count. The more nodes count the more memory usage.
|
||||
* When the maximum node count is exceeded, memClear() will be called.
|
||||
@ -95,8 +90,6 @@ const MAX_LOD_SIZE = 256; //px
|
||||
*/
|
||||
const DEFAULT_MAX_NODES = 200;
|
||||
|
||||
const HORIZON_TANGENT = 0.81;
|
||||
|
||||
type IndexBufferCacheData = { buffer: WebGLBufferExt | null };
|
||||
|
||||
/**
|
||||
@ -121,6 +114,8 @@ export class Planet extends RenderNode {
|
||||
|
||||
public events: EventsHandler<PlanetEventsList>;
|
||||
|
||||
public _createdNodesCount: number;
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @type {Ellipsoid}
|
||||
@ -200,10 +195,6 @@ export class Planet extends RenderNode {
|
||||
*/
|
||||
public camera: PlanetCamera;
|
||||
|
||||
public maxEqualZoomAltitude: number;
|
||||
public minEqualZoomAltitude: number;
|
||||
public minEqualZoomCameraSlope: number;
|
||||
|
||||
/**
|
||||
* Screen mouse pointer projected to planet cartesian position.
|
||||
* @public
|
||||
@ -215,41 +206,8 @@ export class Planet extends RenderNode {
|
||||
public transparentTexture: WebGLTextureExt | null;
|
||||
public defaultTexture: WebGLTextureExt | null;
|
||||
|
||||
/**
|
||||
* Current visible minimal zoom index planet segment.
|
||||
* @public
|
||||
* @type {number}
|
||||
*/
|
||||
public minCurrZoom: number;
|
||||
|
||||
/**
|
||||
* Current visible maximal zoom index planet segment.
|
||||
* @public
|
||||
* @type {number}
|
||||
*/
|
||||
public maxCurrZoom: number;
|
||||
|
||||
public _viewExtent: Extent;
|
||||
|
||||
protected _initialViewExtent: Extent | null;
|
||||
|
||||
public _createdNodesCount: number;
|
||||
|
||||
/**
|
||||
* Planet's segments collected for rendering frame.
|
||||
* @public
|
||||
* @type {Node}
|
||||
*/
|
||||
public _renderedNodes: Node[];
|
||||
|
||||
public _renderedNodesInFrustum: Node[][];
|
||||
|
||||
public _fadingNodes: Map<number, Node>;
|
||||
|
||||
public _fadingNodesInFrustum: Node[][];
|
||||
|
||||
protected _fadingOpaqueSegments: Segment[];
|
||||
|
||||
/**
|
||||
* Layers activity lock.
|
||||
* @public
|
||||
@ -288,6 +246,7 @@ export class Planet extends RenderNode {
|
||||
*/
|
||||
public _textureCoordsBufferCache: WebGLBufferExt[];
|
||||
|
||||
public quadTreeStrategyPrototype: typeof QuadTreeStrategy;
|
||||
public quadTreeStrategy: QuadTreeStrategy;
|
||||
|
||||
/**
|
||||
@ -318,16 +277,6 @@ export class Planet extends RenderNode {
|
||||
public SLICE_SIZE_4: number;
|
||||
public SLICE_SIZE_3: number;
|
||||
|
||||
/**
|
||||
* Level of details of visible segments.
|
||||
* @protected
|
||||
* @type {number}
|
||||
*/
|
||||
protected _lodSize: number;
|
||||
protected _curLodSize: number;
|
||||
protected _minLodSize: number;
|
||||
public _maxLodSize: number;
|
||||
|
||||
public _pickingColorArr: Float32Array;
|
||||
public _samplerArr: Int32Array;
|
||||
public _pickingMaskArr: Int32Array;
|
||||
@ -367,12 +316,6 @@ export class Planet extends RenderNode {
|
||||
|
||||
protected _initialized: boolean;
|
||||
|
||||
public _renderCompleted: boolean
|
||||
public _renderCompletedActivated: boolean;
|
||||
|
||||
public _terrainCompleted: boolean;
|
||||
public _terrainCompletedActivated: boolean;
|
||||
|
||||
protected _collectRenderNodesIsActive: boolean;
|
||||
|
||||
/**
|
||||
@ -390,15 +333,11 @@ export class Planet extends RenderNode {
|
||||
public solidTextureOne: WebGLTextureExt | null;
|
||||
public solidTextureTwo: WebGLTextureExt | null;
|
||||
|
||||
protected _skipPreRender: boolean;
|
||||
|
||||
protected _nightTextureSrc: string | null;
|
||||
protected _specularTextureSrc: string | null;
|
||||
|
||||
public transitionTime: number;
|
||||
|
||||
protected _transitionOpacityEnabled: boolean;
|
||||
|
||||
protected _atmosphere: Atmosphere;
|
||||
private _minDistanceBeforeMemClear: number = 0;
|
||||
private _maxNodes: number;
|
||||
@ -406,6 +345,8 @@ export class Planet extends RenderNode {
|
||||
constructor(options: IPlanetParams = {}) {
|
||||
super(options.name);
|
||||
|
||||
this._createdNodesCount = 0;
|
||||
|
||||
this._atmosphere = new Atmosphere(options.atmosphereParameters);
|
||||
|
||||
this.transitionTime = 580;
|
||||
@ -442,35 +383,14 @@ export class Planet extends RenderNode {
|
||||
maxAltitude: options.maxAltitude
|
||||
});
|
||||
|
||||
this.maxEqualZoomAltitude = options.maxEqualZoomAltitude || 15000000.0;
|
||||
this.minEqualZoomAltitude = options.minEqualZoomAltitude || 10000.0;
|
||||
this.minEqualZoomCameraSlope = options.minEqualZoomCameraSlope || 0.8;
|
||||
|
||||
this.mousePositionOnEarth = new Vec3();
|
||||
|
||||
this.emptyTexture = null;
|
||||
this.transparentTexture = null;
|
||||
this.defaultTexture = null;
|
||||
|
||||
this.minCurrZoom = math.MAX;
|
||||
|
||||
this.maxCurrZoom = math.MIN;
|
||||
|
||||
this._viewExtent = new Extent(new LonLat(180, 180), new LonLat(-180, -180));
|
||||
|
||||
this._skipPreRender = false;
|
||||
|
||||
this._initialViewExtent = null;
|
||||
|
||||
this._createdNodesCount = 0;
|
||||
|
||||
this._renderedNodes = [];
|
||||
this._renderedNodesInFrustum = [];
|
||||
|
||||
this._fadingNodes = new Map<number, Node>;
|
||||
this._fadingNodesInFrustum = [];
|
||||
this._fadingOpaqueSegments = [];
|
||||
|
||||
this.layerLock = new Lock();
|
||||
|
||||
this.terrainLock = new Lock();
|
||||
@ -483,7 +403,17 @@ export class Planet extends RenderNode {
|
||||
|
||||
this._textureCoordsBufferCache = [];
|
||||
|
||||
this.quadTreeStrategy = options.quadTreeStrategyPrototype ? new options.quadTreeStrategyPrototype(this) : new EarthQuadTreeStrategy(this);
|
||||
const quadTreeParams = {
|
||||
planet: this,
|
||||
maxEqualZoomAltitude: options.maxEqualZoomAltitude,
|
||||
minEqualZoomAltitude: options.minEqualZoomAltitude,
|
||||
minEqualZoomCameraSlope: options.minEqualZoomCameraSlope,
|
||||
transitionOpacityEnabled: options.transitionOpacityEnabled,
|
||||
};
|
||||
|
||||
// Used in CameraDepthHandler
|
||||
this.quadTreeStrategyPrototype = options.quadTreeStrategyPrototype || EarthQuadTreeStrategy;
|
||||
this.quadTreeStrategy = new this.quadTreeStrategyPrototype(quadTreeParams);
|
||||
|
||||
this._nightTexture = null;
|
||||
|
||||
@ -504,11 +434,6 @@ export class Planet extends RenderNode {
|
||||
this.SLICE_SIZE_4 = this.SLICE_SIZE * 4;
|
||||
this.SLICE_SIZE_3 = this.SLICE_SIZE * 3;
|
||||
|
||||
this._lodSize = CUR_LOD_SIZE;
|
||||
this._curLodSize = CUR_LOD_SIZE;
|
||||
this._minLodSize = MIN_LOD_SIZE;
|
||||
this._maxLodSize = MAX_LOD_SIZE;
|
||||
|
||||
this._maxNodes = options.maxNodesCount || DEFAULT_MAX_NODES;
|
||||
|
||||
this._pickingColorArr = new Float32Array(this.SLICE_SIZE_4);
|
||||
@ -537,11 +462,6 @@ export class Planet extends RenderNode {
|
||||
|
||||
this._initialized = false;
|
||||
|
||||
this._renderCompleted = false;
|
||||
this._renderCompletedActivated = false;
|
||||
|
||||
this._terrainCompleted = false;
|
||||
this._terrainCompletedActivated = false;
|
||||
this._collectRenderNodesIsActive = true;
|
||||
|
||||
this.nightTextureCoefficient = 2.0;
|
||||
@ -557,15 +477,13 @@ export class Planet extends RenderNode {
|
||||
|
||||
this._nightTextureSrc = options.nightTextureSrc || null;
|
||||
this._specularTextureSrc = options.specularTextureSrc || null;
|
||||
|
||||
this._transitionOpacityEnabled = options.transitionOpacityEnabled != undefined ? options.transitionOpacityEnabled : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if current terrain data set is loaded
|
||||
*/
|
||||
public get terrainReady(): boolean {
|
||||
return this._terrainCompleted && this._terrainCompletedActivated;
|
||||
return this.quadTreeStrategy.terrainReady;
|
||||
}
|
||||
|
||||
public get maxGridSize(): number {
|
||||
@ -635,16 +553,6 @@ export class Planet extends RenderNode {
|
||||
return [...this._layers];
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo: remove after tests
|
||||
* Get the collection of layers associated with this planet.
|
||||
* @return {Array.<Layer>} Layers array.
|
||||
* @public
|
||||
*/
|
||||
public getLayers(): Layer[] {
|
||||
return this.layers;
|
||||
}
|
||||
|
||||
public get sun(): Sun | undefined {
|
||||
if (this.renderer && this.renderer.controls.sun)
|
||||
return this.renderer.controls.sun as Sun;
|
||||
@ -663,18 +571,6 @@ export class Planet extends RenderNode {
|
||||
control.addTo(this.renderer!);
|
||||
}
|
||||
|
||||
public get lodSize(): number {
|
||||
return this._lodSize;
|
||||
}
|
||||
|
||||
public setLodSize(currentLodSize: number, minLodSize?: number, maxLodSize?: number) {
|
||||
this._maxLodSize = maxLodSize || this._maxLodSize;
|
||||
this._minLodSize = minLodSize || this._minLodSize;
|
||||
this._curLodSize = currentLodSize;
|
||||
this._renderCompletedActivated = false;
|
||||
this._terrainCompletedActivated = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given controls array to the renderer of the planet.
|
||||
* @param {Array.<Control>} cArr - Control array.
|
||||
@ -771,14 +667,10 @@ export class Planet extends RenderNode {
|
||||
* @param {number} factor - Elevation scale.
|
||||
*/
|
||||
public setHeightFactor(factor: number) {
|
||||
this._renderCompletedActivated = false;
|
||||
this._terrainCompletedActivated = false;
|
||||
|
||||
if (this._heightFactor !== factor) {
|
||||
this._heightFactor = factor;
|
||||
this.quadTreeStrategy.destroyBranches();
|
||||
this._clearRenderedNodeList();
|
||||
this._clearRenderNodesInFrustum();
|
||||
this.quadTreeStrategy.clearRenderedNodes();
|
||||
}
|
||||
}
|
||||
|
||||
@ -796,9 +688,6 @@ export class Planet extends RenderNode {
|
||||
* @param {EmptyTerrain} terrain - Terrain provider.
|
||||
*/
|
||||
public setTerrain(terrain: EmptyTerrain) {
|
||||
this._renderCompletedActivated = false;
|
||||
this._terrainCompletedActivated = false;
|
||||
|
||||
if (this._initialized) {
|
||||
this.memClear();
|
||||
}
|
||||
@ -835,7 +724,7 @@ export class Planet extends RenderNode {
|
||||
let h = this.renderer.handler;
|
||||
if (h.isWebGl2()) {
|
||||
h.removeProgram("drawnode_screen_wl");
|
||||
h.addProgram(shaders.drawnode_screen_wl_webgl2Atmos(atmosParams), true);
|
||||
h.addProgram(shaders.drawnode_screen_wl_webgl2Atmos(atmosParams));
|
||||
} else {
|
||||
console.warn("Atmosphere WebGL2 only");
|
||||
}
|
||||
@ -866,9 +755,9 @@ export class Planet extends RenderNode {
|
||||
this._atmosphere.activate();
|
||||
|
||||
if (h.isWebGl2()) {
|
||||
h.addProgram(shaders.drawnode_screen_wl_webgl2Atmos(this._atmosphere.parameters), true);
|
||||
h.addProgram(shaders.drawnode_screen_wl_webgl2Atmos(this._atmosphere.parameters));
|
||||
} else {
|
||||
h.addProgram(shaders.drawnode_screen_wl_webgl1NoAtmos(), true);
|
||||
h.addProgram(shaders.drawnode_screen_wl_webgl1NoAtmos());
|
||||
}
|
||||
|
||||
if (this.renderer.controls.SimpleSkyBackground) {
|
||||
@ -889,23 +778,29 @@ export class Planet extends RenderNode {
|
||||
}
|
||||
|
||||
if (h.isWebGl2()) {
|
||||
h.addProgram(shaders.drawnode_screen_wl_webgl2NoAtmos(), true);
|
||||
h.addProgram(shaders.drawnode_screen_wl_webgl2NoAtmos());
|
||||
} else {
|
||||
h.addProgram(shaders.drawnode_screen_wl_webgl1NoAtmos(), true);
|
||||
h.addProgram(shaders.drawnode_screen_wl_webgl1NoAtmos());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected _initializeShaders() {
|
||||
let h = this.renderer!.handler;
|
||||
if (!this.renderer) {
|
||||
throw new Error("Renderer is not initialized");
|
||||
}
|
||||
|
||||
h.addProgram(shaders.drawnode_screen_nl(), true);
|
||||
h.addProgram(shaders.drawnode_colorPicking(), true);
|
||||
h.addProgram(shaders.drawnode_depth(), true);
|
||||
//h.addProgram(shaders.drawnode_heightPicking(), true);
|
||||
let r = this.renderer,
|
||||
h = r.handler;
|
||||
|
||||
this.renderer!.addPickingCallback(this, this._renderColorPickingFramebufferPASS);
|
||||
this.renderer!.addDepthCallback(this, this._renderDepthFramebufferPASS);
|
||||
h.addProgram(shaders.drawnode_screen_nl());
|
||||
h.addProgram(shaders.drawnode_colorPicking());
|
||||
h.addProgram(shaders.drawnode_depth());
|
||||
|
||||
r.addPickingCallback(this, this._renderColorPickingFramebufferPASS);
|
||||
r.addDepthCallback(this, () => {
|
||||
this.renderDepthFramebuffer(this.camera, this.quadTreeStrategy);
|
||||
});
|
||||
}
|
||||
|
||||
protected _onLayerLoadend(layer: Layer) {
|
||||
@ -951,11 +846,6 @@ export class Planet extends RenderNode {
|
||||
}
|
||||
}
|
||||
|
||||
this.renderer!.events.on("resize", () => {
|
||||
this._renderCompletedActivated = false;
|
||||
this._terrainCompletedActivated = false;
|
||||
});
|
||||
|
||||
this.renderer!.events.on("drawtransparent", () => {
|
||||
this._renderScreenNodesWithHeightPASS();
|
||||
});
|
||||
@ -977,14 +867,6 @@ export class Planet extends RenderNode {
|
||||
|
||||
this.transparentTexture = this.renderer!.handler.transparentTexture;
|
||||
|
||||
this._renderedNodesInFrustum = new Array(this.camera.frustums.length);
|
||||
for (let i = 0, len = this._renderedNodesInFrustum.length; i < len; i++) {
|
||||
this._renderedNodesInFrustum[i] = [];
|
||||
}
|
||||
|
||||
// Creating quad trees nodes
|
||||
this.quadTreeStrategy.init();
|
||||
|
||||
this.drawMode = this.renderer!.handler.gl!.TRIANGLE_STRIP;
|
||||
|
||||
// Applying shaders
|
||||
@ -1033,12 +915,12 @@ export class Planet extends RenderNode {
|
||||
|
||||
this.renderer!.events.on("draw", this._globalPreDraw, this, -100);
|
||||
|
||||
// Loading first nodes for better viewing if you have started on a lower altitude.
|
||||
this._preRender();
|
||||
// Creating quad trees nodes
|
||||
this.quadTreeStrategy.init(this.camera);
|
||||
|
||||
this.renderer!.events.on("postdraw", () => {
|
||||
this._checkRendercompleted();
|
||||
});
|
||||
// this.renderer!.events.on("postdraw", () => {
|
||||
// this._checkRendercompleted();
|
||||
// });
|
||||
|
||||
this.initLayers();
|
||||
|
||||
@ -1076,17 +958,6 @@ export class Planet extends RenderNode {
|
||||
}
|
||||
}
|
||||
|
||||
protected _preRender() {
|
||||
this.quadTreeStrategy.preRender();
|
||||
this._preLoad();
|
||||
}
|
||||
|
||||
protected _preLoad() {
|
||||
this._clearRenderedNodeList();
|
||||
this._skipPreRender = false;
|
||||
this.quadTreeStrategy.preLoad();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates default textures first for the North Pole and whole globe and second for the South Pole.
|
||||
* @public
|
||||
@ -1230,148 +1101,36 @@ export class Planet extends RenderNode {
|
||||
}
|
||||
}
|
||||
|
||||
protected _clearRenderedNodeList() {
|
||||
this._renderedNodes.length = 0;
|
||||
this._renderedNodes = [];
|
||||
}
|
||||
|
||||
protected _clearRenderNodesInFrustum() {
|
||||
for (let i = 0, len = this._renderedNodesInFrustum.length; i < len; i++) {
|
||||
this._renderedNodesInFrustum[i].length = 0;
|
||||
this._renderedNodesInFrustum[i] = [];
|
||||
}
|
||||
}
|
||||
|
||||
protected _collectRenderedNodesMaxZoom(cam: PlanetCamera) {
|
||||
if (cam.slope > this.minEqualZoomCameraSlope && cam._lonLat.height < this.maxEqualZoomAltitude && cam._lonLat.height > this.minEqualZoomAltitude) {
|
||||
|
||||
this.minCurrZoom = this.maxCurrZoom;
|
||||
|
||||
let temp = this._renderedNodes,
|
||||
rf = this._renderedNodesInFrustum,
|
||||
temp2 = [];
|
||||
|
||||
this._clearRenderNodesInFrustum();
|
||||
this._renderedNodes = [];
|
||||
|
||||
for (let i = 0, len = temp.length; i < len; i++) {
|
||||
let ri = temp[i];
|
||||
let ht = ri.segment.centerNormal.dot(cam.getBackward());
|
||||
if (ri.segment.tileZoom === this.maxCurrZoom || ht < HORIZON_TANGENT) {
|
||||
this._renderedNodes.push(ri);
|
||||
let k = 0, inFrustum = ri.inFrustum;
|
||||
while (inFrustum) {
|
||||
if (inFrustum & 1) {
|
||||
rf[k].push(ri);
|
||||
}
|
||||
k++;
|
||||
inFrustum >>= 1;
|
||||
}
|
||||
} else {
|
||||
temp2.push(ri);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0, len = temp2.length; i < len; i++) {
|
||||
temp2[i].renderTree(cam, this.maxCurrZoom, null, false, temp2[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public set transitionOpacityEnabled(isEnabled: boolean) {
|
||||
this._transitionOpacityEnabled = isEnabled;
|
||||
//@todo: set render nodes transition opacity to one
|
||||
}
|
||||
|
||||
public get transitionOpacityEnabled(): boolean {
|
||||
return this._transitionOpacityEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects visible quad nodes.
|
||||
* @protected
|
||||
*/
|
||||
protected _collectRenderNodes(cam: PlanetCamera) {
|
||||
this._lodSize = math.lerp(cam.slope < 0.0 ? 0.0 : cam.slope, this._curLodSize, this._minLodSize);
|
||||
cam._insideSegment = null;
|
||||
|
||||
// clear first
|
||||
this._clearRenderedNodeList();
|
||||
this._clearRenderNodesInFrustum();
|
||||
|
||||
this._viewExtent.southWest.set(180, 180);
|
||||
this._viewExtent.northEast.set(-180, -180);
|
||||
|
||||
// todo: replace to camera
|
||||
this.minCurrZoom = math.MAX;
|
||||
this.maxCurrZoom = math.MIN;
|
||||
|
||||
this.quadTreeStrategy.collectRenderNodes();
|
||||
|
||||
this._collectRenderedNodesMaxZoom(cam);
|
||||
|
||||
// main camera effect
|
||||
this._fadingNodes.clear();
|
||||
|
||||
if (this._transitionOpacityEnabled) {
|
||||
|
||||
let opaqueNodes: Node[] = [];
|
||||
|
||||
for (let i = 0; i < this._renderedNodes.length; i++) {
|
||||
let ri = this._renderedNodes[i];
|
||||
// it's not impossible to move the code into Node.addToRender, because
|
||||
// we can't know actual state before _collectRenderedNodesMaxZoom pass
|
||||
ri._collectFadingNodes();
|
||||
ri._refreshTransitionOpacity();
|
||||
|
||||
if (ri.segment._transitionOpacity >= 1.0) {
|
||||
ri.clearNeighbors();
|
||||
ri.getRenderedNodesNeighbors(opaqueNodes);
|
||||
opaqueNodes.push(ri);
|
||||
} else {
|
||||
for (let j = 0; j < ri._fadingNodes.length; j++) {
|
||||
let rij = ri._fadingNodes[j];
|
||||
if (rij.segment && rij.segment._transitionOpacity >= 1.0) {
|
||||
rij.clearNeighbors();
|
||||
rij.getRenderedNodesNeighbors(opaqueNodes);
|
||||
opaqueNodes.push(rij);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected _renderScreenNodesPASSNoAtmos() {
|
||||
let cam = this.renderer!.activeCamera as PlanetCamera;
|
||||
let cam = this.camera;
|
||||
let sh = this._setUniformsNoAtmos(cam);
|
||||
//
|
||||
// PASS 0: rendering base slice of layers, which is often zero height
|
||||
this._renderingScreenNodes(sh, cam, this._renderedNodesInFrustum[cam.currentFrustumIndex]);
|
||||
this._renderingScreenNodes(this.quadTreeStrategy, sh, cam, this.quadTreeStrategy._renderedNodesInFrustum[cam.currentFrustumIndex]);
|
||||
}
|
||||
|
||||
protected _renderScreenNodesPASSAtmos() {
|
||||
let cam = this.renderer!.activeCamera as PlanetCamera;
|
||||
let cam = this.camera;
|
||||
let sh = this._setUniformsAtmos(cam);
|
||||
//
|
||||
// PASS 0: rendering base slice of layers, which is often zero height
|
||||
this._renderingScreenNodes(sh, cam, this._renderedNodesInFrustum[cam.currentFrustumIndex]);
|
||||
this._renderingScreenNodes(this.quadTreeStrategy, sh, cam, this.quadTreeStrategy._renderedNodesInFrustum[cam.currentFrustumIndex]);
|
||||
}
|
||||
|
||||
protected _renderScreenNodesWithHeightPASSNoAtmos() {
|
||||
let cam = this.renderer!.activeCamera as PlanetCamera;
|
||||
let cam = this.camera;
|
||||
let sh = this._setUniformsNoAtmos(cam);
|
||||
//
|
||||
// PASS 1: rendering slices, and layers with heights, without transition opacity effect
|
||||
this._renderingScreenNodesWithHeight(sh, cam, this._renderedNodesInFrustum[cam.currentFrustumIndex]);
|
||||
this._renderingScreenNodesWithHeight(this.quadTreeStrategy, sh, cam, this.quadTreeStrategy._renderedNodesInFrustum[cam.currentFrustumIndex]);
|
||||
}
|
||||
|
||||
protected _renderScreenNodesWithHeightPASSAtmos() {
|
||||
let cam = this.renderer!.activeCamera as PlanetCamera;
|
||||
let cam = this.camera;
|
||||
let sh = this._setUniformsAtmos(cam);
|
||||
//
|
||||
// PASS 1: rendering slices, and layers with heights, without transition opacity effect
|
||||
this._renderingScreenNodesWithHeight(sh, cam, this._renderedNodesInFrustum[cam.currentFrustumIndex]);
|
||||
this._renderingScreenNodesWithHeight(this.quadTreeStrategy, sh, cam, this.quadTreeStrategy._renderedNodesInFrustum[cam.currentFrustumIndex]);
|
||||
}
|
||||
|
||||
protected _globalPreDraw() {
|
||||
@ -1405,12 +1164,10 @@ export class Planet extends RenderNode {
|
||||
if (this.camera.isFirstPass) {
|
||||
this.camera.update();
|
||||
|
||||
if (this._skipPreRender && this._collectRenderNodesIsActive) {
|
||||
this._collectRenderNodes(this.camera);
|
||||
if (this._collectRenderNodesIsActive) {
|
||||
this.quadTreeStrategy.collectRenderNodes(this.camera);
|
||||
}
|
||||
|
||||
this._skipPreRender = true;
|
||||
|
||||
//this.transformLights();
|
||||
|
||||
// creates terrain normal maps
|
||||
@ -1448,29 +1205,6 @@ export class Planet extends RenderNode {
|
||||
this._renderScreenNodesPASS();
|
||||
}
|
||||
|
||||
protected _checkRendercompleted() {
|
||||
if (this._renderCompleted) {
|
||||
if (!this._renderCompletedActivated) {
|
||||
this._renderCompletedActivated = true;
|
||||
this.events.dispatch(this.events.rendercompleted, true);
|
||||
}
|
||||
} else {
|
||||
this._renderCompletedActivated = false;
|
||||
}
|
||||
this._renderCompleted = true;
|
||||
|
||||
if (this._terrainCompleted) {
|
||||
if (!this._terrainCompletedActivated) {
|
||||
this._terrainCompletedActivated = true;
|
||||
this.events.dispatch(this.events.terraincompleted, true);
|
||||
}
|
||||
} else {
|
||||
this._terrainCompletedActivated = false;
|
||||
}
|
||||
|
||||
this._terrainCompleted = true;
|
||||
}
|
||||
|
||||
public lockQuadTree() {
|
||||
this._collectRenderNodesIsActive = false;
|
||||
this.camera.setTerrainCollisionActivity(false);
|
||||
@ -1481,7 +1215,6 @@ export class Planet extends RenderNode {
|
||||
this.camera.setTerrainCollisionActivity(true);
|
||||
}
|
||||
|
||||
|
||||
protected _setUniformsNoAtmos(cam: PlanetCamera): Program {
|
||||
let sh, shu;
|
||||
let renderer = this.renderer!;
|
||||
@ -1613,14 +1346,23 @@ export class Planet extends RenderNode {
|
||||
return sh;
|
||||
}
|
||||
|
||||
protected _renderingFadingNodes = (nodes: Map<number, boolean>, sh: Program, currentNode: Node, sl: Layer[], sliceIndex: number, outTransparentSegments?: Segment[], outOpaqueSegments?: Segment[]) => {
|
||||
protected _renderingFadingNodes = (
|
||||
quadTreeStrategy: QuadTreeStrategy,
|
||||
nodes: Map<number, boolean>,
|
||||
sh: Program,
|
||||
currentNode: Node,
|
||||
sl: Layer[],
|
||||
sliceIndex: number,
|
||||
outTransparentSegments?: Segment[],
|
||||
outOpaqueSegments?: Segment[]
|
||||
) => {
|
||||
|
||||
let isFirstPass = sliceIndex === 0;
|
||||
let isEq = this.terrain!.equalizeVertices;
|
||||
|
||||
for (let j = 0, len = currentNode._fadingNodes.length; j < len; j++) {
|
||||
let f = currentNode._fadingNodes[j].segment;
|
||||
if (this._fadingNodes.has(currentNode._fadingNodes[0].__id) && !nodes.has(f.node.__id)) {
|
||||
if (quadTreeStrategy._fadingNodes.has(currentNode._fadingNodes[0].__id) && !nodes.has(f.node.__id)) {
|
||||
nodes.set(f.node.__id, true);
|
||||
|
||||
if (f._transitionOpacity < 1.0) {
|
||||
@ -1639,7 +1381,15 @@ export class Planet extends RenderNode {
|
||||
}
|
||||
}
|
||||
|
||||
protected _renderingFadingNodesNoDepth = (nodes: Map<number, boolean>, sh: Program, currentNode: Node, sl: Layer[], sliceIndex: number, outOpaqueSegments?: Segment[]) => {
|
||||
protected _renderingFadingNodesNoDepth = (
|
||||
quadTreeStrategy: QuadTreeStrategy,
|
||||
nodes: Map<number, boolean>,
|
||||
sh: Program,
|
||||
currentNode: Node,
|
||||
sl: Layer[],
|
||||
sliceIndex: number,
|
||||
outOpaqueSegments?: Segment[]
|
||||
) => {
|
||||
|
||||
let isFirstPass = sliceIndex === 0;
|
||||
let isEq = this.terrain!.equalizeVertices;
|
||||
@ -1649,7 +1399,7 @@ export class Planet extends RenderNode {
|
||||
|
||||
for (let j = 0, len = currentNode._fadingNodes.length; j < len; j++) {
|
||||
let f = currentNode._fadingNodes[j].segment;
|
||||
if (this._fadingNodes.has(currentNode._fadingNodes[0].__id) && !nodes.has(f.node.__id)) {
|
||||
if (quadTreeStrategy._fadingNodes.has(currentNode._fadingNodes[0].__id) && !nodes.has(f.node.__id)) {
|
||||
nodes.set(f.node.__id, true);
|
||||
if (isFirstPass) {
|
||||
isEq && f.equalize();
|
||||
@ -1665,23 +1415,29 @@ export class Planet extends RenderNode {
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
}
|
||||
|
||||
protected static __refreshLayersFadingOpacity__(layersRef: Layer[], minCurrZoom: number, maxCurrZoom: number) {
|
||||
for (let i = layersRef.length - 1; i >= 0; --i) {
|
||||
let li = layersRef[i];
|
||||
if (li._fading && li._refreshFadingOpacity(minCurrZoom, maxCurrZoom)) {
|
||||
layersRef.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Drawing nodes
|
||||
*/
|
||||
protected _renderingScreenNodes(sh: Program, cam: PlanetCamera, renderedNodes: Node[]) {
|
||||
|
||||
let firstPass = cam.isFirstPass;
|
||||
protected _renderingScreenNodes(
|
||||
quadTreeStrategy: QuadTreeStrategy,
|
||||
sh: Program,
|
||||
cam: PlanetCamera,
|
||||
renderedNodes: Node[]
|
||||
) {
|
||||
|
||||
let sl = this._visibleTileLayerSlices;
|
||||
|
||||
if (sl.length) {
|
||||
let sli = sl[0];
|
||||
for (let i = sli.length - 1; i >= 0; --i) {
|
||||
let li = sli[i];
|
||||
if (li._fading && firstPass && li._refreshFadingOpacity()) {
|
||||
sli.splice(i, 1);
|
||||
}
|
||||
}
|
||||
if (sl.length && cam.isFirstPass) {
|
||||
Planet.__refreshLayersFadingOpacity__(sl[0], quadTreeStrategy.minCurrZoom, quadTreeStrategy.maxCurrZoom);
|
||||
}
|
||||
|
||||
let nodes = new Map<number, boolean>;
|
||||
@ -1695,14 +1451,14 @@ export class Planet extends RenderNode {
|
||||
// as the segments with equalized sides, which means that there are no gaps
|
||||
// between currently rendered neighbours
|
||||
//
|
||||
this._fadingOpaqueSegments = [];
|
||||
quadTreeStrategy._fadingOpaqueSegments = [];
|
||||
|
||||
if (cam.slope > 0.8 || !this.terrain || this.terrain.isEmpty /*|| cam.getAltitude() > 10000*/) {
|
||||
while (i--) {
|
||||
let ri = renderedNodes[i];
|
||||
let s = ri.segment;
|
||||
|
||||
this._renderingFadingNodesNoDepth(nodes, sh, ri, sl[0], 0, this._fadingOpaqueSegments);
|
||||
this._renderingFadingNodesNoDepth(quadTreeStrategy, nodes, sh, ri, sl[0], 0, quadTreeStrategy._fadingOpaqueSegments);
|
||||
|
||||
isEq && s.equalize();
|
||||
s.readyToEngage && s.engage();
|
||||
@ -1717,7 +1473,7 @@ export class Planet extends RenderNode {
|
||||
let ri = renderedNodes[i];
|
||||
let s = ri.segment;
|
||||
|
||||
this._renderingFadingNodes(nodes, sh, ri, sl[0], 0, transparentSegments, this._fadingOpaqueSegments);
|
||||
this._renderingFadingNodes(quadTreeStrategy, nodes, sh, ri, sl[0], 0, transparentSegments, quadTreeStrategy._fadingOpaqueSegments);
|
||||
|
||||
if (s._transitionOpacity < 1) {
|
||||
transparentSegments.push(s);
|
||||
@ -1739,14 +1495,16 @@ export class Planet extends RenderNode {
|
||||
tj.screenRendering(sh, sl[0], 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected _renderingScreenNodesWithHeight(sh: Program, cam: PlanetCamera, renderedNodes: Node[]) {
|
||||
let gl = this.renderer!.handler.gl!;
|
||||
let firstPass = cam.isFirstPass;
|
||||
protected _renderingScreenNodesWithHeight(
|
||||
quadTreeStrategy: QuadTreeStrategy,
|
||||
sh: Program,
|
||||
cam: PlanetCamera,
|
||||
renderedNodes: Node[]
|
||||
) {
|
||||
|
||||
let sl = this._visibleTileLayerSlices;
|
||||
let gl = this.renderer!.handler.gl!;
|
||||
|
||||
gl.enable(gl.POLYGON_OFFSET_FILL);
|
||||
gl.disable(gl.CULL_FACE);
|
||||
@ -1754,20 +1512,19 @@ export class Planet extends RenderNode {
|
||||
let nodes = new Map<number, boolean>;
|
||||
let transparentSegments: Segment[] = [];
|
||||
|
||||
let sl = this._visibleTileLayerSlices;
|
||||
|
||||
for (let j = 1, len = sl.length; j < len; j++) {
|
||||
let slj = sl[j];
|
||||
for (let i = slj.length - 1; i >= 0; --i) {
|
||||
let li = slj[i];
|
||||
if (li._fading && firstPass && li._refreshFadingOpacity()) {
|
||||
slj.splice(i, 1);
|
||||
}
|
||||
|
||||
if (cam.isFirstPass) {
|
||||
Planet.__refreshLayersFadingOpacity__(sl[j], quadTreeStrategy.minCurrZoom, quadTreeStrategy.maxCurrZoom);
|
||||
}
|
||||
|
||||
gl.polygonOffset(0, -j);
|
||||
let i = renderedNodes.length;
|
||||
while (i--) {
|
||||
let ri = renderedNodes[i];
|
||||
this._renderingFadingNodes(nodes, sh, ri, sl[j], j, transparentSegments);
|
||||
this._renderingFadingNodes(quadTreeStrategy, nodes, sh, ri, sl[j], j, transparentSegments);
|
||||
if (ri.segment._transitionOpacity < 1) {
|
||||
ri.segment.initSlice(j);
|
||||
} else {
|
||||
@ -1799,7 +1556,7 @@ export class Planet extends RenderNode {
|
||||
gl.uniform3fv(shu.eyePositionLow, cam.eyeLow);
|
||||
|
||||
// drawing planet nodes
|
||||
let rn = this._renderedNodesInFrustum[cam.getCurrentFrustum()];
|
||||
let rn = this.quadTreeStrategy._renderedNodesInFrustum[cam.getCurrentFrustum()];
|
||||
let sl = this._visibleTileLayerSlices;
|
||||
|
||||
let i = rn.length;
|
||||
@ -1809,8 +1566,8 @@ export class Planet extends RenderNode {
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._fadingOpaqueSegments.length; ++i) {
|
||||
this._fadingOpaqueSegments[i].colorPickingRendering(sh, sl[0], 0);
|
||||
for (let i = 0; i < this.quadTreeStrategy._fadingOpaqueSegments.length; ++i) {
|
||||
this.quadTreeStrategy._fadingOpaqueSegments[i].colorPickingRendering(sh, sl[0], 0);
|
||||
}
|
||||
|
||||
// Here is set blending for transparent overlays
|
||||
@ -1828,7 +1585,7 @@ export class Planet extends RenderNode {
|
||||
gl.disable(gl.POLYGON_OFFSET_FILL);
|
||||
}
|
||||
|
||||
protected _renderDepthFramebufferPASS() {
|
||||
public renderDepthFramebuffer(cam: PlanetCamera, quadTreeStrategy: QuadTreeStrategy) {
|
||||
let sh;
|
||||
let renderer = this.renderer!;
|
||||
let h = renderer.handler;
|
||||
@ -1836,7 +1593,6 @@ export class Planet extends RenderNode {
|
||||
h.programs.drawnode_depth.activate();
|
||||
sh = h.programs.drawnode_depth._program;
|
||||
let shu = sh.uniforms;
|
||||
let cam = renderer.activeCamera!;
|
||||
|
||||
gl.disable(gl.BLEND);
|
||||
gl.disable(gl.POLYGON_OFFSET_FILL);
|
||||
@ -1850,7 +1606,7 @@ export class Planet extends RenderNode {
|
||||
gl.uniform1f(shu.frustumPickingColor, cam.frustumColorIndex);
|
||||
|
||||
// drawing planet nodes
|
||||
let rn = this._renderedNodesInFrustum[cam.getCurrentFrustum()],
|
||||
let rn = quadTreeStrategy._renderedNodesInFrustum[cam.getCurrentFrustum()],
|
||||
sl = this._visibleTileLayerSlices;
|
||||
|
||||
let i = rn.length;
|
||||
@ -1860,8 +1616,8 @@ export class Planet extends RenderNode {
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._fadingOpaqueSegments.length; ++i) {
|
||||
this._fadingOpaqueSegments[i].depthRendering(sh, sl[0]);
|
||||
for (let i = 0; i < quadTreeStrategy._fadingOpaqueSegments.length; ++i) {
|
||||
quadTreeStrategy._fadingOpaqueSegments[i].depthRendering(sh, sl[0]);
|
||||
}
|
||||
|
||||
gl.enable(gl.BLEND);
|
||||
@ -1881,7 +1637,7 @@ export class Planet extends RenderNode {
|
||||
let j = group.length;
|
||||
while (j--) {
|
||||
let vi = group[j];
|
||||
if (vi._fading && vi._refreshFadingOpacity()) {
|
||||
if (vi._fading && vi._refreshFadingOpacity(this.quadTreeStrategy.minCurrZoom, this.quadTreeStrategy.maxCurrZoom)) {
|
||||
group.splice(j, 1);
|
||||
if (group.length === 0) {
|
||||
this._visibleVectorLayersByDepthOrder.splice(k, 1);
|
||||
@ -2103,11 +1859,11 @@ export class Planet extends RenderNode {
|
||||
}
|
||||
}
|
||||
|
||||
return this._viewExtent;
|
||||
return this.quadTreeStrategy._viewExtent;
|
||||
}
|
||||
|
||||
public getViewExtent(): Extent {
|
||||
return this._viewExtent;
|
||||
return this.quadTreeStrategy._viewExtent;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2154,7 +1910,7 @@ export class Planet extends RenderNode {
|
||||
*/
|
||||
public flyLonLat(
|
||||
lonlat: LonLat,
|
||||
params: IPlanetFlyCartesianParams = {}
|
||||
params: IPlanetFlyCartesianParams = {}
|
||||
) {
|
||||
this.camera.flyLonLat(lonlat, params);
|
||||
}
|
||||
@ -2187,7 +1943,7 @@ export class Planet extends RenderNode {
|
||||
}
|
||||
|
||||
public getEntityTerrainPoint(entity: Entity, res: Vec3) {
|
||||
let n = this._renderedNodes, i = n.length;
|
||||
let n = this.quadTreeStrategy._renderedNodes, i = n.length;
|
||||
while (i--) {
|
||||
if (n[i].segment.isEntityInside(entity)) {
|
||||
return n[i].segment.getEntityTerrainPoint(entity, res);
|
||||
@ -2222,7 +1978,7 @@ export class Planet extends RenderNode {
|
||||
public override onremove() {
|
||||
this.memClear();
|
||||
this.quadTreeStrategy.destroyBranches();
|
||||
this._renderedNodes = [];
|
||||
this.quadTreeStrategy.clearRenderedNodes();
|
||||
}
|
||||
|
||||
// function checkTerrainCollision(entity) {
|
||||
|
||||
@ -27,7 +27,7 @@ class SkyBox extends RenderNode {
|
||||
}
|
||||
|
||||
public override init() {
|
||||
this.renderer!.handler!.addProgram(shaders.skybox(), true);
|
||||
this.renderer!.handler!.addProgram(shaders.skybox());
|
||||
this.texture = this.renderer!.handler.loadCubeMapTexture(this.params);
|
||||
this._createBuffers();
|
||||
this.drawMode = this.renderer!.handler.gl!.TRIANGLES;
|
||||
|
||||
@ -24,7 +24,8 @@ import {Slice} from "./Slice";
|
||||
import {Ray} from "../math/Ray";
|
||||
import {Vec3} from "../math/Vec3";
|
||||
import type {IPlainSegmentWorkerData} from "../utils/PlainSegmentWorker";
|
||||
import {MAX_LAT, MIN_LAT, POLE} from "../mercator";
|
||||
import {MAX_LAT} from "../mercator";
|
||||
import {QuadTreeStrategy} from "../quadTree";
|
||||
|
||||
//Math.round(Math.abs(-pole - extent.southWest.lon) / (extent.northEast.lon - extent.southWest.lon));
|
||||
|
||||
@ -216,13 +217,13 @@ class Segment {
|
||||
public initialized: boolean;
|
||||
|
||||
/**
|
||||
* Normal map is allready made.
|
||||
* Normal map is already made.
|
||||
* @type {boolean}
|
||||
*/
|
||||
public normalMapReady: boolean;
|
||||
|
||||
/**
|
||||
* Terrain is allready applied flag.
|
||||
* Terrain is already applied flag.
|
||||
* @type {boolean}
|
||||
*/
|
||||
public terrainReady: boolean;
|
||||
@ -291,7 +292,9 @@ class Segment {
|
||||
|
||||
public _transitionTimestamp: number;
|
||||
|
||||
constructor(node: Node, planet: Planet, tileZoom: number, extent: Extent) {
|
||||
public quadTreeStrategy: QuadTreeStrategy
|
||||
|
||||
constructor(node: Node, quadTreeStrategy: QuadTreeStrategy, tileZoom: number, extent: Extent) {
|
||||
|
||||
this.isPole = false;
|
||||
|
||||
@ -301,9 +304,11 @@ class Segment {
|
||||
|
||||
this.node = node;
|
||||
|
||||
this.planet = planet;
|
||||
this.quadTreeStrategy = quadTreeStrategy;
|
||||
|
||||
this.handler = planet.renderer!.handler;
|
||||
this.planet = quadTreeStrategy.planet;
|
||||
|
||||
this.handler = quadTreeStrategy.planet.renderer!.handler;
|
||||
|
||||
this.bsphere = new Sphere();
|
||||
|
||||
@ -322,7 +327,7 @@ class Segment {
|
||||
|
||||
this._extentLonLat = new Extent();
|
||||
|
||||
this.gridSize = planet.terrain!.gridSizeByZoom[tileZoom];
|
||||
this.gridSize = this.planet.terrain!.gridSizeByZoom[tileZoom];
|
||||
|
||||
this.fileGridSize = 0;
|
||||
|
||||
@ -642,7 +647,7 @@ class Segment {
|
||||
|
||||
public equalize() {
|
||||
|
||||
// Equalization doesnt work correctly for gridSize equals 2
|
||||
// Equalization doesn't work correctly for gridSize equals 2
|
||||
if (this.tileZoom < 2 || this.gridSize < 2) {
|
||||
return;
|
||||
}
|
||||
@ -1352,7 +1357,7 @@ class Segment {
|
||||
public _addViewExtent() {
|
||||
const ext = this._extentLonLat;
|
||||
|
||||
let viewExt = this.planet._viewExtent;
|
||||
let viewExt = this.quadTreeStrategy._viewExtent;
|
||||
|
||||
if (ext.southWest.lon < viewExt.southWest.lon) {
|
||||
viewExt.southWest.lon = ext.southWest.lon;
|
||||
@ -1621,6 +1626,7 @@ class Segment {
|
||||
|
||||
const pm = this.materials;
|
||||
const p = this.planet;
|
||||
const qts = this.quadTreeStrategy;
|
||||
|
||||
let currHeight, li;
|
||||
if (layerSlice && layerSlice.length) {
|
||||
@ -1648,8 +1654,8 @@ class Segment {
|
||||
if (
|
||||
this.layerOverlap(li) &&
|
||||
((li._fading && li._fadingOpacity > 0.0) ||
|
||||
((li.minZoom >= p.minCurrZoom || li.maxZoom >= p.minCurrZoom) &&
|
||||
(li.minZoom <= p.maxCurrZoom || li.maxZoom <= p.maxCurrZoom)))
|
||||
((li.minZoom >= qts.minCurrZoom || li.maxZoom >= qts.minCurrZoom) &&
|
||||
(li.minZoom <= qts.maxCurrZoom || li.maxZoom <= qts.maxCurrZoom)))
|
||||
) {
|
||||
notEmpty = true;
|
||||
|
||||
@ -1660,7 +1666,7 @@ class Segment {
|
||||
}
|
||||
|
||||
if (!m.isReady) {
|
||||
this.planet._renderCompleted = false;
|
||||
qts._renderCompleted = false;
|
||||
}
|
||||
|
||||
slice.append(li, m);
|
||||
@ -1715,32 +1721,32 @@ class Segment {
|
||||
}
|
||||
}
|
||||
|
||||
public heightPickingRendering(sh: Program, layerSlice: Layer[]) {
|
||||
const gl = this.handler.gl!;
|
||||
const sha = sh.attributes;
|
||||
const shu = sh.uniforms;
|
||||
|
||||
// var pm = this.materials,
|
||||
// p = this.planet;
|
||||
|
||||
let currHeight;
|
||||
if (layerSlice && layerSlice.length) {
|
||||
currHeight = layerSlice[0]._height;
|
||||
} else {
|
||||
currHeight = 0;
|
||||
}
|
||||
|
||||
gl.uniform1f(shu.height, currHeight);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexPositionBufferHigh!);
|
||||
gl.vertexAttribPointer(sha.aVertexPositionHigh, this.vertexPositionBufferHigh!.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexPositionBufferLow!);
|
||||
gl.vertexAttribPointer(sha.aVertexPositionLow, this.vertexPositionBufferLow!.itemSize, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer!);
|
||||
gl.drawElements(gl.TRIANGLE_STRIP, this._indexBuffer!.numItems, gl.UNSIGNED_INT, 0);
|
||||
}
|
||||
// public heightPickingRendering(sh: Program, layerSlice: Layer[]) {
|
||||
// const gl = this.handler.gl!;
|
||||
// const sha = sh.attributes;
|
||||
// const shu = sh.uniforms;
|
||||
//
|
||||
// // var pm = this.materials,
|
||||
// // p = this.planet;
|
||||
//
|
||||
// let currHeight;
|
||||
// if (layerSlice && layerSlice.length) {
|
||||
// currHeight = layerSlice[0]._height;
|
||||
// } else {
|
||||
// currHeight = 0;
|
||||
// }
|
||||
//
|
||||
// gl.uniform1f(shu.height, currHeight);
|
||||
//
|
||||
// gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexPositionBufferHigh!);
|
||||
// gl.vertexAttribPointer(sha.aVertexPositionHigh, this.vertexPositionBufferHigh!.itemSize, gl.FLOAT, false, 0, 0);
|
||||
//
|
||||
// gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexPositionBufferLow!);
|
||||
// gl.vertexAttribPointer(sha.aVertexPositionLow, this.vertexPositionBufferLow!.itemSize, gl.FLOAT, false, 0, 0);
|
||||
//
|
||||
// gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer!);
|
||||
// gl.drawElements(gl.TRIANGLE_STRIP, this._indexBuffer!.numItems, gl.UNSIGNED_INT, 0);
|
||||
// }
|
||||
|
||||
public increaseTransitionOpacity() {
|
||||
//this._transitionOpacity += 0.01;
|
||||
@ -1754,8 +1760,8 @@ class Segment {
|
||||
while (i--) {
|
||||
let n = this.node._fadingNodes[i];
|
||||
if (n.segment) {
|
||||
if (n.segment._transitionOpacity > 0 && !this.planet._fadingNodes.has(n.__id)) {
|
||||
this.planet._fadingNodes.set(n.__id, n);
|
||||
if (n.segment._transitionOpacity > 0 && !this.quadTreeStrategy._fadingNodes.has(n.__id)) {
|
||||
this.quadTreeStrategy._fadingNodes.set(n.__id, n);
|
||||
n.segment._transitionOpacity = 2.0 - this._transitionOpacity;
|
||||
if (n.segment._transitionOpacity === 0) {
|
||||
this.node._fadingNodes.splice(i, 1);
|
||||
|
||||
@ -3,12 +3,12 @@ import {EPSG4326} from "../proj/EPSG4326";
|
||||
import {Extent} from "../Extent";
|
||||
import {Layer} from "../layer/Layer";
|
||||
import {Node} from "../quadTree/Node";
|
||||
import {Planet} from "../scene/Planet";
|
||||
import {getTileCellIndex, Segment, TILEGROUP_NORTH, TILEGROUP_SOUTH} from "./Segment";
|
||||
import {LonLat} from "../LonLat";
|
||||
import {Entity} from "../entity/Entity";
|
||||
import {PlanetCamera} from "../camera/PlanetCamera";
|
||||
import type {WebGLTextureExt} from "../webgl/Handler";
|
||||
import {QuadTreeStrategy} from "../quadTree";
|
||||
|
||||
const MAX_POLE_ZOOM = 7;
|
||||
export const POLE_PIECE_SIZE = (90.0 - mercator.MAX_LAT) / Math.pow(2, MAX_POLE_ZOOM);
|
||||
@ -19,8 +19,8 @@ export const POLE_PIECE_SIZE = (90.0 - mercator.MAX_LAT) / Math.pow(2, MAX_POLE_
|
||||
* @extends {Segment}
|
||||
*/
|
||||
class SegmentLonLat extends Segment {
|
||||
constructor(node: Node, planet: Planet, tileZoom: number, extent: Extent) {
|
||||
super(node, planet, tileZoom, extent);
|
||||
constructor(node: Node, quadTreeStrategy: QuadTreeStrategy, tileZoom: number, extent: Extent) {
|
||||
super(node, quadTreeStrategy, tileZoom, extent);
|
||||
|
||||
this._projection = EPSG4326;
|
||||
|
||||
@ -49,7 +49,7 @@ class SegmentLonLat extends Segment {
|
||||
}
|
||||
|
||||
protected _getMaxZoom() {
|
||||
let maxPoleZoom = 0;
|
||||
let maxPoleZoom: number;
|
||||
if (this._isNorth) {
|
||||
//north pole limits
|
||||
let Yz = Math.floor((90.0 - this._extent.northEast.lat) / POLE_PIECE_SIZE);
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
import {Extent} from "../Extent";
|
||||
import {Node} from "../quadTree/Node";
|
||||
import {Planet} from "../scene/Planet";
|
||||
import {SegmentLonLat} from "./SegmentLonLat";
|
||||
import {getTileCellIndex, TILEGROUP_COMMON} from "./Segment";
|
||||
import {equi} from "../proj/equi";
|
||||
import type {WebGLTextureExt} from "../webgl/Handler";
|
||||
import {QuadTreeStrategy} from "../quadTree";
|
||||
|
||||
const MAX_POLE_ZOOM = 5;
|
||||
export const POLE_PIECE_SIZE = 5 / Math.pow(2, MAX_POLE_ZOOM);
|
||||
|
||||
export class SegmentLonLatEqui extends SegmentLonLat {
|
||||
constructor(node: Node, planet: Planet, tileZoom: number, extent: Extent) {
|
||||
super(node, planet, tileZoom, extent);
|
||||
constructor(node: Node, quadTreeStrategy: QuadTreeStrategy, tileZoom: number, extent: Extent) {
|
||||
super(node, quadTreeStrategy, tileZoom, extent);
|
||||
this._projection = equi;
|
||||
this.isPole = false;
|
||||
this._tileGroup = TILEGROUP_COMMON;
|
||||
}
|
||||
|
||||
protected override _getMaxZoom(): number {
|
||||
let maxPoleZoom = 0;
|
||||
let maxPoleZoom: number;
|
||||
if (this._extent.northEast.lat > 85) {
|
||||
//north pole limits
|
||||
let Yz = Math.floor((90.0 - this._extent.northEast.lat) / POLE_PIECE_SIZE);
|
||||
|
||||
@ -38,8 +38,6 @@ type TileData = {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Use GlobusRgbTerrain
|
||||
* Class that loads segment elevation data, converts it to the array and passes it to the planet segment.
|
||||
* @class
|
||||
* @extends {GlobusTerrain}
|
||||
|
||||
@ -2,6 +2,7 @@ import {createEvents} from '../Events';
|
||||
import type {EventsHandler} from '../Events';
|
||||
import {Planet} from "../scene/Planet";
|
||||
import {Segment} from "../segment/Segment";
|
||||
import {QuadTreeStrategy} from "../quadTree";
|
||||
|
||||
type LoaderEventsList = ["loadend", "layerloadend"];
|
||||
|
||||
@ -30,8 +31,8 @@ interface Obj<T> {
|
||||
isIdle: boolean;
|
||||
isEqual: (obj: T) => boolean;
|
||||
events: EventsHandler<any>
|
||||
_planet: Planet | null;
|
||||
|
||||
_planet?: Planet | null;
|
||||
quadTreeStrategy?: QuadTreeStrategy | null;
|
||||
}
|
||||
|
||||
type QueryParams<T> = {
|
||||
@ -139,7 +140,7 @@ export class Loader<T extends Obj<T>> {
|
||||
}
|
||||
|
||||
protected _checkLoadend(request: RequestCounter<T>, sender: T) {
|
||||
if (request.counter === 0 && (!sender._planet || sender._planet._terrainCompletedActivated)) {
|
||||
if (request.counter === 0 && (!sender._planet || sender.quadTreeStrategy && sender.quadTreeStrategy._terrainCompletedActivated)) {
|
||||
sender.events.dispatch(sender.events.loadend, sender);
|
||||
this.events.dispatch(this.events.layerloadend, sender);
|
||||
request.__requestCounterFrame__ = 0;
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { DecoderModule } from "draco3d";
|
||||
import { Entity } from "../../entity";
|
||||
import { Quat } from "../../math/Quat";
|
||||
import { Vec3 } from "../../math/Vec3";
|
||||
import { Mat4, NumberArray16 } from "../../math/Mat4";
|
||||
import { Object3d } from "../../Object3d";
|
||||
import { Glb } from "./glbParser";
|
||||
import {DecoderModule} from "draco3d";
|
||||
import {Entity} from "../../entity";
|
||||
import {Quat} from "../../math/Quat";
|
||||
import {Vec3} from "../../math/Vec3";
|
||||
import {Mat4, NumberArray16} from "../../math/Mat4";
|
||||
import {Object3d} from "../../Object3d";
|
||||
import {Glb} from "./glbParser";
|
||||
import {
|
||||
Accessor,
|
||||
AccessorComponentType,
|
||||
@ -23,9 +23,11 @@ import {
|
||||
|
||||
export class Gltf {
|
||||
private static _dracoDecoderModule: DecoderModule | null = null;
|
||||
|
||||
public static connectDracoDecoderModule(decoder: any): void {
|
||||
Gltf._dracoDecoderModule = decoder;
|
||||
}
|
||||
|
||||
public static async loadGlb(url: string) {
|
||||
const data = await Glb.load(url);
|
||||
return new Gltf(data);
|
||||
@ -79,7 +81,7 @@ export class Gltf {
|
||||
|
||||
private _nodeToEntity(node: GltfNode, parent?: Entity): Entity {
|
||||
const entity = new Entity({
|
||||
name: `node_${node.name}`,
|
||||
name: node.name,
|
||||
cartesian: new Vec3(0, 0, 0),
|
||||
relativePosition: parent !== undefined,
|
||||
});
|
||||
@ -197,7 +199,7 @@ export class Gltf {
|
||||
const source =
|
||||
this.gltf.gltf.textures[
|
||||
material.pbrMetallicRoughness.baseColorTexture.index
|
||||
].source;
|
||||
].source;
|
||||
if (source !== undefined) {
|
||||
mat.baseColorTexture = {
|
||||
image: this._images[source],
|
||||
@ -209,12 +211,12 @@ export class Gltf {
|
||||
const source =
|
||||
this.gltf.gltf.textures[
|
||||
material.pbrMetallicRoughness.metallicRoughnessTexture.index
|
||||
].source;
|
||||
].source;
|
||||
if (source !== undefined) {
|
||||
mat.metallicRoughnessTexture = {
|
||||
image: this._images[source],
|
||||
texCoord:
|
||||
material.pbrMetallicRoughness.metallicRoughnessTexture.texCoord
|
||||
material.pbrMetallicRoughness.metallicRoughnessTexture.texCoord
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -344,7 +346,7 @@ export class Gltf {
|
||||
draco.destroy(decoder);
|
||||
|
||||
primitive = {
|
||||
name: `${meshData.name}_${material.name}_${index}`,
|
||||
name: `${meshData.name}/${material.name}/${index}`,
|
||||
vertices: attributes.POSITION,
|
||||
indices: indices,
|
||||
mode: primitiveData.mode ? primitiveData.mode : PrimitiveMode.triangles,
|
||||
@ -358,7 +360,7 @@ export class Gltf {
|
||||
? this.gltf.gltf.accessors[texcoordAccessorKey]
|
||||
: undefined;
|
||||
primitive = {
|
||||
name: `${meshData.name}_${material.name}_${index}`,
|
||||
name: `${meshData.name}/${material.name}/${index}`,
|
||||
indices: primitiveData.indices
|
||||
? Gltf._access(this.gltf.gltf.accessors[primitiveData.indices], this.gltf)
|
||||
: undefined,
|
||||
|
||||
@ -264,17 +264,15 @@ export class Framebuffer extends BaseFramebuffer {
|
||||
clientWaitAsync(gl, sync, 0).then(() => {
|
||||
this._skipFrame = false;
|
||||
gl.deleteSync(sync);
|
||||
|
||||
for (let i = 0; i < pb.length; i++) {
|
||||
let pbi = pb[i];
|
||||
if (pbi.data) {
|
||||
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, pbi.buffer);
|
||||
gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, pbi.data!);
|
||||
callback && callback(this);
|
||||
}
|
||||
}
|
||||
|
||||
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
|
||||
callback && callback(this);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -799,15 +799,15 @@ class Handler {
|
||||
* Adds shader program to the handler.
|
||||
* @public
|
||||
* @param {Program} program - Shader program.
|
||||
* @param {boolean} [notActivate] - If it's true program will not compile.
|
||||
* @param {boolean} [activate] - If false program will not compile.
|
||||
* @return {Program} -
|
||||
*/
|
||||
public addProgram(program: Program, notActivate: boolean = false): Program {
|
||||
public addProgram(program: Program, activate: boolean = false): Program {
|
||||
if (!this.programs[program.name]) {
|
||||
let sc = new ProgramController(this, program);
|
||||
this.programs[program.name] = sc;
|
||||
this._initProgramController(sc);
|
||||
if (notActivate) {
|
||||
if (!activate) {
|
||||
sc._activated = false;
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -1,15 +1,60 @@
|
||||
import { Extent } from "../src/Extent";
|
||||
import { LonLat } from "../src/LonLat";
|
||||
import { Planet } from "../src/scene/Planet";
|
||||
import { SegmentLonLat } from "../src/segment/SegmentLonLat";
|
||||
import { QuadTreeStrategy } from "../src/quadTree/QuadTreeStrategy";
|
||||
import { Node } from "../src/quadTree/Node";
|
||||
|
||||
const mockPlanet = () => {
|
||||
const planet = new Planet();
|
||||
planet.renderer = {};
|
||||
planet.terrain = { gridSizeByZoom: {} };
|
||||
planet.renderer = {
|
||||
handler: {
|
||||
gl: {
|
||||
createBuffer: vi.fn(),
|
||||
createTexture: vi.fn(),
|
||||
bindBuffer: vi.fn(),
|
||||
bufferData: vi.fn(),
|
||||
deleteBuffer: vi.fn(),
|
||||
deleteTexture: vi.fn()
|
||||
}
|
||||
}
|
||||
};
|
||||
planet.terrain = {
|
||||
gridSizeByZoom: {
|
||||
0: 256,
|
||||
1: 512,
|
||||
2: 1024
|
||||
}
|
||||
};
|
||||
planet.solidTextureOne = null;
|
||||
planet.solidTextureTwo = null;
|
||||
planet._createdNodesCount = 0;
|
||||
return planet;
|
||||
};
|
||||
|
||||
const mockQuadTreeStrategy = (planet) => {
|
||||
const strategy = new QuadTreeStrategy({ planet });
|
||||
return strategy;
|
||||
};
|
||||
|
||||
const mockNode = (quadTreeStrategy) => {
|
||||
const node = new Node(
|
||||
SegmentLonLat,
|
||||
quadTreeStrategy,
|
||||
0, // partId
|
||||
null, // parent
|
||||
0, // tileZoom
|
||||
new Extent(new LonLat(-180, -90), new LonLat(180, 90))
|
||||
);
|
||||
return node;
|
||||
};
|
||||
|
||||
test("Testing SegmentLonLat", () => {
|
||||
const segmentLonLat = new SegmentLonLat({}, mockPlanet(), {}, new Extent());
|
||||
const planet = mockPlanet();
|
||||
const quadTreeStrategy = mockQuadTreeStrategy(planet);
|
||||
const node = mockNode(quadTreeStrategy);
|
||||
const extent = new Extent(new LonLat(-180, -90), new LonLat(180, 90));
|
||||
|
||||
const segmentLonLat = new SegmentLonLat(node, quadTreeStrategy, 0, extent);
|
||||
expect(segmentLonLat).toBeTruthy();
|
||||
});
|
||||
|
||||
@ -33,7 +33,7 @@ export default function forceTerserPlugin({ filePath }) {
|
||||
if (result.code && result.map) {
|
||||
await Promise.all([
|
||||
writeFile(filePath, result.code, 'utf-8'),
|
||||
writeFile(mapPath, result.map, 'utf-8'),
|
||||
writeFile(mapPath, result.map, 'utf-8'),
|
||||
]);
|
||||
console.log(`✔ ${fileName} and ${mapFileName} regenerated with Terser`);
|
||||
} else {
|
||||
|
||||
@ -7,6 +7,7 @@ import glsl from 'vite-plugin-glsl';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
/**
|
||||
* @param {{ mode: 'development' | 'production' }} param0
|
||||
* @returns {import('vite').UserConfig}
|
||||
@ -31,10 +32,9 @@ export default function ({mode}: { mode: 'development' | 'production' }) {
|
||||
output: {
|
||||
entryFileNames: `og.[format].js`,
|
||||
assetFileNames: `[name][extname]`,
|
||||
sourcemapExcludeSources: true,
|
||||
sourcemapExcludeSources: !isDev,
|
||||
},
|
||||
plugins: [
|
||||
// doesn't work for esm modules
|
||||
plugins: !isDev ? [
|
||||
terser({
|
||||
compress: true,
|
||||
mangle: true,
|
||||
@ -42,12 +42,12 @@ export default function ({mode}: { mode: 'development' | 'production' }) {
|
||||
comments: false
|
||||
}
|
||||
})
|
||||
]
|
||||
] : [] // important no plugins for development mode
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
glsl({
|
||||
include: [ // Glob pattern, or array of glob patterns to import
|
||||
include: [
|
||||
'**/*.glsl', '**/*.wgsl',
|
||||
'**/*.vert', '**/*.frag',
|
||||
'**/*.vs', '**/*.fs'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user