You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
469 lines
12 KiB
JavaScript
469 lines
12 KiB
JavaScript
|
|
|
|
import {World} from "./world.js";
|
|
import {Debug} from "./debug.js";
|
|
import {logger} from "./log.js"
|
|
|
|
class Data
|
|
{
|
|
|
|
constructor(cfg)
|
|
{
|
|
this.cfg = cfg;
|
|
|
|
}
|
|
|
|
async readSceneList()
|
|
{
|
|
const req = new Request("/get_all_scene_desc");
|
|
let init = {
|
|
method: 'GET',
|
|
//body: JSON.stringify({"points": data})
|
|
};
|
|
// we defined the xhr
|
|
|
|
return fetch(req, init)
|
|
.then(response=>{
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}else{
|
|
return response.json();
|
|
}
|
|
})
|
|
.then(ret=>
|
|
{
|
|
console.log(ret);
|
|
this.sceneDescList = ret;
|
|
return ret;
|
|
})
|
|
.catch(reject=>{
|
|
console.log("error read scene list!");
|
|
});
|
|
}
|
|
|
|
async init(){
|
|
await this.readSceneList();
|
|
}
|
|
|
|
// multiple world support
|
|
// place world by a offset so they don't overlap
|
|
dbg = new Debug();
|
|
|
|
worldGap=1000.0;
|
|
worldList=[];
|
|
MaxWorldNumber=80;
|
|
createWorldIndex = 0; // this index shall not repeat, so it increases permanently
|
|
|
|
async getWorld(sceneName, frame, on_preload_finished){
|
|
// find in list
|
|
|
|
if (!this.meta[sceneName]){
|
|
await this.readSceneMetaData(sceneName)
|
|
}
|
|
|
|
if (!this.meta[sceneName])
|
|
{
|
|
logger.log("load scene failed", sceneName);
|
|
return null;
|
|
}
|
|
|
|
let world = this.worldList.find((w)=>{
|
|
return w.frameInfo.scene == sceneName && w.frameInfo.frame == frame;
|
|
})
|
|
if (world) // found!
|
|
return world;
|
|
|
|
|
|
world = this._createWorld(sceneName, frame, on_preload_finished);
|
|
|
|
return world;
|
|
};
|
|
|
|
_createWorld(sceneName, frame, on_preload_finished){
|
|
|
|
let [x,y,z] = this.allocateOffset();
|
|
console.log("create world",x,y,z);
|
|
let world = new World(this, sceneName, frame, [this.worldGap*x, this.worldGap*y, this.worldGap*z], on_preload_finished);
|
|
world.offsetIndex = [x,y,z];
|
|
this.createWorldIndex++;
|
|
this.worldList.push(world);
|
|
|
|
return world;
|
|
|
|
};
|
|
|
|
findWorld(sceneName, frameIndex){
|
|
let world = this.worldList.find((w)=>{
|
|
return w.frameInfo.scene == sceneName && w.frameInfo.frame_index == frameIndex;
|
|
})
|
|
if (world) // found!
|
|
return world;
|
|
else
|
|
return null;
|
|
};
|
|
|
|
offsetList = [[0,0,0]];
|
|
lastSeedOffset = [0,0,0];
|
|
offsetsAliveCount = 0;
|
|
allocateOffset()
|
|
{
|
|
|
|
// we need to make sure the first frame loaded in a scene
|
|
// got to locate in [0,0,0]
|
|
|
|
if (this.offsetsAliveCount == 0)
|
|
{
|
|
//reset offsets.
|
|
this.offsetList = [[0,0,0]];
|
|
this.lastSeedOffset = [0,0,0];
|
|
}
|
|
|
|
|
|
|
|
if (this.offsetList.length == 0)
|
|
{
|
|
let [x,y,z] = this.lastSeedOffset;
|
|
|
|
if (x == y)
|
|
{
|
|
x = x+1;
|
|
y = 0;
|
|
}
|
|
else
|
|
{
|
|
y = y+1;
|
|
}
|
|
|
|
this.lastSeedOffset = [x, y, 0];
|
|
|
|
this.offsetList.push([x,y,0]);
|
|
|
|
if (x != 0) this.offsetList.push([-x,y,0]);
|
|
if (y != 0) this.offsetList.push([x,-y,0]);
|
|
if (x * y != 0) this.offsetList.push([-x,-y,0]);
|
|
|
|
if (x != y) {
|
|
this.offsetList.push([y,x,0]);
|
|
|
|
if (y != 0) this.offsetList.push([-y,x,0]);
|
|
if (x != 0) this.offsetList.push([y,-x,0]);
|
|
if (x * y != 0) this.offsetList.push([-y,-x,0]);
|
|
}
|
|
}
|
|
|
|
let ret = this.offsetList.pop();
|
|
this.offsetsAliveCount++;
|
|
|
|
return ret;
|
|
};
|
|
|
|
returnOffset(offset)
|
|
{
|
|
this.offsetList.push(offset);
|
|
this.offsetsAliveCount--;
|
|
};
|
|
|
|
deleteDistantWorlds(world){
|
|
let currentWorldIndex = world.frameInfo.frame_index;
|
|
|
|
let disposable = (w)=>{
|
|
let distant = Math.abs(w.frameInfo.frame_index - currentWorldIndex)>this.MaxWorldNumber;
|
|
let active = w.everythingDone;
|
|
if (w.annotation.modified)
|
|
{
|
|
console.log("deleting world not saved. stop.");
|
|
}
|
|
|
|
return distant && !active && !w.annotation.modified;
|
|
}
|
|
|
|
let distantWorldList = this.worldList.filter(w=>disposable(w));
|
|
|
|
distantWorldList.forEach(w=>{
|
|
this.returnOffset(w.offsetIndex);
|
|
w.deleteAll();
|
|
});
|
|
|
|
|
|
this.worldList = this.worldList.filter(w=>!disposable(w));
|
|
|
|
};
|
|
|
|
deleteOtherWorldsExcept=function(keepScene){
|
|
// release resources if scene changed
|
|
this.worldList.forEach(w=>{
|
|
if (w.frameInfo.scene != keepScene){
|
|
this.returnOffset(w.offsetIndex);
|
|
w.deleteAll();
|
|
|
|
this.removeRefEgoPoseOfScene(w.frameInfo.scene);
|
|
}
|
|
})
|
|
this.worldList = this.worldList.filter(w=>w.frameInfo.scene==keepScene);
|
|
};
|
|
|
|
|
|
refEgoPose={};
|
|
getRefEgoPose(sceneName, currentPose)
|
|
{
|
|
if (this.refEgoPose[sceneName]){
|
|
return this.refEgoPose[sceneName];
|
|
}
|
|
else{
|
|
this.refEgoPose[sceneName] = currentPose;
|
|
return currentPose;
|
|
}
|
|
}
|
|
|
|
removeRefEgoPoseOfScene(sceneName)
|
|
{
|
|
if (this.refEgoPose[sceneName])
|
|
delete this.refEgoPose[sceneName];
|
|
}
|
|
|
|
forcePreloadScene(sceneName, currentWorld){
|
|
//this.deleteOtherWorldsExcept(sceneName);
|
|
let meta = currentWorld.sceneMeta;
|
|
|
|
let currentWorldIndex = currentWorld.frameInfo.frame_index;
|
|
let startIndex = Math.max(0, currentWorldIndex - this.MaxWorldNumber/2);
|
|
let endIndex = Math.min(meta.frames.length, startIndex + this.MaxWorldNumber);
|
|
|
|
this._doPreload(sceneName, startIndex, endIndex);
|
|
|
|
logger.log(`${endIndex - startIndex} frames created`);
|
|
}
|
|
|
|
preloadScene(sceneName, currentWorld){
|
|
|
|
// clean other scenes.
|
|
this.deleteOtherWorldsExcept(sceneName);
|
|
this.deleteDistantWorlds(currentWorld);
|
|
|
|
if (!this.cfg.enablePreload)
|
|
return;
|
|
|
|
this.forcePreloadScene(sceneName, currentWorld);
|
|
|
|
};
|
|
|
|
_doPreload(sceneName, startIndex, endIndex)
|
|
{
|
|
let meta = this.getMetaBySceneName(sceneName);
|
|
|
|
let numLoaded = 0;
|
|
let _need_create = (frame)=>{
|
|
let world = this.worldList.find((w)=>{
|
|
return w.frameInfo.scene == sceneName && w.frameInfo.frame == frame;
|
|
})
|
|
|
|
return !world;
|
|
}
|
|
|
|
let _do_create = (frame)=>{
|
|
this._createWorld(sceneName, frame);
|
|
numLoaded++;
|
|
};
|
|
|
|
let pendingFrames = meta.frames.slice(startIndex, endIndex).filter(_need_create);
|
|
|
|
logger.log(`preload ${meta.scene} ${pendingFrames}`);
|
|
// if (numLoaded > 0){
|
|
// meta.frames.slice(endIndex, Math.min(endIndex+5, meta.frames.length)).forEach(_do_create);
|
|
// meta.frames.slice(Math.max(0, startIndex-5), startIndex).forEach(_do_create);
|
|
// }
|
|
|
|
pendingFrames.forEach(_do_create);
|
|
}
|
|
|
|
|
|
reloadAllAnnotation=function(done){
|
|
this.worldList.forEach(w=>w.reloadAnnotation(done));
|
|
};
|
|
|
|
onAnnotationUpdatedByOthers(scene, frames){
|
|
frames.forEach(f=>{
|
|
let world = this.worldList.find(w=>(w.frameInfo.scene==scene && w.frameInfo.frame==f));
|
|
if (world)
|
|
world.annotation.reloadAnnotation();
|
|
})
|
|
};
|
|
|
|
webglScene = null;
|
|
set_webglScene=function(scene, mainScene){
|
|
this.webglScene = scene;
|
|
this.webglMainScene = mainScene;
|
|
};
|
|
|
|
scale_point_size(v){
|
|
this.cfg.point_size *= v;
|
|
// if (this.world){
|
|
// this.world.lidar.set_point_size(this.cfg.point_size);
|
|
// }
|
|
|
|
this.worldList.forEach(w=>{
|
|
w.lidar.set_point_size(this.cfg.point_size);
|
|
});
|
|
};
|
|
|
|
scale_point_brightness(v){
|
|
this.cfg.point_brightness *= v;
|
|
|
|
// if (this.world){
|
|
// this.world.lidar.recolor_all_points();
|
|
// }
|
|
|
|
this.worldList.forEach(w=>{
|
|
w.lidar.recolor_all_points();
|
|
})
|
|
};
|
|
|
|
set_box_opacity(opacity){
|
|
this.cfg.box_opacity = opacity;
|
|
|
|
this.worldList.forEach(w=>{
|
|
w.annotation.set_box_opacity(this.cfg.box_opacity);
|
|
});
|
|
};
|
|
|
|
toggle_background(){
|
|
this.cfg.show_background = !this.cfg.show_background;
|
|
|
|
if (this.cfg.show_background){
|
|
this.world.lidar.cancel_highlight();
|
|
}
|
|
else{
|
|
this.world.lidar.hide_background();
|
|
}
|
|
};
|
|
|
|
set_obj_color_scheme(scheme){
|
|
|
|
|
|
pointsGlobalConfig.color_obj = scheme;
|
|
|
|
// if (pointsGlobalConfig.color_obj != "no"){
|
|
// this.world.lidar.color_points();
|
|
// } else {
|
|
// this.world.lidar.set_points_color({
|
|
// x: this.cfg.point_brightness,
|
|
// y: this.cfg.point_brightness,
|
|
// z: this.cfg.point_brightness,
|
|
// });
|
|
// }
|
|
|
|
// this.world.lidar.update_points_color();
|
|
// this.world.annotation.color_boxes();
|
|
|
|
|
|
// toto: move to world
|
|
this.worldList.forEach(w=>{
|
|
if (pointsGlobalConfig.color_obj == "no")
|
|
{
|
|
w.lidar.color_points();
|
|
}
|
|
else
|
|
{
|
|
w.lidar.color_objects();
|
|
}
|
|
|
|
w.lidar.update_points_color();
|
|
|
|
w.annotation.color_boxes();
|
|
})
|
|
};
|
|
|
|
// active_camera_name = "";
|
|
|
|
// // return null means not changed.
|
|
// set_active_image(name){
|
|
// if (name === this.active_camera_name){
|
|
// return null;
|
|
// }
|
|
|
|
// this.active_camera_name = name;
|
|
// if (this.world){
|
|
// this.world.cameras.activate(name);
|
|
// }
|
|
// this.worldList.forEach(w=>w.cameras.activate(name));
|
|
|
|
// return name;
|
|
// };
|
|
|
|
world=null;
|
|
|
|
// this.future_world_buffer = [];
|
|
// this.put_world_into_buffer= function(world){
|
|
// this.future_world_buffer.push(world);
|
|
// };
|
|
|
|
// this.reset_world_buffer= function(){
|
|
// this.future_world_buffer=[];
|
|
// };
|
|
|
|
// this.activateMultiWorld=function(world, on_finished){
|
|
// world.activate(this.webglScene,
|
|
// null, //don't destroy old world
|
|
// on_finished);
|
|
// this.worldList.push(world);
|
|
// };
|
|
|
|
activate_world= function(world, on_finished, dontDestroyOldWorld){
|
|
|
|
if (dontDestroyOldWorld){
|
|
world.activate(this.webglScene, null, on_finished);
|
|
}
|
|
else{
|
|
var old_world = this.world; // current world, should we get current world later?
|
|
this.world = world; // swich when everything is ready. otherwise data.world is half-baked, causing mysterious problems.
|
|
|
|
world.activate(this.webglMainScene,
|
|
function(){
|
|
if (old_world)
|
|
old_world.unload();
|
|
},
|
|
on_finished);
|
|
}
|
|
};
|
|
|
|
|
|
meta = {}; //meta data
|
|
|
|
getMetaBySceneName = (sceneName)=>{
|
|
return this.meta[sceneName];
|
|
};
|
|
|
|
|
|
get_current_world_scene_meta(){
|
|
return this.getMetaBySceneName(this.world.frameInfo.scene);
|
|
};
|
|
|
|
|
|
readSceneMetaData(sceneName)
|
|
{
|
|
let self =this;
|
|
return new Promise(function(resolve, reject){
|
|
let xhr = new XMLHttpRequest();
|
|
|
|
xhr.onreadystatechange = function () {
|
|
if (this.readyState != 4)
|
|
return;
|
|
|
|
if (this.status == 200) {
|
|
let sceneMeta = JSON.parse(this.responseText);
|
|
self.meta[sceneName] = sceneMeta;
|
|
resolve(sceneMeta);
|
|
}
|
|
|
|
};
|
|
|
|
xhr.open('GET', `/scenemeta?scene=${sceneName}`, true);
|
|
xhr.send();
|
|
});
|
|
}
|
|
};
|
|
|
|
|
|
export {Data};
|
|
|