Skip to content

Commit

Permalink
Cleanup web proto viewer (#5750)
Browse files Browse the repository at this point in the history
* remove protos and test.html

* Fix devices scale

* solve todos

* Fix devices scale (#5751)

* Fix devices scale

* solve todos

* remove console.log

* modify colormap

* pose to update

* html
  • Loading branch information
Benjamin Délèze authored Jan 18, 2023
1 parent eaa04d3 commit 6883a31
Show file tree
Hide file tree
Showing 47 changed files with 193 additions and 109,092 deletions.
81 changes: 41 additions & 40 deletions resources/web/wwi/Animation.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,20 @@ export default class Animation {
if (this.data.frames.length > 1000) {
this.numberOfKeyFrames = Math.floor(this.data.frames.length / 1000);
for (let i = 0; i < this.numberOfKeyFrames; i++) {
const allPoses = new Map();
const allUpdates = new Map();
const allLabels = new Map();
for (let j = (i + 1) * this.keyFrameStepSize; j > i * this.keyFrameStepSize; j--) {
const poses = this.data.frames[j].poses;
if (poses) {
for (let k = 0; k < poses.length; k++) {
const currentIdFields = allPoses.has(poses[k].id) ? allPoses.get(poses[k].id) : new Map();
for (let field in poses[k]) {
const updates = this.data.frames[j].updates;
if (updates) {
for (let k = 0; k < updates.length; k++) {
const currentIdFields = allUpdates.has(updates[k].id) ? allUpdates.get(updates[k].id) : new Map();
for (let field in updates[k]) {
if (field === 'id' || currentIdFields.has(field))
continue;
else
currentIdFields.set(field, {'id': poses[k].id, [field]: poses[k][field]});
currentIdFields.set(field, {'id': updates[k].id, [field]: updates[k][field]});
}
allPoses.set(poses[k].id, currentIdFields);
allUpdates.set(updates[k].id, currentIdFields);
}
}

Expand All @@ -100,33 +100,34 @@ export default class Animation {
}

if (i === 0) {
const poses = this.data.frames[0].poses; // No need to check the labels because they are defined in the second frames.
if (poses) {
for (let j = 0; j < poses.length; j++) {
const currentIdFields = allPoses.has(poses[j].id) ? allPoses.get(poses[j].id) : new Map();
// No need to check the labels because they are defined in the second frames.
const updates = this.data.frames[0].updates;
if (updates) {
for (let j = 0; j < updates.length; j++) {
const currentIdFields = allUpdates.has(updates[j].id) ? allUpdates.get(updates[j].id) : new Map();

for (let field in poses[j]) {
for (let field in updates[j]) {
if (field === 'id' || currentIdFields.has(field))
continue;
else
currentIdFields.set(field, {'id': poses[j].id, [field]: poses[j][field]});
currentIdFields.set(field, {'id': updates[j].id, [field]: updates[j][field]});
}
allPoses.set(poses[j].id, currentIdFields);
allUpdates.set(updates[j].id, currentIdFields);
}
}
} else { // Check the previous keyFrame to get missing updates
const poses = this.#keyFrames.get(i - 1).poses;
for (let element of poses) {
const updates = this.#keyFrames.get(i - 1).updates;
for (let element of updates) {
const id = element[0];
const currentIdFields = allPoses.has(id) ? allPoses.get(id) : new Map();
const currentIdFields = allUpdates.has(id) ? allUpdates.get(id) : new Map();

for (let field of element[1]) {
if (currentIdFields.has(field[0])) // we want to update each field only once
continue;
else
currentIdFields.set(field[0], field[1]);
}
allPoses.set(id, currentIdFields);
allUpdates.set(id, currentIdFields);
}

const labels = this.#keyFrames.get(i - 1).labels;
Expand All @@ -137,10 +138,10 @@ export default class Animation {
}
}

this.#keyFrames.set(i, {poses: new Map(allPoses), labels: new Map(allLabels)});
this.#keyFrames.set(i, {updates: new Map(allUpdates), labels: new Map(allLabels)});
}
this.numberOfFields = new Map();
for (let [key, value] of this.#keyFrames.get(this.numberOfKeyFrames - 1).poses)
for (let [key, value] of this.#keyFrames.get(this.numberOfKeyFrames - 1).updates)
this.numberOfFields.set(key, value.size);
}

Expand Down Expand Up @@ -181,14 +182,14 @@ export default class Animation {

// lookback mechanism: search in history
if (this.step !== this.#previousStep + 1) {
let previousPoseStep;
let previousUpdateStep;
const closestKeyFrame = Math.floor(this.step / this.keyFrameStepSize) - 1;

let previousStepIsAKeyFrame = false;
if (this.step > this.#previousStep && this.#previousStep > (closestKeyFrame + 1) * this.keyFrameStepSize)
previousPoseStep = this.#previousStep;
previousUpdateStep = this.#previousStep;
else {
previousPoseStep = (closestKeyFrame + 1) * this.keyFrameStepSize;
previousUpdateStep = (closestKeyFrame + 1) * this.keyFrameStepSize;
if (this.#keyFrames.size > 0)
previousStepIsAKeyFrame = true;
}
Expand All @@ -197,19 +198,19 @@ export default class Animation {
const appliedFieldsByIds = new Map();
const appliedLabelsIds = new Set();

// We do not want to include the previousPoseStep in the loop as its updates are in the keyFrame.
// We do not want to include the previousUpdateStep in the loop as its updates are in the keyFrame.
// However, we need to include it if there is no keyFrames or if it is the step 0 as there is no keyFrame for it
if (previousStepIsAKeyFrame && previousPoseStep !== 0)
previousPoseStep++;
if (previousStepIsAKeyFrame && previousUpdateStep !== 0)
previousUpdateStep++;

// Iterate through each step until the nearest keyFrame is reached or all necessary updates have been applied.
// Go in decreasing order to minize the number of steps.
for (let i = this.step; i >= previousPoseStep; i--) {
if (this.data.frames[i].poses) {
for (let j = 0; j < this.data.frames[i].poses.length; j++) { // At each frame, apply all poses
const id = this.data.frames[i].poses[j].id;
for (let i = this.step; i >= previousUpdateStep; i--) {
if (this.data.frames[i].updates) {
for (let j = 0; j < this.data.frames[i].updates.length; j++) { // At each frame, apply all updates
const id = this.data.frames[i].updates[j].id;
if (!completeIds.has(id)) { // Try to apply some updates to a node only if it is missing some
for (let field in this.data.frames[i].poses[j]) {
for (let field in this.data.frames[i].updates[j]) {
if (!appliedFieldsByIds.has(id)) {
appliedFieldsByIds.set(id, new Set());
appliedFieldsByIds.get(id).add('id');
Expand All @@ -218,7 +219,7 @@ export default class Animation {
if (appliedFieldsByIds.get(id).has(field)) // we want to update each field only once
continue;
else {
this.#scene.applyPose({'id': id, [field]: this.data.frames[i].poses[j][field]});
this.#scene.applyUpdate({'id': id, [field]: this.data.frames[i].updates[j][field]});
appliedFieldsByIds.get(id).add(field);

if (typeof this.numberOfFields !== 'undefined' && appliedFieldsByIds.size === this.numberOfFields.get(id))
Expand All @@ -241,8 +242,8 @@ export default class Animation {
}

if (previousStepIsAKeyFrame && closestKeyFrame >= 0) { // Get the missing updates from the closest keyFrame
const poses = this.#keyFrames.get(closestKeyFrame).poses;
for (let element of poses) {
const updates = this.#keyFrames.get(closestKeyFrame).updates;
for (let element of updates) {
const id = element[0];
if (!completeIds.has(id)) { // Try to apply some updates to a node only if it is missing some
for (let field of element[1]) {
Expand All @@ -253,7 +254,7 @@ export default class Animation {
if (appliedFieldsByIds.get(id).has(field[0])) // we want to update each field only once
continue;
else {
this.#scene.applyPose(field[1]);
this.#scene.applyUpdate(field[1]);
appliedFieldsByIds.get(id).add(field[0]);
if (typeof this.numberOfFields !== 'undefined' && appliedFieldsByIds.size === this.numberOfFields.get(id))
completeIds.add(id);
Expand All @@ -271,10 +272,10 @@ export default class Animation {
}
}
} else {
if (this.data.frames[this.step].hasOwnProperty('poses')) {
const poses = this.data.frames[this.step].poses;
for (let p = 0; p < poses.length; p++)
this.#scene.applyPose(poses[p], undefined);
if (this.data.frames[this.step].hasOwnProperty('updates')) {
const updates = this.data.frames[this.step].updates;
for (let p = 0; p < updates.length; p++)
this.#scene.applyUpdate(updates[p], undefined);
WbWorld.instance.tracks.forEach(track => {
if (track.linearSpeed !== 0) {
track.animateMesh();
Expand Down
13 changes: 6 additions & 7 deletions resources/web/wwi/Parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,6 @@ export default class Parser {
setTimeout(() => { webots.currentView.progress.setProgressBar('none'); }, 300);
if (typeof callback === 'function')
callback();
console.log('World Instance', WbWorld.instance);
console.timeEnd('Loaded in: ');
});
}
Expand Down Expand Up @@ -1580,27 +1579,27 @@ export default class Parser {
for (let i = 0; i < imageTextures.length; i++) {
const imageTexture = imageTextures[i];
const role = getNodeAttribute(imageTexture, 'role', undefined);
if (role === 'baseColor') {
if (role === 'baseColorMap') {
baseColorMap = this.#parseImageTexture(imageTexture);
if (typeof baseColorMap !== 'undefined')
baseColorMap.role = 'baseColorMap';
} else if (role === 'roughness') {
} else if (role === 'roughnessMap') {
roughnessMap = this.#parseImageTexture(imageTexture);
if (typeof roughnessMap !== 'undefined')
roughnessMap.role = 'roughnessMap';
} else if (role === 'metalness') {
} else if (role === 'metalnessMap') {
metalnessMap = this.#parseImageTexture(imageTexture);
if (typeof metalnessMap !== 'undefined')
metalnessMap.role = 'metalnessMap';
} else if (role === 'normal') {
} else if (role === 'normalMap') {
normalMap = this.#parseImageTexture(imageTexture);
if (typeof normalMap !== 'undefined')
normalMap.role = 'normalMap';
} else if (role === 'occlusion') {
} else if (role === 'occlusionMap') {
occlusionMap = this.#parseImageTexture(imageTexture);
if (typeof occlusionMap !== 'undefined')
occlusionMap.role = 'occlusionMap';
} else if (role === 'emissiveColor') {
} else if (role === 'emissiveColorMap') {
emissiveColorMap = this.#parseImageTexture(imageTexture);
if (typeof emissiveColorMap !== 'undefined')
emissiveColorMap.role = 'emissiveColorMap';
Expand Down
9 changes: 1 addition & 8 deletions resources/web/wwi/ProtoManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,6 @@ export default class ProtoManager {
await this.proto.generateInterface();
this.proto.parseBody();
this.loadX3d();
// generate list of exposed parameters (that will be tied to interface elements)
for (const [parameterName, parameter] of this.proto.parameters) {
parameter._view = this.#view;
this.exposedParameters.set(parameterName, parameter); // TODO: change key to parameter id ?
}
});
}

Expand All @@ -45,7 +40,6 @@ export default class ProtoManager {
};
xmlhttp.send();
}).then(async text => {
console.log('Load PROTO from URL: ' + url);
const node = new Node(url, text);
await node.generateInterface();
node.parseBody();
Expand Down Expand Up @@ -133,7 +127,6 @@ export default class ProtoManager {
s += `${indent(2)}}\n`;
s += '}\n';

console.log(s);
return s;
}

Expand Down Expand Up @@ -180,7 +173,7 @@ export default class ProtoManager {
const imageTexture = xml.createElement('ImageTexture');
imageTexture.setAttribute('id', getAnId());
imageTexture.setAttribute('url', 'https://raw.githubusercontent.com/cyberbotics/webots/R2022b/projects/default/worlds/textures/grid.png');
imageTexture.setAttribute('role', 'baseColor');
imageTexture.setAttribute('role', 'baseColorMap');
appearance.appendChild(imageTexture);
const textureTransform = xml.createElement('TextureTransform');
textureTransform.setAttribute('id', getAnId());
Expand Down
4 changes: 2 additions & 2 deletions resources/web/wwi/WebotsView.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,11 @@ export default class WebotsView extends HTMLElement {
typeof this._view === 'undefined')
return;

let pose = {
let update = {
'id': nodeId,
[field]: value
};
this._view.x3dScene.applyPose(pose);
this._view.x3dScene.applyUpdate(update);
if (render)
this._view.x3dScene.render();
}
Expand Down
Loading

0 comments on commit 6883a31

Please sign in to comment.