Use mesh instance id to identify meshes.

This commit is contained in:
kovacsv 2021-10-26 13:15:56 +02:00
parent af5a0fef13
commit 6f9801010b
9 changed files with 135 additions and 116 deletions

View File

@ -19,13 +19,19 @@ OV.MeshInstanceId = class
OV.MeshInstance = class extends OV.Object3D
{
constructor (node, mesh)
constructor (id, node, mesh)
{
super ();
this.id = id;
this.node = node;
this.mesh = mesh;
}
GetId ()
{
return this.id;
}
VertexCount ()
{
return this.mesh.VertexCount ();

View File

@ -121,7 +121,8 @@ OV.Model = class extends OV.ModelObject3D
this.root.Enumerate ((node) => {
for (let meshIndex of node.GetMeshIndices ()) {
let mesh = this.GetMesh (meshIndex);
let meshInstance = new OV.MeshInstance (node, mesh);
let instanceId = new OV.MeshInstanceId (node.GetId (), meshIndex);
let meshInstance = new OV.MeshInstance (instanceId, node, mesh);
onMeshInstance (meshInstance);
}
});

View File

@ -1,3 +1,5 @@
OV.InvalidNodeId = -1;
OV.NodeIdGenerator = class
{
constructor ()

View File

@ -302,7 +302,7 @@ OV.ConvertModelToThreeObject = function (model, params, output, callbacks)
OV.RunTasksBatch (node.MeshIndexCount (), 100, {
runTask : (firstNodeMeshIndex, lastNodeMeshIndex, ready) => {
for (let nodeMeshIndex = firstNodeMeshIndex; nodeMeshIndex <= lastNodeMeshIndex; nodeMeshIndex++) {
let meshInstanceId = new OV.MeshInstanceId (node.GetId (), node.GetMeshIndex (nodeMeshIndex));
let meshInstanceId = new OV.MeshInstanceId (OV.InvalidNodeId, node.GetMeshIndex (nodeMeshIndex));
ConvertMesh (threeNode, model, meshInstanceId, modelThreeMaterials);
}
ready ();
@ -323,7 +323,7 @@ OV.ConvertModelToThreeObject = function (model, params, output, callbacks)
OV.RunTasksBatch (model.MeshCount (), 100, {
runTask : (firstIndex, lastIndex, ready) => {
for (let meshIndex = firstIndex; meshIndex <= lastIndex; meshIndex++) {
let meshInstanceId = new OV.MeshInstanceId (-1, meshIndex);
let meshInstanceId = new OV.MeshInstanceId (OV.InvalidNodeId, meshIndex);
ConvertMesh (threeObject, model, meshInstanceId, modelThreeMaterials);
}
ready ();

View File

@ -91,7 +91,7 @@ describe ('Model Utils', function () {
let transformation = new OV.Transformation (new OV.Matrix ().CreateTranslation (2.0, 0.0, 0.0));
let node = new OV.Node ();
node.SetTransformation (transformation);
let cubeInstance = new OV.MeshInstance (node, cube);
let cubeInstance = new OV.MeshInstance (new OV.MeshInstanceId (-1, -1), node, cube);
let cubeInstanceBounds = OV.GetBoundingBox (cubeInstance);
assert (OV.CoordIsEqual3D (cubeInstanceBounds.min, new OV.Coord3D (2.0, 0.0, 0.0)));
assert (OV.CoordIsEqual3D (cubeInstanceBounds.max, new OV.Coord3D (3.0, 1.0, 1.0)));

View File

@ -92,7 +92,7 @@ describe ('Quantities', function () {
const transformation = new OV.Transformation (new OV.Matrix ().CreateScale (2.0, 2.0, 2.0));
let node = new OV.Node ();
node.SetTransformation (transformation);
const meshInstance = new OV.MeshInstance (node, mesh);
const meshInstance = new OV.MeshInstance (new OV.MeshInstanceId (-1, -1), node, mesh);
assert (OV.IsEqual (OV.CalculateVolume (meshInstance), 8.0));
assert (OV.IsEqual (OV.CalculateSurfaceArea (meshInstance), 24.0));
});

View File

@ -6,10 +6,28 @@ OV.SelectionType =
OV.Selection = class
{
constructor (type, index)
constructor (type, data)
{
this.type = type;
this.index = index;
this.materialIndex = null;
this.meshInstanceId = null;
if (this.type === OV.SelectionType.Material) {
this.materialIndex = data;
} else if (this.type === OV.SelectionType.Mesh) {
this.meshInstanceId = data;
}
}
IsEqual (rhs)
{
if (this.type !== rhs.type) {
return false;
}
if (this.type === OV.SelectionType.Material) {
return this.materialIndex === rhs.materialIndex;
} else if (this.type === OV.SelectionType.Mesh) {
return this.meshInstanceId.IsEqual (rhs.meshInstanceId);
}
}
};
@ -46,15 +64,15 @@ OV.NavigatorInfoPanel = class
return OV.CalculatePopupPositionToElementBottomRight (button, contentDiv);
},
onHoverStart : (index) => {
const meshItem = usedByMeshes[index];
callbacks.onMeshHover (meshItem.index);
const meshData = usedByMeshes[index];
callbacks.onMeshHover (meshData.meshId);
},
onHoverStop : (index) => {
callbacks.onMeshHover (null);
},
onClick : (index) => {
const meshItem = usedByMeshes[index];
callbacks.onMeshSelect (meshItem.index);
const meshData = usedByMeshes[index];
callbacks.onMeshSelect (meshData.meshId);
}
});
});
@ -105,7 +123,7 @@ OV.NavigatorInfoPanel = class
if (this.popup !== null) {
this.popup.Hide ();
this.popup = null;
}
}
this.parentDiv.empty ();
}
};
@ -123,7 +141,7 @@ OV.Navigator = class
this.infoPanel = new OV.NavigatorInfoPanel (this.infoDiv);
this.navigatorItems = new OV.NavigatorItems ();
this.selection = null;
this.tempSelectedMeshIndex = null;
this.tempSelectedMeshId = null;
}
Init (callbacks)
@ -191,21 +209,19 @@ OV.Navigator = class
for (let meshIndex = 0; meshIndex < model.MeshCount (); meshIndex++) {
let mesh = model.GetMesh (meshIndex);
let meshName = OV.GetMeshName (mesh.GetName ());
let meshItem = new OV.MeshItem (meshName, meshIndex, {
onShowHide : (selectedMeshIndex) => {
this.ToggleMeshVisibility (selectedMeshIndex);
let meshInstanceId = new OV.MeshInstanceId (OV.InvalidNodeId, meshIndex);
let meshItem = new OV.MeshItem (meshName, meshInstanceId, {
onShowHide : (selectedMeshId) => {
this.ToggleMeshVisibility (selectedMeshId);
},
onIsolate : (selectedMeshIndex) => {
this.IsolateMesh (selectedMeshIndex);
},
onFitToWindow : (selectedMeshIndex) => {
this.FitMeshToWindow (selectedMeshIndex);
onFitToWindow : (selectedMeshId) => {
this.FitMeshToWindow (selectedMeshId);
},
onSelected : (selectedMeshIndex) => {
this.SetSelection (new OV.Selection (OV.SelectionType.Mesh, selectedMeshIndex));
onSelected : (selectedMeshId) => {
this.SetSelection (new OV.Selection (OV.SelectionType.Mesh, selectedMeshId));
}
});
this.navigatorItems.AddMeshItem (meshIndex, meshItem);
this.navigatorItems.AddMeshItem (meshInstanceId, meshItem);
meshesItem.AddChild (meshItem);
}
@ -218,9 +234,9 @@ OV.Navigator = class
return this.navigatorItems.MeshItemCount ();
}
IsMeshVisible (meshIndex)
IsMeshVisible (meshInstanceId)
{
let meshItem = this.navigatorItems.GetMeshItem (meshIndex);
let meshItem = this.navigatorItems.GetMeshItem (meshInstanceId);
return meshItem.IsVisible ();
}
@ -246,18 +262,18 @@ OV.Navigator = class
this.callbacks.updateMeshesVisibility ();
}
ToggleMeshVisibility (meshIndex)
ToggleMeshVisibility (meshInstanceId)
{
let meshItem = this.navigatorItems.GetMeshItem (meshIndex);
let meshItem = this.navigatorItems.GetMeshItem (meshInstanceId);
meshItem.SetVisible (!meshItem.IsVisible ());
this.callbacks.updateMeshesVisibility ();
}
IsMeshIsolated (meshIndex)
IsMeshIsolated (meshInstanceId)
{
let isIsolated = true;
this.navigatorItems.EnumerateMeshItems ((meshItem) => {
if (meshItem.GetMeshIndex () !== meshIndex && meshItem.IsVisible ()) {
if (!meshItem.GetMeshInstanceId ().IsEqual (meshInstanceId) && meshItem.IsVisible ()) {
isIsolated = false;
return false;
}
@ -266,11 +282,11 @@ OV.Navigator = class
return isIsolated;
}
IsolateMesh (meshIndex)
IsolateMesh (meshInstanceId)
{
let isIsolated = this.IsMeshIsolated (meshIndex);
let isIsolated = this.IsMeshIsolated (meshInstanceId);
this.navigatorItems.EnumerateMeshItems ((meshItem) => {
if (meshItem.GetMeshIndex () === meshIndex || isIsolated) {
if (meshItem.GetMeshInstanceId ().IsEqual (meshInstanceId) || isIsolated) {
meshItem.SetVisible (true);
} else {
meshItem.SetVisible (false);
@ -280,21 +296,15 @@ OV.Navigator = class
this.callbacks.updateMeshesVisibility ();
}
GetSelectedMeshIndex ()
GetSelectedMeshId ()
{
if (this.tempSelectedMeshIndex !== null) {
return this.tempSelectedMeshIndex;
if (this.tempSelectedMeshId !== null) {
return this.tempSelectedMeshId;
}
if (this.selection === null || this.selection.type !== OV.SelectionType.Mesh) {
return null;
}
return this.selection.index;
}
SetTempSelectedMeshIndex (tempSelectedMeshIndex)
{
this.tempSelectedMeshIndex = tempSelectedMeshIndex;
this.callbacks.updateMeshesSelection ();
return this.selection.meshInstanceId;
}
SetSelection (selection)
@ -302,10 +312,10 @@ OV.Navigator = class
function SetEntitySelection (obj, selection, select)
{
if (selection.type === OV.SelectionType.Material) {
obj.navigatorItems.GetMaterialItem (selection.index).SetSelected (select);
obj.navigatorItems.GetMaterialItem (selection.materialIndex).SetSelected (select);
} else if (selection.type === OV.SelectionType.Mesh) {
obj.navigatorItems.GetMeshItem (selection.index).SetSelected (select);
}
obj.navigatorItems.GetMeshItem (selection.meshInstanceId).SetSelected (select);
}
}
function SetCurrentSelection (obj, selection)
@ -320,10 +330,10 @@ OV.Navigator = class
}
SetCurrentSelection (this, selection);
this.tempSelectedMeshIndex = null;
this.tempSelectedMeshId = null;
if (this.selection !== null) {
if (oldSelection !== null && this.selection.type === oldSelection.type && this.selection.index === oldSelection.index) {
if (oldSelection !== null && oldSelection.IsEqual (this.selection)) {
SetEntitySelection (this, this.selection, false);
SetCurrentSelection (this, null);
} else {
@ -334,9 +344,9 @@ OV.Navigator = class
this.callbacks.updateMeshesSelection ();
}
FitMeshToWindow (meshIndex)
FitMeshToWindow (meshInstanceId)
{
this.callbacks.fitMeshToWindow (meshIndex);
this.callbacks.fitMeshToWindow (meshInstanceId);
}
UpdateInfoPanel ()
@ -351,29 +361,30 @@ OV.Navigator = class
this.callbacks.onModelSelected ();
} else {
if (this.selection.type === OV.SelectionType.Material) {
let usedByMeshes = this.callbacks.getMeshesForMaterial (this.selection.index);
let usedByMeshes = this.callbacks.getMeshesForMaterial (this.selection.materialIndex);
this.infoPanel.FillWithMaterialInfo (usedByMeshes, {
onMeshHover : (meshIndex) => {
this.SetTempSelectedMeshIndex (meshIndex);
onMeshHover : (meshInstanceId) => {
this.tempSelectedMeshId = meshInstanceId;
this.callbacks.updateMeshesSelection ();
},
onMeshSelect : (meshIndex) => {
this.SetSelection (new OV.Selection (OV.SelectionType.Mesh, meshIndex));
onMeshSelect : (meshInstanceId) => {
this.SetSelection (new OV.Selection (OV.SelectionType.Mesh, meshInstanceId));
}
});
this.callbacks.onMaterialSelected (this.selection.index);
this.callbacks.onMaterialSelected (this.selection.materialIndex);
} else if (this.selection.type === OV.SelectionType.Mesh) {
let usedMaterials = this.callbacks.getMaterialsForMesh (this.selection.index);
let usedMaterials = this.callbacks.getMaterialsForMesh (this.selection.meshInstanceId);
this.infoPanel.FillWithModelInfo (usedMaterials, {
onMaterialSelect : (materialIndex) => {
this.SetSelection (new OV.Selection (OV.SelectionType.Material, materialIndex));
}
});
this.callbacks.onMeshSelected (this.selection.index);
this.callbacks.onMeshSelected (this.selection.meshInstanceId);
}
}
this.Resize ();
}
Clear ()
{
this.titleDiv.empty ();

View File

@ -1,44 +1,44 @@
OV.MaterialItem = class extends OV.TreeViewButtonItem
{
constructor (name, originalIndex, callbacks)
constructor (name, materialIndex, callbacks)
{
super (name);
this.originalIndex = originalIndex;
this.materialIndex = materialIndex;
this.OnNameClick (() => {
callbacks.onSelected (this.originalIndex);
callbacks.onSelected (this.materialIndex);
});
}
};
OV.MeshItem = class extends OV.TreeViewButtonItem
{
constructor (name, originalIndex, callbacks)
constructor (name, meshInstanceId, callbacks)
{
super (name);
this.originalIndex = originalIndex;
this.meshInstanceId = meshInstanceId;
this.visible = true;
this.fitToWindowButton = new OV.TreeViewButton ('fit');
this.fitToWindowButton.OnClick (() => {
callbacks.onFitToWindow (this.originalIndex);
callbacks.onFitToWindow (this.meshInstanceId);
});
this.AddButton (this.fitToWindowButton);
this.showHideButton = new OV.TreeViewButton ('visible');
this.showHideButton.OnClick ((ev) => {
callbacks.onShowHide (this.originalIndex);
callbacks.onShowHide (this.meshInstanceId);
});
this.AddButton (this.showHideButton);
this.OnNameClick (() => {
callbacks.onSelected (this.originalIndex);
});
callbacks.onSelected (this.meshInstanceId);
});
}
GetMeshIndex ()
GetMeshInstanceId ()
{
return this.originalIndex;
return this.meshInstanceId;
}
IsVisible ()
@ -62,7 +62,7 @@ OV.NavigatorItems = class
constructor ()
{
this.materialIndexToItem = {};
this.meshIndexToItem = {};
this.meshInstanceIdToItem = {};
}
MaterialItemCount ()
@ -82,22 +82,22 @@ OV.NavigatorItems = class
MeshItemCount ()
{
return Object.keys (this.meshIndexToItem).length;
return Object.keys (this.meshInstanceIdToItem).length;
}
GetMeshItem (meshIndex)
GetMeshItem (meshInstanceId)
{
return this.meshIndexToItem[meshIndex];
return this.meshInstanceIdToItem[meshInstanceId.GetKey ()];
}
AddMeshItem (meshIndex, meshItem)
AddMeshItem (meshInstanceId, meshItem)
{
this.meshIndexToItem[meshIndex] = meshItem;
this.meshInstanceIdToItem[meshInstanceId.GetKey ()] = meshItem;
}
EnumerateMeshItems (processor)
{
for (const meshItem of Object.values (this.meshIndexToItem)) {
for (const meshItem of Object.values (this.meshInstanceIdToItem)) {
if (!processor (meshItem)) {
break;
}
@ -106,7 +106,7 @@ OV.NavigatorItems = class
Clear ()
{
this.materialItems = {};
this.meshItems = {};
this.materialIndexToItem = {};
this.meshInstanceIdToItem = {};
}
};

View File

@ -71,10 +71,10 @@ OV.Website = class
}
safetyMargin = 1;
}
let contentWidth = windowWidth - navigatorWidth - sidebarWidth - safetyMargin;
let contentHeight = windowHeight - headerHeight - safetyMargin;
this.parameters.navigatorDiv.outerHeight (contentHeight, true);
this.parameters.sidebarDiv.outerHeight (contentHeight, true);
this.parameters.introDiv.outerHeight (contentHeight, true);
@ -96,7 +96,7 @@ OV.Website = class
let root = document.querySelector (':root');
root.style.setProperty ('--ov_only_on_model_display', show ? 'inherit' : 'none');
}
if (uiState === OV.WebsiteUIState.Intro) {
this.parameters.introDiv.show ();
this.parameters.mainDiv.hide ();
@ -130,7 +130,7 @@ OV.Website = class
}
this.sidebar.HidePopups ();
}
OnModelFinished (importResult, threeObject)
{
this.model = importResult.model;
@ -148,7 +148,7 @@ OV.Website = class
if (meshUserData === null) {
this.navigator.SetSelection (null);
} else {
this.navigator.SetSelection (new OV.Selection (OV.SelectionType.Mesh, meshUserData.originalMeshId.meshIndex));
this.navigator.SetSelection (new OV.Selection (OV.SelectionType.Mesh, meshUserData.originalMeshId));
}
}
}
@ -175,28 +175,27 @@ OV.Website = class
});
}
} else {
let meshIndex = meshUserData.originalMeshId.meshIndex;
items.push ({
name : 'Hide mesh',
icon : 'hidden',
onClick : () => {
this.navigator.ToggleMeshVisibility (meshIndex);
this.navigator.ToggleMeshVisibility (meshUserData.originalMeshId);
}
});
items.push ({
name : 'Fit mesh to window',
icon : 'fit',
onClick : () => {
this.navigator.FitMeshToWindow (meshIndex);
this.navigator.FitMeshToWindow (meshUserData.originalMeshId);
}
});
if (this.navigator.MeshItemCount () > 1) {
let isMeshIsolated = this.navigator.IsMeshIsolated (meshIndex);
let isMeshIsolated = this.navigator.IsMeshIsolated (meshUserData.originalMeshId);
items.push ({
name : isMeshIsolated ? 'Remove isolation' : 'Isolate mesh',
icon : isMeshIsolated ? 'deisolate' : 'isolate',
onClick : () => {
this.navigator.IsolateMesh (meshIndex);
this.navigator.IsolateMesh (meshUserData.originalMeshId);
}
});
}
@ -242,7 +241,7 @@ OV.Website = class
{
let animation = !onLoad;
let boundingSphere = this.viewer.GetBoundingSphere ((meshUserData) => {
return this.navigator.IsMeshVisible (meshUserData.originalMeshId.meshIndex);
return this.navigator.IsMeshVisible (meshUserData.originalMeshId);
});
if (onLoad) {
this.viewer.AdjustClippingPlanesToSphere (boundingSphere);
@ -250,31 +249,31 @@ OV.Website = class
this.viewer.FitSphereToWindow (boundingSphere, animation);
}
FitMeshToWindow (meshIndex)
FitMeshToWindow (meshInstanceId)
{
let boundingSphere = this.viewer.GetBoundingSphere ((meshUserData) => {
return meshUserData.originalMeshId.meshIndex === meshIndex;
});
return meshUserData.originalMeshId.IsEqual (meshInstanceId);
});
this.viewer.FitSphereToWindow (boundingSphere, true);
}
UpdateMeshesVisibility ()
{
this.viewer.SetMeshesVisibility ((meshUserData) => {
return this.navigator.IsMeshVisible (meshUserData.originalMeshId.meshIndex);
return this.navigator.IsMeshVisible (meshUserData.originalMeshId);
});
}
UpdateMeshesSelection ()
{
let selectedMeshIndex = this.navigator.GetSelectedMeshIndex ();
let selectedMeshId = this.navigator.GetSelectedMeshId ();
this.viewer.SetMeshesHighlight (this.highlightMaterial, (meshUserData) => {
if (meshUserData.originalMeshId.meshIndex === selectedMeshIndex) {
if (selectedMeshId !== null && meshUserData.originalMeshId.IsEqual (selectedMeshId)) {
return true;
}
return false;
});
}
}
LoadModelFromUrlList (urls, settings)
{
@ -320,7 +319,7 @@ OV.Website = class
if (this.modelLoader.defaultMaterial !== null) {
OV.ReplaceDefaultMaterialColor (this.model, this.settings.defaultColor);
this.modelLoader.ReplaceDefaultMaterialColor (this.settings.defaultColor);
}
}
if (this.settingsPanel !== null) {
this.settingsPanel.UpdateSettings (this.settings);
}
@ -537,7 +536,7 @@ OV.Website = class
UpdateSidebarButtons (sidebar, sidebarPanels);
cookieHandler.SetBoolVal ('ov_show_sidebar', sidebar.IsVisible ());
}
function ToggleSidebar (sidebar, cookieHandler, sidebarPanels, panelId)
{
if (sidebar.GetVisiblePanelId () !== panelId) {
@ -564,7 +563,7 @@ OV.Website = class
image : 'settings',
title : 'Settings panel',
button : null
}
}
];
for (let id = 0; id < sidebarPanels.length; id++) {
@ -613,11 +612,11 @@ OV.Website = class
InitNavigator ()
{
function GetMeshUserData (viewer, meshIndex)
function GetMeshUserData (viewer, meshInstanceId)
{
let userData = null;
viewer.EnumerateMeshesUserData ((meshUserData) => {
if (meshUserData.originalMeshId.meshIndex === meshIndex) {
if (meshUserData.originalMeshId.IsEqual (meshInstanceId)) {
userData = meshUserData;
}
});
@ -631,7 +630,7 @@ OV.Website = class
if (meshUserData.originalMaterials.indexOf (materialIndex) !== -1) {
const mesh = model.GetMesh (meshUserData.originalMeshId.meshIndex);
usedByMeshes.push ({
index : meshUserData.originalMeshId.meshIndex,
meshId : meshUserData.originalMeshId,
name : mesh.GetName ()
});
}
@ -649,20 +648,20 @@ OV.Website = class
};
}
function GetMaterialsForMesh (viewer, model, meshIndex)
function GetMaterialsForMesh (viewer, model, meshInstanceId)
{
let usedMaterials = [];
let userData = GetMeshUserData (viewer, meshIndex);
let userData = GetMeshUserData (viewer, meshInstanceId);
for (let i = 0; i < userData.originalMaterials.length; i++) {
const materialIndex = userData.originalMaterials[i];
usedMaterials.push (GetMaterialReferenceInfo (model, materialIndex));
usedMaterials.push (GetMaterialReferenceInfo (model, materialIndex));
}
usedMaterials.sort ((a, b) => {
return a.index - b.index;
});
});
return usedMaterials;
}
function GetMaterialsForModel (model)
{
let usedMaterials = [];
@ -682,14 +681,14 @@ OV.Website = class
updateMeshesSelection : () => {
this.UpdateMeshesSelection ();
},
fitMeshToWindow : (meshIndex) => {
this.FitMeshToWindow (meshIndex);
fitMeshToWindow : (meshInstanceId) => {
this.FitMeshToWindow (meshInstanceId);
},
getMeshesForMaterial : (materialIndex) => {
return GetMeshesForMaterial (this.viewer, this.model, materialIndex);
},
getMaterialsForMesh : (meshIndex) => {
return GetMaterialsForMesh (this.viewer, this.model, meshIndex);
getMaterialsForMesh : (meshInstanceId) => {
return GetMaterialsForMesh (this.viewer, this.model, meshInstanceId);
},
getMaterialsForModel : () => {
return GetMaterialsForModel (this.model);
@ -697,8 +696,8 @@ OV.Website = class
onModelSelected : () => {
this.detailsPanel.AddObject3DProperties (this.model);
},
onMeshSelected : (meshIndex) => {
this.detailsPanel.AddObject3DProperties (this.model.GetMesh (meshIndex));
onMeshSelected : (meshInstanceId) => {
this.detailsPanel.AddObject3DProperties (this.model.GetMesh (meshInstanceId.meshIndex));
},
onMaterialSelected : (materialIndex) => {
this.detailsPanel.AddMaterialProperties (this.model.GetMaterial (materialIndex));