Implement polygon offset if the model contains lines.

This commit is contained in:
kovacsv 2023-10-23 11:40:18 +02:00
parent 0f3e42be4b
commit 4f0336c268
12 changed files with 240 additions and 99 deletions

View File

@ -54,7 +54,7 @@ import { MeshInstanceId, MeshInstance } from './model/meshinstance.js';
import { IsEmptyMesh, CalculateTriangleNormal, TransformMesh, FlipMeshTrianglesOrientation } from './model/meshutils.js';
import { Model } from './model/model.js';
import { FinalizeModel, CheckModel } from './model/modelfinalization.js';
import { IsModelEmpty, GetBoundingBox, GetTopology, IsTwoManifold, HasDefaultMaterial, ReplaceDefaultMaterialColor } from './model/modelutils.js';
import { IsModelEmpty, GetBoundingBox, GetTopology, IsTwoManifold, HasDefaultMaterial, ReplaceDefaultMaterialsColor } from './model/modelutils.js';
import { Node } from './model/node.js';
import { Object3D, ModelObject3D } from './model/object.js';
import { Property, PropertyGroup, PropertyToString, PropertyType } from './model/property.js';
@ -63,9 +63,9 @@ import { TopologyVertex, TopologyEdge, TopologyTriangleEdge, TopologyTriangle, T
import { Triangle } from './model/triangle.js';
import { Unit } from './model/unit.js';
import { ParameterListBuilder, ParameterListParser, CreateUrlBuilder, CreateUrlParser, CreateModelUrlParameters, ParameterConverter } from './parameters/parameterlist.js';
import { ModelToThreeConversionParams, ModelToThreeConversionOutput, ThreeConversionStateHandler, ThreeNodeTree, ThreeMaterialHandler, ThreeMeshMaterialHandler, ConvertModelToThreeObject } from './threejs/threeconverter.js';
import { ModelToThreeConversionParams, ModelToThreeConversionOutput, ThreeConversionStateHandler, ThreeNodeTree, ThreeMaterialHandler, ThreeMeshMaterialHandler, ConvertModelToThreeObject, MaterialGeometryType } from './threejs/threeconverter.js';
import { ThreeModelLoader } from './threejs/threemodelloader.js';
import { ThreeColorConverter, ThreeLinearToSRGBColorConverter, ThreeSRGBToLinearColorConverter, HasHighpDriverIssue, GetShadingType, ConvertThreeColorToColor, ConvertColorToThreeColor, ConvertThreeGeometryToMesh, DisposeThreeObjects, ShadingType } from './threejs/threeutils.js';
import { ThreeColorConverter, ThreeLinearToSRGBColorConverter, ThreeSRGBToLinearColorConverter, HasHighpDriverIssue, GetShadingType, ConvertThreeColorToColor, ConvertColorToThreeColor, ConvertThreeGeometryToMesh, CreateHighlightMaterial, CreateHighlightMaterials, DisposeThreeObjects, ShadingType } from './threejs/threeutils.js';
import { Camera, CameraIsEqual3D, NavigationMode, ProjectionMode } from './viewer/camera.js';
import { GetIntegerFromStyle, GetDomElementExternalWidth, GetDomElementExternalHeight, GetDomElementInnerDimensions, GetDomElementClientCoordinates, CreateDomElement, AddDomElement, AddDiv, ClearDomElement, InsertDomElementBefore, InsertDomElementAfter, ShowDomElement, IsDomElementVisible, SetDomElementWidth, SetDomElementHeight, GetDomElementOuterWidth, GetDomElementOuterHeight, SetDomElementOuterWidth, SetDomElementOuterHeight, CreateDiv } from './viewer/domutils.js';
import { EmbeddedViewer, Init3DViewerFromUrlList, Init3DViewerFromFileList, Init3DViewerElements } from './viewer/embeddedviewer.js';
@ -254,7 +254,7 @@ export {
GetTopology,
IsTwoManifold,
HasDefaultMaterial,
ReplaceDefaultMaterialColor,
ReplaceDefaultMaterialsColor,
Node,
Object3D,
ModelObject3D,
@ -286,6 +286,7 @@ export {
ThreeMaterialHandler,
ThreeMeshMaterialHandler,
ConvertModelToThreeObject,
MaterialGeometryType,
ThreeModelLoader,
ThreeColorConverter,
ThreeLinearToSRGBColorConverter,
@ -295,6 +296,8 @@ export {
ConvertThreeColorToColor,
ConvertColorToThreeColor,
ConvertThreeGeometryToMesh,
CreateHighlightMaterial,
CreateHighlightMaterials,
DisposeThreeObjects,
ShadingType,
Camera,

View File

@ -106,7 +106,7 @@ export function HasDefaultMaterial (model)
return false;
}
export function ReplaceDefaultMaterialColor (model, color)
export function ReplaceDefaultMaterialsColor (model, color)
{
for (let i = 0; i < model.MaterialCount (); i++) {
let material = model.GetMaterial (i);

View File

@ -8,6 +8,12 @@ import { ConvertColorToThreeColor, GetShadingType, ShadingType } from './threeut
import * as THREE from 'three';
export const MaterialGeometryType =
{
Line : 1,
Face : 2
};
export class ModelToThreeConversionParams
{
constructor ()
@ -20,7 +26,7 @@ export class ModelToThreeConversionOutput
{
constructor ()
{
this.defaultMaterial = null;
this.defaultMaterials = [];
this.objectUrls = [];
}
}
@ -97,12 +103,6 @@ export class ThreeNodeTree
}
}
export const MaterialGeometryType =
{
Line : 1,
Face : 2
};
export class ThreeMaterialHandler
{
constructor (model, stateHandler, conversionParams, conversionOutput)
@ -205,7 +205,7 @@ export class ThreeMaterialHandler
});
if (material.isDefault) {
this.conversionOutput.defaultMaterial = threeMaterial;
this.conversionOutput.defaultMaterials.push (threeMaterial);
}
return threeMaterial;
@ -226,7 +226,7 @@ export class ThreeMaterialHandler
let threeMaterial = new THREE.LineBasicMaterial (materialParams);
if (material.isDefault) {
this.conversionOutput.defaultMaterial = threeMaterial;
this.conversionOutput.defaultMaterials.push (threeMaterial);
}
return threeMaterial;

View File

@ -12,7 +12,7 @@ export class ThreeModelLoader
{
this.importer = new Importer ();
this.inProgress = false;
this.defaultMaterial = null;
this.defaultMaterials = null;
this.objectUrls = null;
this.hasHighpDriverIssue = HasHighpDriverIssue ();
}
@ -60,7 +60,7 @@ export class ThreeModelLoader
callbacks.onTextureLoaded ();
},
onModelLoaded : (threeObject) => {
this.defaultMaterial = output.defaultMaterial;
this.defaultMaterials = output.defaultMaterials;
this.objectUrls = output.objectUrls;
if (importResult.upVector === Direction.X) {
let rotation = new THREE.Quaternion ().setFromAxisAngle (new THREE.Vector3 (0.0, 0.0, 1.0), Math.PI / 2.0);
@ -86,15 +86,19 @@ export class ThreeModelLoader
return this.importer;
}
GetDefaultMaterial ()
GetDefaultMaterials ()
{
return this.defaultMaterial;
return this.defaultMaterials;
}
ReplaceDefaultMaterialColor (defaultColor)
ReplaceDefaultMaterialsColor (defaultColor)
{
if (this.defaultMaterial !== null && !this.defaultMaterial.vertexColors) {
this.defaultMaterial.color = ConvertColorToThreeColor (defaultColor);
if (this.defaultMaterials !== null) {
for (let defaultMaterial of this.defaultMaterials) {
if (!defaultMaterial.vertexColors) {
defaultMaterial.color = ConvertColorToThreeColor (defaultColor);
}
}
}
}

View File

@ -210,6 +210,48 @@ export function ConvertThreeGeometryToMesh (threeGeometry, materialIndex, colorC
return mesh;
}
export function CreateHighlightMaterial (originalMaterial, highlightColor, withPolygonOffset)
{
let material = null;
if (originalMaterial.type === 'MeshPhongMaterial') {
material = new THREE.MeshPhongMaterial ({
color : ConvertColorToThreeColor (highlightColor),
side : THREE.DoubleSide
});
} else if (originalMaterial.type === 'MeshStandardMaterial') {
material = new THREE.MeshStandardMaterial ({
color : ConvertColorToThreeColor (highlightColor),
side : THREE.DoubleSide
});
} else if (originalMaterial.type === 'LineBasicMaterial') {
material = new THREE.LineBasicMaterial ({
color : ConvertColorToThreeColor (highlightColor)
});
}
if (material !== null && withPolygonOffset) {
material.polygonOffset = true;
material.polygonOffsetUnit = 1;
material.polygonOffsetFactor = 1;
}
return material;
}
export function CreateHighlightMaterials (originalMaterials, highlightColor, withPolygonOffset)
{
let typeToHighlightMaterial = new Map ();
let highlightMaterials = [];
for (let originalMaterial of originalMaterials) {
if (typeToHighlightMaterial.has (originalMaterial.type)) {
highlightMaterials.push (typeToHighlightMaterial.get (originalMaterial.type));
continue;
}
let highlightMaterial = CreateHighlightMaterial (originalMaterial, highlightColor, withPolygonOffset);
typeToHighlightMaterial.set (originalMaterial.type, highlightMaterial);
highlightMaterials.push (highlightMaterial);
}
return highlightMaterials;
}
export function DisposeThreeObjects (mainObject)
{
if (mainObject === null) {

View File

@ -1,6 +1,6 @@
import { SubCoord3D } from '../geometry/coord3d.js';
import { ProjectionMode } from '../viewer/camera.js';
import { ConvertColorToThreeColor, ShadingType } from '../threejs/threeutils.js';
import { ShadingType } from '../threejs/threeutils.js';
import * as THREE from 'three';
@ -99,26 +99,4 @@ export class ShadingModel
const lightDir = SubCoord3D (camera.eye, camera.center);
this.directionalLight.position.set (lightDir.x, lightDir.y, lightDir.z);
}
CreateHighlightMaterial (highlightColor, withOffset)
{
let material = null;
if (this.type === ShadingType.Phong) {
material = new THREE.MeshPhongMaterial ({
color : ConvertColorToThreeColor (highlightColor),
side : THREE.DoubleSide
});
} else if (this.type === ShadingType.Physical) {
material = new THREE.MeshStandardMaterial ({
color : ConvertColorToThreeColor (highlightColor),
side : THREE.DoubleSide
});
}
if (material !== null && withOffset) {
material.polygonOffset = true;
material.polygonOffsetUnit = 1;
material.polygonOffsetFactor = 1;
}
return material;
}
}

View File

@ -1,7 +1,7 @@
import { Coord3D, CoordDistance3D, SubCoord3D } from '../geometry/coord3d.js';
import { DegRad, Direction, IsEqual } from '../geometry/geometry.js';
import { ColorComponentToFloat } from '../model/color.js';
import { ShadingType } from '../threejs/threeutils.js';
import { CreateHighlightMaterials, ShadingType } from '../threejs/threeutils.js';
import { Camera, NavigationMode, ProjectionMode } from './camera.js';
import { GetDomElementInnerDimensions } from './domutils.js';
import { Navigation } from './navigation.js';
@ -448,7 +448,7 @@ export class Viewer
SetMeshesVisibility (isVisible)
{
this.mainModel.EnumerateMeshes ((mesh) => {
this.mainModel.EnumerateMeshesAndLines ((mesh) => {
let visible = isVisible (mesh.userData);
if (mesh.visible !== visible) {
mesh.visible = visible;
@ -465,22 +465,13 @@ export class Viewer
SetMeshesHighlight (highlightColor, isHighlighted)
{
function CreateHighlightMaterials (originalMaterials, highlightMaterial)
{
let highlightMaterials = [];
for (let i = 0; i < originalMaterials.length; i++) {
highlightMaterials.push (highlightMaterial);
}
return highlightMaterials;
}
const highlightMaterial = this.CreateHighlightMaterial (highlightColor);
this.mainModel.EnumerateMeshes ((mesh) => {
let withPolygonOffset = this.mainModel.HasLinesOrEdges ();
this.mainModel.EnumerateMeshesAndLines ((mesh) => {
let highlighted = isHighlighted (mesh.userData);
if (highlighted) {
if (mesh.userData.threeMaterials === null) {
mesh.userData.threeMaterials = mesh.material;
mesh.material = CreateHighlightMaterials (mesh.material, highlightMaterial);
mesh.material = CreateHighlightMaterials (mesh.userData.threeMaterials, highlightColor, withPolygonOffset);
}
} else {
if (mesh.userData.threeMaterials !== null) {
@ -493,12 +484,6 @@ export class Viewer
this.Render ();
}
CreateHighlightMaterial (highlightColor)
{
const showEdges = this.mainModel.edgeSettings.showEdges;
return this.shadingModel.CreateHighlightMaterial (highlightColor, showEdges);
}
GetMeshUserDataUnderMouse (mouseCoords)
{
let intersection = this.GetMeshIntersectionUnderMouse (mouseCoords);
@ -528,9 +513,9 @@ export class Viewer
return this.mainModel.GetBoundingSphere (needToProcess);
}
EnumerateMeshesUserData (enumerator)
EnumerateMeshesAndLinesUserData (enumerator)
{
this.mainModel.EnumerateMeshes ((mesh) => {
this.mainModel.EnumerateMeshesAndLines ((mesh) => {
enumerator (mesh.userData);
});
}

View File

@ -119,14 +119,24 @@ export class ViewerMainModel
this.edgeModel = new ViewerModel (this.scene);
this.edgeSettings = new EdgeSettings (false, new RGBColor (0, 0, 0), 1);
this.hasLines = false;
this.hasPolygonOffset = false;
}
SetMainObject (mainObject)
{
this.mainModel.SetRootObject (mainObject);
this.hasLines = false;
this.hasPolygonOffset = false;
this.EnumerateLines ((line) => {
this.hasLines = true;
});
if (this.edgeSettings.showEdges) {
this.GenerateEdgeModel ();
}
this.UpdatePolygonOffset ();
}
UpdateWorldMatrix ()
@ -169,7 +179,6 @@ export class ViewerMainModel
this.UpdateWorldMatrix ();
this.EnumerateMeshes ((mesh) => {
SetThreeMeshPolygonOffset (mesh, true);
let edges = new THREE.EdgesGeometry (mesh.geometry, this.edgeSettings.edgeThreshold);
let line = new THREE.LineSegments (edges, new THREE.LineBasicMaterial ({
color: edgeColor
@ -179,13 +188,15 @@ export class ViewerMainModel
line.visible = mesh.visible;
this.edgeModel.AddObject (line);
});
this.UpdatePolygonOffset ();
}
GetBoundingBox (needToProcess)
{
let hasMesh = false;
let boundingBox = new THREE.Box3 ();
this.EnumerateMeshes ((mesh) => {
this.EnumerateMeshesAndLines ((mesh) => {
if (needToProcess (mesh.userData)) {
boundingBox.union (new THREE.Box3 ().setFromObject (mesh));
hasMesh = true;
@ -221,9 +232,7 @@ export class ViewerMainModel
return;
}
this.EnumerateMeshes ((mesh) => {
SetThreeMeshPolygonOffset (mesh, false);
});
this.UpdatePolygonOffset ();
this.edgeModel.Clear ();
}
@ -232,7 +241,25 @@ export class ViewerMainModel
this.mainModel.Traverse ((obj) => {
if (obj.isMesh) {
enumerator (obj);
} else if (obj.type === 'LineSegments') {
}
});
}
EnumerateLines (enumerator)
{
this.mainModel.Traverse ((obj) => {
if (obj.isLineSegments) {
enumerator (obj);
}
});
}
EnumerateMeshesAndLines (enumerator)
{
this.mainModel.Traverse ((obj) => {
if (obj.isMesh) {
enumerator (obj);
} else if (obj.isLineSegments) {
enumerator (obj);
}
});
@ -247,6 +274,22 @@ export class ViewerMainModel
});
}
HasLinesOrEdges ()
{
return this.hasLines || this.edgeSettings.showEdges;
}
UpdatePolygonOffset ()
{
let needPolygonOffset = this.HasLinesOrEdges ();
if (needPolygonOffset !== this.hasPolygonOffset) {
this.EnumerateMeshes ((mesh) => {
SetThreeMeshPolygonOffset (mesh, needPolygonOffset);
});
this.hasPolygonOffset = needPolygonOffset;
}
}
GetMeshIntersectionUnderMouse (mouseCoords, camera, width, height)
{
if (this.mainModel.IsEmpty ()) {
@ -258,6 +301,8 @@ export class ViewerMainModel
}
let raycaster = new THREE.Raycaster ();
raycaster.params.Line.threshold = 0.1;
let mousePos = new THREE.Vector2 ();
mousePos.x = (mouseCoords.x / width) * 2 - 1;
mousePos.y = -(mouseCoords.y / height) * 2 + 1;
@ -265,7 +310,7 @@ export class ViewerMainModel
let iSectObjects = raycaster.intersectObject (this.mainModel.GetRootObject (), true);
for (let i = 0; i < iSectObjects.length; i++) {
let iSectObject = iSectObjects[i];
if (iSectObject.object.isMesh && iSectObject.object.visible) {
if ((iSectObject.object.isMesh || iSectObject.object.isLineSegments) && iSectObject.object.visible) {
return iSectObject;
}
}

View File

@ -19,7 +19,7 @@ import { ShowSnapshotDialog } from './snapshotdialog.js';
import { AddSvgIconElement, GetFilesFromDataTransfer, InstallTooltip, IsSmallWidth } from './utils.js';
import { ShowOpenUrlDialog } from './openurldialog.js';
import { ShowSharingDialog } from './sharingdialog.js';
import { HasDefaultMaterial, ReplaceDefaultMaterialColor } from '../engine/model/modelutils.js';
import { HasDefaultMaterial, ReplaceDefaultMaterialsColor } from '../engine/model/modelutils.js';
import { Direction } from '../engine/geometry/geometry.js';
import { CookieGetBoolVal, CookieSetBoolVal } from './cookiehandler.js';
import { MeasureTool } from './measuretool.js';
@ -577,9 +577,9 @@ export class Website
this.viewer.SetBackgroundColor (this.settings.backgroundColor);
let modelLoader = this.modelLoaderUI.GetModelLoader ();
if (modelLoader.GetDefaultMaterial () !== null) {
ReplaceDefaultMaterialColor (this.model, this.settings.defaultColor);
modelLoader.ReplaceDefaultMaterialColor (this.settings.defaultColor);
if (modelLoader.GetDefaultMaterials () !== null) {
ReplaceDefaultMaterialsColor (this.model, this.settings.defaultColor);
modelLoader.ReplaceDefaultMaterialsColor (this.settings.defaultColor);
}
}
@ -814,9 +814,9 @@ export class Website
onDefaultColorChanged : () => {
this.settings.SaveToCookies ();
let modelLoader = this.modelLoaderUI.GetModelLoader ();
if (modelLoader.GetDefaultMaterial () !== null) {
ReplaceDefaultMaterialColor (this.model, this.settings.defaultColor);
modelLoader.ReplaceDefaultMaterialColor (this.settings.defaultColor);
if (modelLoader.GetDefaultMaterials () !== null) {
ReplaceDefaultMaterialsColor (this.model, this.settings.defaultColor);
modelLoader.ReplaceDefaultMaterialsColor (this.settings.defaultColor);
}
this.viewer.Render ();
},
@ -839,7 +839,7 @@ export class Website
function GetMeshUserDataArray (viewer, meshInstanceId)
{
let userDataArr = [];
viewer.EnumerateMeshesUserData ((meshUserData) => {
viewer.EnumerateMeshesAndLinesUserData ((meshUserData) => {
if (meshUserData.originalMeshInstance.id.IsEqual (meshInstanceId)) {
userDataArr.push (meshUserData);
}
@ -850,7 +850,7 @@ export class Website
function GetMeshesForMaterial (viewer, materialIndex)
{
let usedByMeshes = [];
viewer.EnumerateMeshesUserData ((meshUserData) => {
viewer.EnumerateMeshesAndLinesUserData ((meshUserData) => {
if (materialIndex === null || meshUserData.originalMaterials.indexOf (materialIndex) !== -1) {
usedByMeshes.push (meshUserData.originalMeshInstance);
}

View File

@ -0,0 +1,14 @@
newmtl Red
Ka 0.000000 0.000000 0.000000
Kd 0.800000 0.000000 0.000000
Ks 0.500000 0.500000 0.500000
newmtl Green
Ka 0.000000 0.000000 0.000000
Kd 0.000000 0.800000 0.000000
Ks 0.500000 0.500000 0.500000
newmtl Blue
Ka 0.000000 0.000000 0.000000
Kd 0.000000 0.000000 0.800000
Ks 0.500000 0.500000 0.500000

View File

@ -0,0 +1,44 @@
# Cube with Materials
mtllib cube_with_edges.mtl
g Cube
v 0.0 0.0 0.0
v 1.0 0.0 0.0
v 1.0 1.0 0.0
v 0.0 1.0 0.0
v 0.0 0.0 1.0
v 1.0 0.0 1.0
v 1.0 1.0 1.0
v 0.0 1.0 1.0
vn 1.0 0.0 0.0
vn -1.0 0.0 0.0
vn 0.0 1.0 0.0
vn 0.0 -1.0 0.0
vn 0.0 0.0 1.0
vn 0.0 0.0 -1.0
vt 0.0 0.0
vt 1.0 0.0
vt 1.0 1.0
vt 0.0 1.0
f 1/1/6 4/2/6 3/3/6 2/4/6
f 2/1/1 3/2/1 7/3/1 6/4/1
f 4/1/2 1/2/2 5/3/2 8/4/2
f 5/1/5 6/2/5 7/3/5 8/4/5
l 1 4 2 3 6 7 5 8
usemtl Red
f 3/1/3 4/2/3 8/3/3 7/4/3
usemtl Blue
f 1/1/4 2/2/4 6/3/4 5/4/4
usemtl Green
l 3 4 4 8 8 7 7 3
l 1 2 2 6 6 5 5 1

View File

@ -2,23 +2,49 @@ mtllib lines_triangles_colors.mtl
v 0.0 0.0 0.0
v 1.0 0.0 0.0
v 1.0 1.0 0.0
v 0.0 1.0 0.0
v 0.0 0.0 1.0
v 1.0 0.0 1.0
v 1.0 1.0 1.0
v 0.0 1.0 1.0
v 0.0 0.0 2.0
v 1.0 0.0 2.0
v 1.0 1.0 2.0
v 0.0 1.0 2.0
v 0.0 0.0 1.0
v 0.5 1.0 0.5
g Mesh01
usemtl Red
l 1 2
l 3 4
f 9 10 11
usemtl Green
l 5 6 6 7 7 8 8 5
f 9 11 12
usemtl Blue
f 1 2 3
l 1 5
f 9 5 8 12
usemtl Green
f 1 3 4
l 3 5
v 2.0 0.0 0.0
v 3.0 0.0 0.0
v 3.0 0.0 1.0
v 2.0 0.0 1.0
v 2.5 1.0 0.5
g Mesh02
usemtl Red
f 6 7 8
l 6 10
usemtl Green
f 6 8 9
l 8 10
v 4.0 0.0 0.0
v 5.0 0.0 0.0
v 5.0 0.0 1.0
v 4.0 0.0 1.0
g Mesh03
usemtl Red
f 11 12 13
usemtl Green
f 11 13 14
v 6.0 0.0 0.0
v 7.0 0.0 1.0
v 6.5 1.0 0.5
g Mesh04
usemtl Red
l 15 17
usemtl Green
l 16 17