@cesium/engine 23.0.1 → 24.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Build/Workers/{chunk-G6MJ3ZW3.js → chunk-2N4KDHS3.js} +10 -10
- package/Build/Workers/{chunk-C6HHBKT5.js → chunk-44EMEGKW.js} +5 -5
- package/Build/Workers/{chunk-TNXOPEIG.js → chunk-4TIG36AW.js} +12 -12
- package/Build/Workers/{chunk-PQTSXJBJ.js → chunk-5A2SW66E.js} +16 -16
- package/Build/Workers/{chunk-TXYQNXNW.js → chunk-5GXYJQ2K.js} +3 -3
- package/Build/Workers/{chunk-O67UP5YO.js → chunk-63SIWPLS.js} +13 -13
- package/Build/Workers/{chunk-CVAAIRNP.js → chunk-6MPGQEHA.js} +2 -2
- package/Build/Workers/{chunk-LHFC4R7Z.js → chunk-6RMS4S72.js} +6 -6
- package/Build/Workers/{chunk-77DJBHMI.js → chunk-6WLHJFD3.js} +7 -7
- package/Build/Workers/{chunk-HXEPZWJN.js → chunk-72VYSVEW.js} +9 -9
- package/Build/Workers/{chunk-VPWYHFQA.js → chunk-7MDYBRYJ.js} +4 -4
- package/Build/Workers/{chunk-XPMXRJDD.js → chunk-7O5XJTVE.js} +5 -5
- package/Build/Workers/{chunk-UEWYSOFD.js → chunk-7QRFIKWQ.js} +2 -2
- package/Build/Workers/{chunk-3UQ2YMPP.js → chunk-7TYLCBGK.js} +8 -8
- package/Build/Workers/{chunk-GLCPE2BJ.js → chunk-7X322WP2.js} +13 -13
- package/Build/Workers/{chunk-2OBWHTIC.js → chunk-A47HVBC5.js} +7 -7
- package/Build/Workers/{chunk-CID5SY7L.js → chunk-AF3MU2RL.js} +5 -5
- package/Build/Workers/{chunk-BTP3634E.js → chunk-AJLTU6PF.js} +1 -1
- package/Build/Workers/{chunk-YSJRB2UZ.js → chunk-AMIHNSST.js} +2 -2
- package/Build/Workers/{chunk-QPXGGVHC.js → chunk-B6SCUUFP.js} +10 -10
- package/Build/Workers/{chunk-QNABVTTP.js → chunk-BJD6QGXZ.js} +12 -12
- package/Build/Workers/{chunk-RZX6LOG6.js → chunk-C6P4IG5P.js} +6 -6
- package/Build/Workers/{chunk-4JJQRZYL.js → chunk-D4EJ2NXG.js} +17 -17
- package/Build/Workers/{chunk-K7UTK4OM.js → chunk-DHKPFLSJ.js} +1 -1
- package/Build/Workers/{chunk-S53HSRT6.js → chunk-DVB56LG7.js} +6 -6
- package/Build/Workers/{chunk-PBECJOWF.js → chunk-EDXL4W76.js} +2 -2
- package/Build/Workers/{chunk-ALTCIHRH.js → chunk-EV3VGO6Y.js} +17 -17
- package/Build/Workers/{chunk-UOQB7XQI.js → chunk-GOQBUCXH.js} +10 -10
- package/Build/Workers/{chunk-TMCTZ5E3.js → chunk-GQUNK2XC.js} +14 -14
- package/Build/Workers/{chunk-PAFMAR7A.js → chunk-HKUES6UG.js} +12 -12
- package/Build/Workers/{chunk-6U5QMZU3.js → chunk-HRHRYFHS.js} +9 -9
- package/Build/Workers/{chunk-PUO7BYDY.js → chunk-HXJMS2ZI.js} +1 -1
- package/Build/Workers/{chunk-FXSRA5UG.js → chunk-ILMFADZA.js} +4 -4
- package/Build/Workers/{chunk-U4SWB6TI.js → chunk-ISY4EZCA.js} +4 -4
- package/Build/Workers/{chunk-PGZ3B6CB.js → chunk-J6AW5YHS.js} +14 -14
- package/Build/Workers/{chunk-VX774SWE.js → chunk-JCI63T3K.js} +6 -6
- package/Build/Workers/{chunk-54O3AGOA.js → chunk-KLPGTXS3.js} +6 -6
- package/Build/Workers/{chunk-CNLXMOPM.js → chunk-LIB2H534.js} +10 -10
- package/Build/Workers/{chunk-H3TVRJLY.js → chunk-LXMCPFFS.js} +4 -4
- package/Build/Workers/{chunk-DNMASBMH.js → chunk-MKM27KGV.js} +2 -2
- package/Build/Workers/{chunk-66OWUDO7.js → chunk-N65BAKSH.js} +8 -8
- package/Build/Workers/{chunk-ZEMJQKHD.js → chunk-NKT5K3K3.js} +11 -11
- package/Build/Workers/{chunk-EIC3VAOZ.js → chunk-NPF7SSHZ.js} +7 -7
- package/Build/Workers/{chunk-YDR5LX5Z.js → chunk-PVV64VFW.js} +1 -1
- package/Build/Workers/{chunk-FKU77FNM.js → chunk-Q3C6VQH6.js} +4 -4
- package/Build/Workers/{chunk-CYOPNGPX.js → chunk-RQNJD3O4.js} +12 -12
- package/Build/Workers/{chunk-IJ3SUMK3.js → chunk-UIGVOKKI.js} +1 -1
- package/Build/Workers/{chunk-TFPG3ZKW.js → chunk-UQU4RXLT.js} +27 -19
- package/Build/Workers/{chunk-N6HRZLS6.js → chunk-VLDEUTOP.js} +2 -2
- package/Build/Workers/{chunk-MNSNOONX.js → chunk-VMVOUQ5J.js} +7 -7
- package/Build/Workers/{chunk-OZYB3AOR.js → chunk-XJRBB253.js} +11 -11
- package/Build/Workers/{chunk-B2VA6IEL.js → chunk-XY6HMDGI.js} +5 -5
- package/Build/Workers/{chunk-2M7DKGLW.js → chunk-Y7HNNPNK.js} +10 -10
- package/Build/Workers/{chunk-CJ7ZDY77.js → chunk-YAOZMOFL.js} +5 -5
- package/Build/Workers/{chunk-FCJQO4NC.js → chunk-YJZGW74L.js} +8 -8
- package/Build/Workers/{chunk-JUKGMJX7.js → chunk-YQFTYQMZ.js} +1 -1
- package/Build/Workers/{chunk-HNDE73JK.js → chunk-ZBZRTRJB.js} +10 -10
- package/Build/Workers/combineGeometry.js +24 -24
- package/Build/Workers/createBoxGeometry.js +18 -18
- package/Build/Workers/createBoxOutlineGeometry.js +16 -16
- package/Build/Workers/createCircleGeometry.js +26 -26
- package/Build/Workers/createCircleOutlineGeometry.js +19 -19
- package/Build/Workers/createCoplanarPolygonGeometry.js +33 -33
- package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +31 -31
- package/Build/Workers/createCorridorGeometry.js +29 -29
- package/Build/Workers/createCorridorOutlineGeometry.js +28 -28
- package/Build/Workers/createCylinderGeometry.js +20 -20
- package/Build/Workers/createCylinderOutlineGeometry.js +18 -18
- package/Build/Workers/createEllipseGeometry.js +26 -26
- package/Build/Workers/createEllipseOutlineGeometry.js +19 -19
- package/Build/Workers/createEllipsoidGeometry.js +19 -19
- package/Build/Workers/createEllipsoidOutlineGeometry.js +18 -18
- package/Build/Workers/createFrustumGeometry.js +18 -18
- package/Build/Workers/createFrustumOutlineGeometry.js +18 -18
- package/Build/Workers/createGeometry.js +24 -24
- package/Build/Workers/createGroundPolylineGeometry.js +22 -22
- package/Build/Workers/createPlaneGeometry.js +16 -16
- package/Build/Workers/createPlaneOutlineGeometry.js +15 -15
- package/Build/Workers/createPolygonGeometry.js +32 -32
- package/Build/Workers/createPolygonOutlineGeometry.js +30 -30
- package/Build/Workers/createPolylineGeometry.js +25 -25
- package/Build/Workers/createPolylineVolumeGeometry.js +31 -31
- package/Build/Workers/createPolylineVolumeOutlineGeometry.js +27 -27
- package/Build/Workers/createRectangleGeometry.js +27 -27
- package/Build/Workers/createRectangleOutlineGeometry.js +20 -20
- package/Build/Workers/createSimplePolylineGeometry.js +23 -23
- package/Build/Workers/createSphereGeometry.js +19 -19
- package/Build/Workers/createSphereOutlineGeometry.js +18 -18
- package/Build/Workers/createTaskProcessorWorker.js +3 -3
- package/Build/Workers/createVectorTileClampedPolylines.js +14 -14
- package/Build/Workers/createVectorTileGeometries.js +24 -24
- package/Build/Workers/createVectorTilePoints.js +13 -13
- package/Build/Workers/createVectorTilePolygons.js +22 -22
- package/Build/Workers/createVectorTilePolylines.js +14 -14
- package/Build/Workers/createVerticesFromCesium3DTilesTerrain.js +25 -25
- package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +22 -22
- package/Build/Workers/createVerticesFromHeightmap.js +22 -22
- package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +20 -20
- package/Build/Workers/createWallGeometry.js +25 -25
- package/Build/Workers/createWallOutlineGeometry.js +24 -24
- package/Build/Workers/decodeDraco.js +10 -10
- package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +5 -5
- package/Build/Workers/decodeI3S.js +12 -12
- package/Build/Workers/gaussianSplatSorter.js +4 -4
- package/Build/Workers/gaussianSplatTextureGenerator.js +4 -4
- package/Build/Workers/incrementallyBuildTerrainPicker.js +10 -10
- package/Build/Workers/transcodeKTX2.js +6 -6
- package/Build/Workers/transferTypedArrayTest.js +1 -1
- package/Build/Workers/upsampleQuantizedTerrainMesh.js +22 -22
- package/Build/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +25 -25
- package/Source/Core/BoundingSphere.js +1 -1
- package/Source/Core/Cartesian2.js +7 -5
- package/Source/Core/Cartesian3.js +8 -6
- package/Source/Core/Cartesian4.js +8 -6
- package/Source/Core/Color.js +5 -3
- package/Source/Core/DeveloperError.js +2 -1
- package/Source/Core/ITwinPlatform.js +1 -0
- package/Source/Core/Ion.js +1 -1
- package/Source/Core/S2Cell.js +2 -2
- package/Source/Core/TerrainMesh.js +10 -1
- package/Source/Core/TerrainPicker.js +1 -0
- package/Source/Core/WallGeometry.js +1 -1
- package/Source/Core/WallOutlineGeometry.js +1 -1
- package/Source/Core/assert.js +27 -0
- package/Source/Core/globalTypes.js +4 -0
- package/Source/DataSources/CzmlDataSource.js +9 -0
- package/Source/DataSources/PathGraphics.js +13 -0
- package/Source/DataSources/PathVisualizer.js +330 -18
- package/Source/DataSources/StaticGeometryColorBatch.js +7 -2
- package/Source/DataSources/StaticGeometryPerMaterialBatch.js +7 -2
- package/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js +3 -1
- package/Source/DataSources/StaticGroundPolylinePerMaterialBatch.js +3 -1
- package/Source/Renderer/Context.js +1 -1
- package/Source/Renderer/RenderState.js +2 -2
- package/Source/Renderer/VertexArray.js +80 -0
- package/Source/Scene/ArcGisMapService.js +1 -1
- package/Source/Scene/BillboardCollection.js +65 -364
- package/Source/Scene/BufferPoint.js +148 -0
- package/Source/Scene/BufferPointCollection.js +135 -0
- package/Source/Scene/BufferPointMaterial.js +95 -0
- package/Source/Scene/BufferPolygon.js +516 -0
- package/Source/Scene/BufferPolygonCollection.js +368 -0
- package/Source/Scene/BufferPolygonMaterial.js +41 -0
- package/Source/Scene/BufferPolyline.js +185 -0
- package/Source/Scene/BufferPolylineCollection.js +136 -0
- package/Source/Scene/BufferPolylineMaterial.js +93 -0
- package/Source/Scene/BufferPrimitive.js +347 -0
- package/Source/Scene/BufferPrimitiveCollection.js +702 -0
- package/Source/Scene/BufferPrimitiveMaterial.js +140 -0
- package/Source/Scene/Cesium3DTileContent.js +5 -1
- package/Source/Scene/Cesium3DTileContentFactory.js +9 -0
- package/Source/Scene/Cesium3DTileStyle.js +22 -0
- package/Source/Scene/Cesium3DTileset.js +1 -0
- package/Source/Scene/ClippingPolygonCollection.js +270 -101
- package/Source/Scene/CubeMapPanorama.js +4 -4
- package/Source/Scene/GaussianSplat3DTileContent.js +40 -46
- package/Source/Scene/GaussianSplatPrimitive.js +413 -70
- package/Source/Scene/GetFeatureInfoFormat.js +3 -3
- package/Source/Scene/GltfLoader.js +215 -34
- package/Source/Scene/GltfSpzLoader.js +109 -0
- package/Source/Scene/ITwinData.js +1 -0
- package/Source/Scene/Label.js +32 -0
- package/Source/Scene/LabelCollection.js +14 -13
- package/Source/Scene/Material.js +2 -0
- package/Source/Scene/Megatexture.js +1 -0
- package/Source/Scene/MetadataClassProperty.js +24 -10
- package/Source/Scene/MetadataComponentType.js +115 -23
- package/Source/Scene/Model/CustomShaderPipelineStage.js +3 -1
- package/Source/Scene/Model/EdgeVisibilityPipelineStage.js +761 -263
- package/Source/Scene/Model/MaterialPipelineStage.js +147 -0
- package/Source/Scene/Model/MetadataPipelineStage.js +3 -3
- package/Source/Scene/Model/ModelDrawCommand.js +6 -0
- package/Source/Scene/Model/ModelReader.js +1 -1
- package/Source/Scene/Model/ModelUtility.js +3 -1
- package/Source/Scene/Model/createVectorTileBuffersFromModelComponents.js +330 -0
- package/Source/Scene/ModelComponents.js +1632 -1542
- package/Source/Scene/PickedMetadataInfo.js +1 -0
- package/Source/Scene/ScreenSpaceCameraController.js +13 -0
- package/Source/Scene/SkyBox.js +17 -8
- package/Source/Scene/TileBoundingRegion.js +1 -1
- package/Source/Scene/TileBoundingS2Cell.js +1 -1
- package/Source/Scene/TileBoundingSphere.js +1 -1
- package/Source/Scene/TweenCollection.js +7 -0
- package/Source/Scene/VectorGltf3DTileContent.js +382 -0
- package/Source/Scene/VertexAttributeSemantic.js +14 -0
- package/Source/Scene/WebMapServiceImageryProvider.js +2 -2
- package/Source/Scene/WebMapTileServiceImageryProvider.js +366 -131
- package/Source/Scene/parseStructuralMetadata.js +97 -37
- package/Source/Scene/renderBufferPointCollection.js +334 -0
- package/Source/Scene/renderBufferPolygonCollection.js +386 -0
- package/Source/Scene/renderBufferPolylineCollection.js +529 -0
- package/Source/Shaders/BillboardCollectionFS.glsl +2 -77
- package/Source/Shaders/BillboardCollectionFS.js +2 -77
- package/Source/Shaders/BillboardCollectionVS.glsl +2 -60
- package/Source/Shaders/BillboardCollectionVS.js +2 -60
- package/Source/Shaders/BufferPointMaterialFS.glsl +27 -0
- package/Source/Shaders/BufferPointMaterialFS.js +29 -0
- package/Source/Shaders/BufferPointMaterialVS.glsl +48 -0
- package/Source/Shaders/BufferPointMaterialVS.js +50 -0
- package/Source/Shaders/BufferPolygonMaterialFS.glsl +13 -0
- package/Source/Shaders/BufferPolygonMaterialFS.js +15 -0
- package/Source/Shaders/BufferPolygonMaterialVS.glsl +30 -0
- package/Source/Shaders/BufferPolygonMaterialVS.js +32 -0
- package/Source/Shaders/BufferPolylineMaterialFS.glsl +13 -0
- package/Source/Shaders/BufferPolylineMaterialFS.js +15 -0
- package/Source/Shaders/BufferPolylineMaterialVS.glsl +49 -0
- package/Source/Shaders/BufferPolylineMaterialVS.js +51 -0
- package/Source/Shaders/Model/EdgeVisibilityStageFS.glsl +34 -48
- package/Source/Shaders/Model/EdgeVisibilityStageFS.js +34 -49
- package/Source/Shaders/Model/EdgeVisibilityStageVS.glsl +98 -0
- package/Source/Shaders/Model/EdgeVisibilityStageVS.js +100 -0
- package/Source/Shaders/Model/ModelFS.glsl +15 -0
- package/Source/Shaders/Model/ModelFS.js +15 -0
- package/Source/Shaders/Model/ModelVS.glsl +8 -0
- package/Source/Shaders/Model/ModelVS.js +8 -0
- package/Source/Shaders/PolygonSignedDistanceFS.glsl +64 -33
- package/Source/Shaders/PolygonSignedDistanceFS.js +64 -33
- package/Source/Shaders/PrimitiveGaussianSplatVS.glsl +9 -2
- package/Source/Shaders/PrimitiveGaussianSplatVS.js +9 -2
- package/Source/Shaders/Voxels/VoxelFS.glsl +1 -1
- package/Source/Shaders/Voxels/VoxelFS.js +1 -1
- package/Source/Workers/decodeDraco.js +3 -0
- package/Source/Workers/decodeI3S.js +5 -2
- package/index.d.ts +1007 -111
- package/index.js +394 -369
- package/package.json +2 -2
|
@@ -5,13 +5,17 @@ import defined from "../../Core/defined.js";
|
|
|
5
5
|
import IndexDatatype from "../../Core/IndexDatatype.js";
|
|
6
6
|
import ComponentDatatype from "../../Core/ComponentDatatype.js";
|
|
7
7
|
import PrimitiveType from "../../Core/PrimitiveType.js";
|
|
8
|
+
import Cartesian2 from "../../Core/Cartesian2.js";
|
|
8
9
|
import Cartesian3 from "../../Core/Cartesian3.js";
|
|
10
|
+
import AttributeCompression from "../../Core/AttributeCompression.js";
|
|
9
11
|
import Pass from "../../Renderer/Pass.js";
|
|
10
12
|
import ShaderDestination from "../../Renderer/ShaderDestination.js";
|
|
11
13
|
import EdgeVisibilityStageFS from "../../Shaders/Model/EdgeVisibilityStageFS.js";
|
|
14
|
+
import EdgeVisibilityStageVS from "../../Shaders/Model/EdgeVisibilityStageVS.js";
|
|
12
15
|
import ModelUtility from "./ModelUtility.js";
|
|
13
16
|
import ModelReader from "./ModelReader.js";
|
|
14
17
|
import VertexAttributeSemantic from "../VertexAttributeSemantic.js";
|
|
18
|
+
import AttributeType from "../AttributeType.js";
|
|
15
19
|
|
|
16
20
|
/**
|
|
17
21
|
* Builds derived line geometry for model edges using EXT_mesh_primitive_edge_visibility data.
|
|
@@ -69,10 +73,18 @@ EdgeVisibilityPipelineStage.process = function (
|
|
|
69
73
|
ShaderDestination.FRAGMENT,
|
|
70
74
|
);
|
|
71
75
|
shaderBuilder.addFragmentLines(EdgeVisibilityStageFS);
|
|
76
|
+
shaderBuilder.addVertexLines(EdgeVisibilityStageVS);
|
|
72
77
|
|
|
73
78
|
// Add a uniform to distinguish between original geometry pass and edge pass
|
|
74
79
|
shaderBuilder.addUniform("bool", "u_isEdgePass", ShaderDestination.BOTH);
|
|
75
80
|
|
|
81
|
+
// Add line width uniform for edge expansion if not already added by MaterialPipelineStage
|
|
82
|
+
const material = primitive.material;
|
|
83
|
+
const lineStyle = defined(material) ? material.lineStyle : undefined;
|
|
84
|
+
if (!defined(lineStyle) || !defined(lineStyle.width)) {
|
|
85
|
+
shaderBuilder.addUniform("float", "u_lineWidth", ShaderDestination.VERTEX);
|
|
86
|
+
}
|
|
87
|
+
|
|
76
88
|
// Add edge type attribute and varying
|
|
77
89
|
const edgeTypeLocation = shaderBuilder.addAttribute("float", "a_edgeType");
|
|
78
90
|
shaderBuilder.addVarying("float", "v_edgeType", "flat");
|
|
@@ -102,23 +114,21 @@ EdgeVisibilityPipelineStage.process = function (
|
|
|
102
114
|
shaderBuilder.addVarying("vec3", "v_faceNormalAView", "flat");
|
|
103
115
|
shaderBuilder.addVarying("vec3", "v_faceNormalBView", "flat");
|
|
104
116
|
|
|
105
|
-
// Add varying for
|
|
117
|
+
// Add varying for silhouette discard decision in vertex shader
|
|
118
|
+
shaderBuilder.addVarying("float", "v_shouldDiscard", "flat");
|
|
119
|
+
|
|
120
|
+
// Add attributes and varyings for quad-based wide line rendering
|
|
121
|
+
const edgeOtherPosLocation = shaderBuilder.addAttribute(
|
|
122
|
+
"vec3",
|
|
123
|
+
"a_edgeOtherPos",
|
|
124
|
+
);
|
|
125
|
+
const edgeOffsetLocation = shaderBuilder.addAttribute(
|
|
126
|
+
"float",
|
|
127
|
+
"a_edgeOffset",
|
|
128
|
+
);
|
|
129
|
+
shaderBuilder.addVarying("float", "v_edgeOffset");
|
|
106
130
|
|
|
107
|
-
//
|
|
108
|
-
shaderBuilder.addFunctionLines("setDynamicVaryingsVS", [
|
|
109
|
-
"#ifdef HAS_EDGE_VISIBILITY",
|
|
110
|
-
" if (u_isEdgePass) {",
|
|
111
|
-
" v_edgeType = a_edgeType;",
|
|
112
|
-
"#ifdef HAS_EDGE_FEATURE_ID",
|
|
113
|
-
" v_featureId_0 = a_edgeFeatureId;",
|
|
114
|
-
"#endif",
|
|
115
|
-
" // Transform normals from model space to view space",
|
|
116
|
-
" v_silhouetteNormalView = czm_normal * a_silhouetteNormal;",
|
|
117
|
-
" v_faceNormalAView = czm_normal * a_faceNormalA;",
|
|
118
|
-
" v_faceNormalBView = czm_normal * a_faceNormalB;",
|
|
119
|
-
" }",
|
|
120
|
-
"#endif",
|
|
121
|
-
]);
|
|
131
|
+
// Add varying for view space position for perspective-correct silhouette detection
|
|
122
132
|
|
|
123
133
|
// Build triangle adjacency (mapping edges to adjacent triangles) and compute per-triangle face normals.
|
|
124
134
|
const adjacencyData = buildTriangleAdjacency(primitive);
|
|
@@ -133,14 +143,56 @@ EdgeVisibilityPipelineStage.process = function (
|
|
|
133
143
|
return;
|
|
134
144
|
}
|
|
135
145
|
|
|
146
|
+
const runtimePrimitive = renderResources.runtimePrimitive.primitive;
|
|
147
|
+
const vertexColorInfo = collectVertexColors(runtimePrimitive);
|
|
148
|
+
const hasEdgeColorOverride = edgeResult.edgeData.some(function (edge) {
|
|
149
|
+
return defined(edge.color);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const needsEdgeColorAttribute =
|
|
153
|
+
hasEdgeColorOverride || defined(vertexColorInfo);
|
|
154
|
+
|
|
155
|
+
let edgeColorLocation;
|
|
156
|
+
if (needsEdgeColorAttribute) {
|
|
157
|
+
edgeColorLocation = shaderBuilder.addAttribute("vec4", "a_edgeColor");
|
|
158
|
+
shaderBuilder.addVarying("vec4", "v_edgeColor", "flat");
|
|
159
|
+
shaderBuilder.addDefine(
|
|
160
|
+
"HAS_EDGE_COLOR_ATTRIBUTE",
|
|
161
|
+
undefined,
|
|
162
|
+
ShaderDestination.BOTH,
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
let cumDistAttribute;
|
|
167
|
+
let edgeCumDistLocation;
|
|
168
|
+
const cumDistAttr = ModelUtility.getAttributeBySemantic(
|
|
169
|
+
primitive,
|
|
170
|
+
"BENTLEY_materials_line_style:CUMULATIVE_DISTANCE",
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
if (defined(cumDistAttr)) {
|
|
174
|
+
cumDistAttribute = cumDistAttr;
|
|
175
|
+
edgeCumDistLocation = shaderBuilder.addAttribute(
|
|
176
|
+
"float",
|
|
177
|
+
"a_edgeCumulativeDistance",
|
|
178
|
+
);
|
|
179
|
+
shaderBuilder.addDefine(
|
|
180
|
+
"HAS_EDGE_CUMULATIVE_DISTANCE",
|
|
181
|
+
undefined,
|
|
182
|
+
ShaderDestination.VERTEX,
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
136
186
|
// Generate paired face normals for each unique edge (used to classify silhouette edges in the shader).
|
|
137
187
|
const edgeFaceNormals = generateEdgeFaceNormals(
|
|
138
188
|
adjacencyData,
|
|
139
189
|
edgeResult.edgeIndices,
|
|
190
|
+
edgeResult.edgeData,
|
|
191
|
+
primitive.edgeVisibility,
|
|
140
192
|
);
|
|
141
193
|
|
|
142
|
-
// Create edge-domain
|
|
143
|
-
const edgeGeometry =
|
|
194
|
+
// Create edge-domain quad geometry (4 vertices per edge) with all required attributes for wide line rendering.
|
|
195
|
+
const edgeGeometry = createQuadEdgeGeometry(
|
|
144
196
|
edgeResult.edgeIndices,
|
|
145
197
|
edgeResult.edgeData,
|
|
146
198
|
renderResources,
|
|
@@ -150,8 +202,14 @@ EdgeVisibilityPipelineStage.process = function (
|
|
|
150
202
|
faceNormalALocation,
|
|
151
203
|
faceNormalBLocation,
|
|
152
204
|
edgeFeatureIdLocation,
|
|
205
|
+
edgeColorLocation,
|
|
206
|
+
edgeOtherPosLocation,
|
|
207
|
+
edgeOffsetLocation,
|
|
208
|
+
vertexColorInfo,
|
|
153
209
|
primitive.edgeVisibility,
|
|
154
210
|
edgeFaceNormals,
|
|
211
|
+
cumDistAttribute,
|
|
212
|
+
edgeCumDistLocation,
|
|
155
213
|
);
|
|
156
214
|
|
|
157
215
|
if (!defined(edgeGeometry)) {
|
|
@@ -171,12 +229,34 @@ EdgeVisibilityPipelineStage.process = function (
|
|
|
171
229
|
return false;
|
|
172
230
|
};
|
|
173
231
|
|
|
232
|
+
// Provide a fallback line width when the material did not define one.
|
|
233
|
+
if (!defined(renderResources.uniformMap.u_lineWidth)) {
|
|
234
|
+
renderResources.uniformMap.u_lineWidth = function () {
|
|
235
|
+
return 1.0;
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (defined(cumDistAttribute)) {
|
|
240
|
+
if (!defined(renderResources.uniformMap.u_pixelsPerWorld)) {
|
|
241
|
+
renderResources.uniformMap.u_pixelsPerWorld = function () {
|
|
242
|
+
return 1.0;
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const lineWidth =
|
|
248
|
+
defined(lineStyle) && defined(lineStyle.width)
|
|
249
|
+
? lineStyle.width * frameState.pixelRatio
|
|
250
|
+
: undefined;
|
|
251
|
+
|
|
174
252
|
// Store edge geometry metadata so the renderer can issue a separate edges pass.
|
|
253
|
+
// Use TRIANGLES instead of LINES to support wide lines via quad tessellation
|
|
175
254
|
renderResources.edgeGeometry = {
|
|
176
255
|
vertexArray: edgeGeometry.vertexArray,
|
|
177
256
|
indexCount: edgeGeometry.indexCount,
|
|
178
|
-
primitiveType: PrimitiveType.
|
|
257
|
+
primitiveType: PrimitiveType.TRIANGLES,
|
|
179
258
|
pass: Pass.CESIUM_3D_TILE_EDGES,
|
|
259
|
+
lineWidth: lineWidth,
|
|
180
260
|
};
|
|
181
261
|
};
|
|
182
262
|
|
|
@@ -284,7 +364,7 @@ function buildTriangleAdjacency(primitive) {
|
|
|
284
364
|
faceNormals[base + 1] = scratchCross.y;
|
|
285
365
|
faceNormals[base + 2] = scratchCross.z;
|
|
286
366
|
|
|
287
|
-
//
|
|
367
|
+
// Register edges
|
|
288
368
|
processEdge(i0, i1, t);
|
|
289
369
|
processEdge(i1, i2, t);
|
|
290
370
|
processEdge(i2, i0, t);
|
|
@@ -294,21 +374,83 @@ function buildTriangleAdjacency(primitive) {
|
|
|
294
374
|
}
|
|
295
375
|
|
|
296
376
|
/**
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
* the
|
|
377
|
+
* Generate face normal pairs for each edge. Silhouette edges use normals from the GLB
|
|
378
|
+
* silhouetteNormals accessor if available. Boundary edges synthesize the opposite normal
|
|
379
|
+
* as the negation of the first triangle's normal.
|
|
300
380
|
*
|
|
301
|
-
* @param {{edgeMap:Map<string,number[]>, faceNormals:Float32Array}} adjacencyData
|
|
381
|
+
* @param {{edgeMap:Map<string,number[]>, faceNormals:Float32Array}} adjacencyData Triangle adjacency data
|
|
302
382
|
* @param {number[]} edgeIndices Packed array of 2 vertex indices per edge
|
|
383
|
+
* @param {Object[]} edgeData Array of edge metadata (edgeType, mateVertexIndex)
|
|
384
|
+
* @param {Object} edgeVisibility Edge visibility extension data
|
|
303
385
|
* @returns {Float32Array} Packed array: 6 floats per edge (normalA.xyz, normalB.xyz)
|
|
304
386
|
* @private
|
|
305
387
|
*/
|
|
306
|
-
function generateEdgeFaceNormals(
|
|
388
|
+
function generateEdgeFaceNormals(
|
|
389
|
+
adjacencyData,
|
|
390
|
+
edgeIndices,
|
|
391
|
+
edgeData,
|
|
392
|
+
edgeVisibility,
|
|
393
|
+
) {
|
|
307
394
|
const { edgeMap, faceNormals } = adjacencyData;
|
|
308
395
|
const numEdges = edgeIndices.length / 2;
|
|
396
|
+
const edgeFaceNormals = new Float32Array(numEdges * 6);
|
|
397
|
+
|
|
398
|
+
const hasGLBSilhouetteNormals =
|
|
399
|
+
defined(edgeVisibility) && defined(edgeVisibility.silhouetteNormals);
|
|
400
|
+
let silhouetteNormalsUint32 = null;
|
|
401
|
+
const scratchDecodedA = new Cartesian3();
|
|
402
|
+
const scratchDecodedB = new Cartesian3();
|
|
403
|
+
|
|
404
|
+
if (hasGLBSilhouetteNormals) {
|
|
405
|
+
// GLB stores VEC3 BYTE as normalized normal vectors (signed bytes).
|
|
406
|
+
// Decode from signed bytes to normalized vectors, then re-encode to 16-bit octahedral format.
|
|
407
|
+
const decodeSignedByte = (val) => 2 * ((val + 128) / 255) - 1;
|
|
408
|
+
|
|
409
|
+
// Re-encode each VEC3 BYTE to 16-bit oct-encoded normal using AttributeCompression
|
|
410
|
+
const uint16Normals = new Uint16Array(
|
|
411
|
+
edgeVisibility.silhouetteNormals.length,
|
|
412
|
+
);
|
|
413
|
+
const scratchNormal = new Cartesian3();
|
|
414
|
+
const scratchEncoded = new Cartesian2();
|
|
415
|
+
|
|
416
|
+
for (let i = 0; i < edgeVisibility.silhouetteNormals.length; i++) {
|
|
417
|
+
const vec3 = edgeVisibility.silhouetteNormals[i];
|
|
418
|
+
|
|
419
|
+
// Decode from signed byte to normal vector
|
|
420
|
+
scratchNormal.x = decodeSignedByte(vec3.x);
|
|
421
|
+
scratchNormal.y = decodeSignedByte(vec3.y);
|
|
422
|
+
scratchNormal.z = decodeSignedByte(vec3.z);
|
|
423
|
+
|
|
424
|
+
// Normalize to unit vector
|
|
425
|
+
const magnitude = Cartesian3.magnitude(scratchNormal);
|
|
426
|
+
if (magnitude > 0) {
|
|
427
|
+
Cartesian3.normalize(scratchNormal, scratchNormal);
|
|
428
|
+
} else {
|
|
429
|
+
// Handle zero vector - use default up vector
|
|
430
|
+
scratchNormal.x = 0;
|
|
431
|
+
scratchNormal.y = 0;
|
|
432
|
+
scratchNormal.z = 1;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// Use Cesium's octahedral encoding (returns 0-255 integers)
|
|
436
|
+
AttributeCompression.octEncodeInRange(scratchNormal, 255, scratchEncoded);
|
|
437
|
+
|
|
438
|
+
// Convert to 16-bit integer: (y << 8) | x
|
|
439
|
+
const byteX = scratchEncoded.x & 0xff;
|
|
440
|
+
const byteY = scratchEncoded.y & 0xff;
|
|
441
|
+
uint16Normals[i] = (byteY << 8) | byteX;
|
|
442
|
+
}
|
|
309
443
|
|
|
310
|
-
|
|
311
|
-
|
|
444
|
+
// Pack pairs into Uint32Array (little-endian: normalA|normalB<<16)
|
|
445
|
+
const numPairs = Math.floor(uint16Normals.length / 2);
|
|
446
|
+
silhouetteNormalsUint32 = new Uint32Array(numPairs);
|
|
447
|
+
|
|
448
|
+
for (let i = 0; i < numPairs; i++) {
|
|
449
|
+
const normalA = uint16Normals[i * 2];
|
|
450
|
+
const normalB = uint16Normals[i * 2 + 1];
|
|
451
|
+
silhouetteNormalsUint32[i] = normalA | (normalB << 16);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
312
454
|
|
|
313
455
|
for (let i = 0; i < numEdges; i++) {
|
|
314
456
|
const a = edgeIndices[i * 2];
|
|
@@ -316,31 +458,77 @@ function generateEdgeFaceNormals(adjacencyData, edgeIndices) {
|
|
|
316
458
|
const edgeKey = `${a < b ? a : b},${a < b ? b : a}`;
|
|
317
459
|
const triangleList = edgeMap.get(edgeKey);
|
|
318
460
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
461
|
+
const { edgeType, mateVertexIndex } = edgeData[i];
|
|
462
|
+
|
|
463
|
+
let nAx, nAy, nAz, nBx, nBy, nBz;
|
|
464
|
+
let usedGLBNormals = false;
|
|
465
|
+
|
|
466
|
+
// Use GLB silhouetteNormals for type=1 (SILHOUETTE) edges if available
|
|
467
|
+
if (
|
|
468
|
+
hasGLBSilhouetteNormals &&
|
|
469
|
+
silhouetteNormalsUint32 &&
|
|
470
|
+
edgeType === 1 &&
|
|
471
|
+
mateVertexIndex >= 0
|
|
472
|
+
) {
|
|
473
|
+
// Each OctEncodedNormalPair is stored as one Uint32 value
|
|
474
|
+
// Uint32 contains 4 bytes: [byte0, byte1, byte2, byte3]
|
|
475
|
+
// normalA = byte0 | (byte1 << 8) - little endian
|
|
476
|
+
// normalB = byte2 | (byte3 << 8) - little endian
|
|
477
|
+
|
|
478
|
+
if (mateVertexIndex < silhouetteNormalsUint32.length) {
|
|
479
|
+
const uint32Value = silhouetteNormalsUint32[mateVertexIndex];
|
|
480
|
+
|
|
481
|
+
// Uint32 contains 4 bytes: [xA, yA, xB, yB]
|
|
482
|
+
// Extract and decode using octDecode (rangeMax=255)
|
|
483
|
+
AttributeCompression.octDecode(
|
|
484
|
+
uint32Value & 0xff, // xA
|
|
485
|
+
(uint32Value >> 8) & 0xff, // yA
|
|
486
|
+
scratchDecodedA,
|
|
487
|
+
);
|
|
488
|
+
AttributeCompression.octDecode(
|
|
489
|
+
(uint32Value >> 16) & 0xff, // xB
|
|
490
|
+
(uint32Value >> 24) & 0xff, // yB
|
|
491
|
+
scratchDecodedB,
|
|
492
|
+
);
|
|
493
|
+
|
|
494
|
+
nAx = scratchDecodedA.x;
|
|
495
|
+
nAy = scratchDecodedA.y;
|
|
496
|
+
nAz = scratchDecodedA.z;
|
|
497
|
+
nBx = scratchDecodedB.x;
|
|
498
|
+
nBy = scratchDecodedB.y;
|
|
499
|
+
nBz = scratchDecodedB.z;
|
|
500
|
+
|
|
501
|
+
usedGLBNormals = true;
|
|
502
|
+
}
|
|
322
503
|
}
|
|
323
504
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
505
|
+
// Fallback to triangle adjacency if GLB normals not used
|
|
506
|
+
if (!usedGLBNormals) {
|
|
507
|
+
// Expect at least one triangle; silently skip if not found (defensive)
|
|
508
|
+
if (!defined(triangleList) || triangleList.length === 0) {
|
|
509
|
+
continue;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
const tA = triangleList[0];
|
|
513
|
+
const aBase = tA * 3;
|
|
514
|
+
nAx = faceNormals[aBase];
|
|
515
|
+
nAy = faceNormals[aBase + 1];
|
|
516
|
+
nAz = faceNormals[aBase + 2];
|
|
517
|
+
|
|
518
|
+
const isManifold = triangleList.length > 1;
|
|
519
|
+
|
|
520
|
+
if (isManifold) {
|
|
521
|
+
const tB = triangleList[1];
|
|
522
|
+
const bBase = tB * 3;
|
|
523
|
+
nBx = faceNormals[bBase];
|
|
524
|
+
nBy = faceNormals[bBase + 1];
|
|
525
|
+
nBz = faceNormals[bBase + 2];
|
|
526
|
+
} else {
|
|
527
|
+
// Boundary edge – synthesize opposite normal
|
|
528
|
+
nBx = -nAx;
|
|
529
|
+
nBy = -nAy;
|
|
530
|
+
nBz = -nAz;
|
|
531
|
+
}
|
|
344
532
|
}
|
|
345
533
|
|
|
346
534
|
const baseIdx = i * 6;
|
|
@@ -372,91 +560,167 @@ function generateEdgeFaceNormals(adjacencyData, edgeIndices) {
|
|
|
372
560
|
*/
|
|
373
561
|
function extractVisibleEdges(primitive) {
|
|
374
562
|
const edgeVisibility = primitive.edgeVisibility;
|
|
563
|
+
if (!defined(edgeVisibility)) {
|
|
564
|
+
return [];
|
|
565
|
+
}
|
|
566
|
+
|
|
375
567
|
const visibility = edgeVisibility.visibility;
|
|
376
568
|
const indices = primitive.indices;
|
|
569
|
+
const lineStrings = edgeVisibility.lineStrings;
|
|
570
|
+
|
|
571
|
+
const attributes = primitive.attributes;
|
|
572
|
+
const vertexCount =
|
|
573
|
+
defined(attributes) && attributes.length > 0 ? attributes[0].count : 0;
|
|
377
574
|
|
|
378
|
-
|
|
575
|
+
const hasVisibilityData =
|
|
576
|
+
defined(visibility) &&
|
|
577
|
+
defined(indices) &&
|
|
578
|
+
defined(indices.typedArray) &&
|
|
579
|
+
indices.typedArray.length > 0;
|
|
580
|
+
const hasLineStrings = defined(lineStrings) && lineStrings.length > 0;
|
|
581
|
+
|
|
582
|
+
if (!hasVisibilityData && !hasLineStrings) {
|
|
379
583
|
return [];
|
|
380
584
|
}
|
|
381
585
|
|
|
382
|
-
const triangleIndexArray = indices.typedArray;
|
|
383
|
-
const vertexCount = primitive.attributes[0].count;
|
|
586
|
+
const triangleIndexArray = hasVisibilityData ? indices.typedArray : undefined;
|
|
384
587
|
const edgeIndices = [];
|
|
385
588
|
const edgeData = [];
|
|
386
589
|
const seenEdgeHashes = new Set();
|
|
387
590
|
let silhouetteEdgeCount = 0;
|
|
591
|
+
const globalColor = edgeVisibility.materialColor;
|
|
592
|
+
|
|
593
|
+
if (hasVisibilityData) {
|
|
594
|
+
let edgeIndex = 0;
|
|
595
|
+
const totalIndices = triangleIndexArray.length;
|
|
596
|
+
const visibilityArray = visibility;
|
|
597
|
+
|
|
598
|
+
for (let i = 0; i + 2 < totalIndices; i += 3) {
|
|
599
|
+
const v0 = triangleIndexArray[i];
|
|
600
|
+
const v1 = triangleIndexArray[i + 1];
|
|
601
|
+
const v2 = triangleIndexArray[i + 2];
|
|
602
|
+
for (let e = 0; e < 3; e++) {
|
|
603
|
+
let a;
|
|
604
|
+
let b;
|
|
605
|
+
if (e === 0) {
|
|
606
|
+
a = v0;
|
|
607
|
+
b = v1;
|
|
608
|
+
} else if (e === 1) {
|
|
609
|
+
a = v1;
|
|
610
|
+
b = v2;
|
|
611
|
+
} else {
|
|
612
|
+
a = v2;
|
|
613
|
+
b = v0;
|
|
614
|
+
}
|
|
388
615
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
for (let i = 0; i + 2 < totalIndices; i += 3) {
|
|
394
|
-
const v0 = triangleIndexArray[i];
|
|
395
|
-
const v1 = triangleIndexArray[i + 1];
|
|
396
|
-
const v2 = triangleIndexArray[i + 2];
|
|
397
|
-
for (let e = 0; e < 3; e++) {
|
|
398
|
-
let a, b;
|
|
399
|
-
if (e === 0) {
|
|
400
|
-
a = v0;
|
|
401
|
-
b = v1;
|
|
402
|
-
} else if (e === 1) {
|
|
403
|
-
a = v1;
|
|
404
|
-
b = v2;
|
|
405
|
-
} else if (e === 2) {
|
|
406
|
-
a = v2;
|
|
407
|
-
b = v0;
|
|
408
|
-
}
|
|
409
|
-
const byteIndex = Math.floor(edgeIndex / 4);
|
|
410
|
-
const bitPairOffset = (edgeIndex % 4) * 2;
|
|
411
|
-
edgeIndex++;
|
|
616
|
+
const byteIndex = Math.floor(edgeIndex / 4);
|
|
617
|
+
const bitPairOffset = (edgeIndex % 4) * 2;
|
|
618
|
+
edgeIndex++;
|
|
412
619
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
620
|
+
if (byteIndex >= visibilityArray.length) {
|
|
621
|
+
break;
|
|
622
|
+
}
|
|
416
623
|
|
|
417
|
-
|
|
418
|
-
|
|
624
|
+
const byte = visibilityArray[byteIndex];
|
|
625
|
+
const visibility2Bit = (byte >> bitPairOffset) & 0x3;
|
|
419
626
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
case 0: // HIDDEN - never draw
|
|
424
|
-
shouldIncludeEdge = false;
|
|
425
|
-
break;
|
|
426
|
-
case 1: // SILHOUETTE - conditionally visible (front-facing vs back-facing)
|
|
427
|
-
shouldIncludeEdge = true;
|
|
428
|
-
break;
|
|
429
|
-
case 2: // HARD - always draw (primary encoding)
|
|
430
|
-
shouldIncludeEdge = true;
|
|
431
|
-
break;
|
|
432
|
-
case 3: // REPEATED - always draw (secondary encoding of a hard edge already encoded as 2)
|
|
433
|
-
shouldIncludeEdge = true;
|
|
434
|
-
break;
|
|
435
|
-
}
|
|
627
|
+
if (visibility2Bit === 0) {
|
|
628
|
+
continue;
|
|
629
|
+
}
|
|
436
630
|
|
|
437
|
-
if (shouldIncludeEdge) {
|
|
438
631
|
const small = Math.min(a, b);
|
|
439
632
|
const big = Math.max(a, b);
|
|
440
|
-
const
|
|
633
|
+
const edgeKey = `${small},${big}`;
|
|
441
634
|
|
|
442
|
-
if (
|
|
443
|
-
|
|
444
|
-
|
|
635
|
+
if (seenEdgeHashes.has(edgeKey)) {
|
|
636
|
+
continue;
|
|
637
|
+
}
|
|
638
|
+
seenEdgeHashes.add(edgeKey);
|
|
639
|
+
edgeIndices.push(a, b);
|
|
640
|
+
|
|
641
|
+
// Only process silhouette edges (type=1) as marked in GLB
|
|
642
|
+
// Use computed edge index for boundary edges
|
|
643
|
+
let mateVertexIndex = -1;
|
|
644
|
+
if (visibility2Bit === 1) {
|
|
645
|
+
mateVertexIndex = silhouetteEdgeCount;
|
|
646
|
+
silhouetteEdgeCount++;
|
|
647
|
+
}
|
|
445
648
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
649
|
+
edgeData.push({
|
|
650
|
+
edgeType: visibility2Bit, // Use original GLB edge type
|
|
651
|
+
triangleIndex: Math.floor(i / 3),
|
|
652
|
+
edgeIndex: e,
|
|
653
|
+
mateVertexIndex: mateVertexIndex,
|
|
654
|
+
currentTriangleVertices: [v0, v1, v2],
|
|
655
|
+
color: globalColor,
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
451
660
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
661
|
+
if (hasLineStrings) {
|
|
662
|
+
for (let i = 0; i < lineStrings.length; i++) {
|
|
663
|
+
const lineString = lineStrings[i];
|
|
664
|
+
if (!defined(lineString) || !defined(lineString.indices)) {
|
|
665
|
+
continue;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
const indicesArray = lineString.indices;
|
|
669
|
+
if (!defined(indicesArray) || indicesArray.length < 2) {
|
|
670
|
+
continue;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
const restartValue = lineString.restartIndex;
|
|
674
|
+
const lineColor = defined(lineString.materialColor)
|
|
675
|
+
? lineString.materialColor
|
|
676
|
+
: globalColor;
|
|
677
|
+
|
|
678
|
+
let previous;
|
|
679
|
+
for (let j = 0; j < indicesArray.length; j++) {
|
|
680
|
+
const currentIndex = indicesArray[j];
|
|
681
|
+
if (defined(restartValue) && currentIndex === restartValue) {
|
|
682
|
+
previous = undefined;
|
|
683
|
+
continue;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
if (!defined(previous)) {
|
|
687
|
+
previous = currentIndex;
|
|
688
|
+
continue;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
const a = previous;
|
|
692
|
+
const b = currentIndex;
|
|
693
|
+
previous = currentIndex;
|
|
694
|
+
|
|
695
|
+
if (a === b) {
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
if (
|
|
700
|
+
vertexCount > 0 &&
|
|
701
|
+
(a < 0 || a >= vertexCount || b < 0 || b >= vertexCount)
|
|
702
|
+
) {
|
|
703
|
+
continue;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
const small = Math.min(a, b);
|
|
707
|
+
const big = Math.max(a, b);
|
|
708
|
+
const edgeKey = `${small},${big}`;
|
|
709
|
+
|
|
710
|
+
if (seenEdgeHashes.has(edgeKey)) {
|
|
711
|
+
continue;
|
|
459
712
|
}
|
|
713
|
+
|
|
714
|
+
seenEdgeHashes.add(edgeKey);
|
|
715
|
+
edgeIndices.push(a, b);
|
|
716
|
+
edgeData.push({
|
|
717
|
+
edgeType: 2,
|
|
718
|
+
triangleIndex: -1,
|
|
719
|
+
edgeIndex: -1,
|
|
720
|
+
mateVertexIndex: -1,
|
|
721
|
+
currentTriangleVertices: undefined,
|
|
722
|
+
color: defined(lineColor) ? lineColor : undefined,
|
|
723
|
+
});
|
|
460
724
|
}
|
|
461
725
|
}
|
|
462
726
|
}
|
|
@@ -464,10 +728,91 @@ function extractVisibleEdges(primitive) {
|
|
|
464
728
|
return { edgeIndices, edgeData, silhouetteEdgeCount };
|
|
465
729
|
}
|
|
466
730
|
|
|
731
|
+
function collectVertexColors(runtimePrimitive) {
|
|
732
|
+
if (!defined(runtimePrimitive)) {
|
|
733
|
+
return undefined;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
const colorAttribute = ModelUtility.getAttributeBySemantic(
|
|
737
|
+
runtimePrimitive,
|
|
738
|
+
VertexAttributeSemantic.COLOR,
|
|
739
|
+
);
|
|
740
|
+
if (!defined(colorAttribute)) {
|
|
741
|
+
return undefined;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
const components = AttributeType.getNumberOfComponents(colorAttribute.type);
|
|
745
|
+
if (components !== 3 && components !== 4) {
|
|
746
|
+
return undefined;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
let colorData = colorAttribute.typedArray;
|
|
750
|
+
if (!defined(colorData)) {
|
|
751
|
+
colorData = ModelReader.readAttributeAsTypedArray(colorAttribute);
|
|
752
|
+
}
|
|
753
|
+
if (!defined(colorData)) {
|
|
754
|
+
return undefined;
|
|
755
|
+
}
|
|
756
|
+
const count = colorAttribute.count;
|
|
757
|
+
if (!defined(count) || count === 0) {
|
|
758
|
+
return undefined;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
if (colorData.length < count * components) {
|
|
762
|
+
return undefined;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
const isFloatArray =
|
|
766
|
+
colorData instanceof Float32Array || colorData instanceof Float64Array;
|
|
767
|
+
const isUint8Array = colorData instanceof Uint8Array;
|
|
768
|
+
const isUint16Array = colorData instanceof Uint16Array;
|
|
769
|
+
|
|
770
|
+
if (!isFloatArray && !isUint8Array && !isUint16Array) {
|
|
771
|
+
return undefined;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
const colors = new Float32Array(count * 4);
|
|
775
|
+
|
|
776
|
+
const convertComponent = function (value) {
|
|
777
|
+
let converted;
|
|
778
|
+
if (isFloatArray) {
|
|
779
|
+
converted = value;
|
|
780
|
+
} else if (isUint8Array) {
|
|
781
|
+
converted = value / 255.0;
|
|
782
|
+
} else if (isUint16Array) {
|
|
783
|
+
converted = value / 65535.0;
|
|
784
|
+
}
|
|
785
|
+
return Math.min(Math.max(converted, 0.0), 1.0);
|
|
786
|
+
};
|
|
787
|
+
|
|
788
|
+
for (let i = 0; i < count; i++) {
|
|
789
|
+
const srcBase = i * components;
|
|
790
|
+
const destBase = i * 4;
|
|
791
|
+
colors[destBase] = convertComponent(colorData[srcBase]);
|
|
792
|
+
colors[destBase + 1] = convertComponent(colorData[srcBase + 1]);
|
|
793
|
+
colors[destBase + 2] = convertComponent(colorData[srcBase + 2]);
|
|
794
|
+
if (components === 4) {
|
|
795
|
+
colors[destBase + 3] = convertComponent(colorData[srcBase + 3]);
|
|
796
|
+
} else {
|
|
797
|
+
colors[destBase + 3] = 1.0;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
return {
|
|
802
|
+
colors: colors,
|
|
803
|
+
count: count,
|
|
804
|
+
};
|
|
805
|
+
}
|
|
806
|
+
|
|
467
807
|
/**
|
|
468
|
-
*
|
|
469
|
-
*
|
|
470
|
-
*
|
|
808
|
+
* @typedef {object} VertexColorInfo
|
|
809
|
+
* @property {Float32Array} colors The packed per-vertex colors.
|
|
810
|
+
* @property {number} count The number of vertices.
|
|
811
|
+
*/
|
|
812
|
+
|
|
813
|
+
/**
|
|
814
|
+
* Create quad-based edge geometry for wide line rendering. Each edge becomes a quad (4 vertices, 2 triangles).
|
|
815
|
+
* This allows proper line width rendering in the vertex shader by extruding perpendicular to the line direction.
|
|
471
816
|
*
|
|
472
817
|
* @param {number[]} edgeIndices Packed array [a0,b0, a1,b1, ...] of vertex indices into the source mesh
|
|
473
818
|
* @param {Object[]} edgeData Array of edge metadata including edge type and silhouette normal lookup index
|
|
@@ -478,12 +823,18 @@ function extractVisibleEdges(primitive) {
|
|
|
478
823
|
* @param {number} faceNormalALocation Shader attribute location for face normal A
|
|
479
824
|
* @param {number} faceNormalBLocation Shader attribute location for face normal B
|
|
480
825
|
* @param {number} edgeFeatureIdLocation Shader attribute location for optional edge feature ID
|
|
826
|
+
* @param {number} edgeColorLocation Shader attribute location for optional edge color data
|
|
827
|
+
* @param {number} edgeOtherPosLocation Shader attribute location for the other endpoint position
|
|
828
|
+
* @param {number} edgeOffsetLocation Shader attribute location for edge offset (-1 or +1)
|
|
829
|
+
* @param {VertexColorInfo} [vertexColorInfo] Packed per-vertex colors (optional)
|
|
481
830
|
* @param {Object} edgeVisibility Edge visibility extension object (may contain silhouetteNormals[])
|
|
482
831
|
* @param {Float32Array} edgeFaceNormals Packed face normals (6 floats per edge)
|
|
483
|
-
* @
|
|
832
|
+
* @param {Object} [cumDistAttribute] Cumulative distance attribute
|
|
833
|
+
* @param {number} [edgeCumDistLocation] Cumulative distance location
|
|
834
|
+
* @returns {Object|undefined} Object with {vertexArray, indexCount, hasEdgeFeatureIds} or undefined on failure
|
|
484
835
|
* @private
|
|
485
836
|
*/
|
|
486
|
-
function
|
|
837
|
+
function createQuadEdgeGeometry(
|
|
487
838
|
edgeIndices,
|
|
488
839
|
edgeData,
|
|
489
840
|
renderResources,
|
|
@@ -493,18 +844,24 @@ function createCPULineEdgeGeometry(
|
|
|
493
844
|
faceNormalALocation,
|
|
494
845
|
faceNormalBLocation,
|
|
495
846
|
edgeFeatureIdLocation,
|
|
847
|
+
edgeColorLocation,
|
|
848
|
+
edgeOtherPosLocation,
|
|
849
|
+
edgeOffsetLocation,
|
|
850
|
+
vertexColorInfo,
|
|
496
851
|
edgeVisibility,
|
|
497
852
|
edgeFaceNormals,
|
|
853
|
+
cumDistAttribute,
|
|
854
|
+
edgeCumDistLocation,
|
|
498
855
|
) {
|
|
499
856
|
if (!defined(edgeIndices) || edgeIndices.length === 0) {
|
|
500
857
|
return undefined;
|
|
501
858
|
}
|
|
502
859
|
|
|
503
860
|
const numEdges = edgeData.length;
|
|
504
|
-
const vertsPerEdge =
|
|
861
|
+
const vertsPerEdge = 4; // Each edge becomes a quad (4 vertices)
|
|
505
862
|
const totalVerts = numEdges * vertsPerEdge;
|
|
506
863
|
|
|
507
|
-
// Always use location 0 for position
|
|
864
|
+
// Always use location 0 for position
|
|
508
865
|
const positionLocation = 0;
|
|
509
866
|
|
|
510
867
|
// Get original vertex positions
|
|
@@ -516,57 +873,85 @@ function createCPULineEdgeGeometry(
|
|
|
516
873
|
? positionAttribute.typedArray
|
|
517
874
|
: ModelReader.readAttributeAsTypedArray(positionAttribute);
|
|
518
875
|
|
|
519
|
-
// Create
|
|
876
|
+
// Create arrays for quad vertices
|
|
520
877
|
const edgePosArray = new Float32Array(totalVerts * 3);
|
|
521
878
|
const edgeTypeArray = new Float32Array(totalVerts);
|
|
522
879
|
const silhouetteNormalArray = new Float32Array(totalVerts * 3);
|
|
523
880
|
const faceNormalAArray = new Float32Array(totalVerts * 3);
|
|
524
881
|
const faceNormalBArray = new Float32Array(totalVerts * 3);
|
|
525
|
-
|
|
882
|
+
const edgeOtherPosArray = new Float32Array(totalVerts * 3);
|
|
883
|
+
const edgeOffsetArray = new Float32Array(totalVerts);
|
|
884
|
+
|
|
885
|
+
const needsCumulativeDistance = defined(cumDistAttribute);
|
|
886
|
+
const edgeCumDistArray = needsCumulativeDistance
|
|
887
|
+
? new Float32Array(totalVerts)
|
|
888
|
+
: undefined;
|
|
889
|
+
let srcCumDist;
|
|
890
|
+
if (needsCumulativeDistance) {
|
|
891
|
+
srcCumDist = defined(cumDistAttribute.typedArray)
|
|
892
|
+
? cumDistAttribute.typedArray
|
|
893
|
+
: ModelReader.readAttributeAsTypedArray(cumDistAttribute);
|
|
894
|
+
}
|
|
526
895
|
|
|
527
|
-
const
|
|
896
|
+
const needsEdgeColorAttribute = defined(edgeColorLocation);
|
|
897
|
+
const edgeColorArray = needsEdgeColorAttribute
|
|
898
|
+
? new Float32Array(totalVerts * 4)
|
|
899
|
+
: undefined;
|
|
900
|
+
const vertexColors = defined(vertexColorInfo)
|
|
901
|
+
? vertexColorInfo.colors
|
|
902
|
+
: undefined;
|
|
903
|
+
const vertexColorCount = defined(vertexColorInfo) ? vertexColorInfo.count : 0;
|
|
904
|
+
|
|
905
|
+
function setNoColor(destVertexIndex) {
|
|
906
|
+
if (!needsEdgeColorAttribute) {
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
const destOffset = destVertexIndex * 4;
|
|
910
|
+
edgeColorArray[destOffset] = 0.0;
|
|
911
|
+
edgeColorArray[destOffset + 1] = 0.0;
|
|
912
|
+
edgeColorArray[destOffset + 2] = 0.0;
|
|
913
|
+
edgeColorArray[destOffset + 3] = -1.0;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
function setColorFromOverride(destVertexIndex, color) {
|
|
917
|
+
if (!needsEdgeColorAttribute) {
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
920
|
+
const destOffset = destVertexIndex * 4;
|
|
921
|
+
const r = defined(color.x) ? color.x : color[0];
|
|
922
|
+
const g = defined(color.y) ? color.y : color[1];
|
|
923
|
+
const b = defined(color.z) ? color.z : color[2];
|
|
924
|
+
const a = defined(color.w) ? color.w : defined(color[3]) ? color[3] : 1.0;
|
|
925
|
+
edgeColorArray[destOffset] = r;
|
|
926
|
+
edgeColorArray[destOffset + 1] = g;
|
|
927
|
+
edgeColorArray[destOffset + 2] = b;
|
|
928
|
+
edgeColorArray[destOffset + 3] = a;
|
|
929
|
+
}
|
|
528
930
|
|
|
931
|
+
function assignVertexColor(destVertexIndex, srcVertexIndex) {
|
|
932
|
+
if (!needsEdgeColorAttribute) {
|
|
933
|
+
return;
|
|
934
|
+
}
|
|
935
|
+
if (srcVertexIndex >= vertexColorCount) {
|
|
936
|
+
setNoColor(destVertexIndex);
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
939
|
+
const srcOffset = srcVertexIndex * 4;
|
|
940
|
+
const destOffset = destVertexIndex * 4;
|
|
941
|
+
edgeColorArray[destOffset] = vertexColors[srcOffset];
|
|
942
|
+
edgeColorArray[destOffset + 1] = vertexColors[srcOffset + 1];
|
|
943
|
+
edgeColorArray[destOffset + 2] = vertexColors[srcOffset + 2];
|
|
944
|
+
edgeColorArray[destOffset + 3] = vertexColors[srcOffset + 3];
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
// Generate quad vertices for each edge
|
|
529
948
|
for (let i = 0; i < numEdges; i++) {
|
|
530
949
|
const a = edgeIndices[i * 2];
|
|
531
950
|
const b = edgeIndices[i * 2 + 1];
|
|
951
|
+
const rawType = edgeData[i].edgeType;
|
|
952
|
+
const normalizedType = rawType / 255.0;
|
|
532
953
|
|
|
533
|
-
//
|
|
534
|
-
if (a < 0 || b < 0 || a > maxSrcVertex || b > maxSrcVertex) {
|
|
535
|
-
// Fill with zeros to maintain indexing
|
|
536
|
-
edgePosArray[p++] = 0;
|
|
537
|
-
edgePosArray[p++] = 0;
|
|
538
|
-
edgePosArray[p++] = 0;
|
|
539
|
-
edgePosArray[p++] = 0;
|
|
540
|
-
edgePosArray[p++] = 0;
|
|
541
|
-
edgePosArray[p++] = 0;
|
|
542
|
-
edgeTypeArray[i * 2] = 0;
|
|
543
|
-
edgeTypeArray[i * 2 + 1] = 0;
|
|
544
|
-
// Fill with default values
|
|
545
|
-
const normalIdx = i * 2;
|
|
546
|
-
silhouetteNormalArray[normalIdx * 3] = 0;
|
|
547
|
-
silhouetteNormalArray[normalIdx * 3 + 1] = 0;
|
|
548
|
-
silhouetteNormalArray[normalIdx * 3 + 2] = 1;
|
|
549
|
-
silhouetteNormalArray[(normalIdx + 1) * 3] = 0;
|
|
550
|
-
silhouetteNormalArray[(normalIdx + 1) * 3 + 1] = 0;
|
|
551
|
-
silhouetteNormalArray[(normalIdx + 1) * 3 + 2] = 1;
|
|
552
|
-
|
|
553
|
-
// Fill face normals with default values
|
|
554
|
-
faceNormalAArray[normalIdx * 3] = 0;
|
|
555
|
-
faceNormalAArray[normalIdx * 3 + 1] = 0;
|
|
556
|
-
faceNormalAArray[normalIdx * 3 + 2] = 1;
|
|
557
|
-
faceNormalAArray[(normalIdx + 1) * 3] = 0;
|
|
558
|
-
faceNormalAArray[(normalIdx + 1) * 3 + 1] = 0;
|
|
559
|
-
faceNormalAArray[(normalIdx + 1) * 3 + 2] = 1;
|
|
560
|
-
|
|
561
|
-
faceNormalBArray[normalIdx * 3] = 0;
|
|
562
|
-
faceNormalBArray[normalIdx * 3 + 1] = 0;
|
|
563
|
-
faceNormalBArray[normalIdx * 3 + 2] = 1;
|
|
564
|
-
faceNormalBArray[(normalIdx + 1) * 3] = 0;
|
|
565
|
-
faceNormalBArray[(normalIdx + 1) * 3 + 1] = 0;
|
|
566
|
-
faceNormalBArray[(normalIdx + 1) * 3 + 2] = 1;
|
|
567
|
-
continue;
|
|
568
|
-
}
|
|
569
|
-
|
|
954
|
+
// Get positions
|
|
570
955
|
const ax = srcPos[a * 3];
|
|
571
956
|
const ay = srcPos[a * 3 + 1];
|
|
572
957
|
const az = srcPos[a * 3 + 2];
|
|
@@ -574,24 +959,80 @@ function createCPULineEdgeGeometry(
|
|
|
574
959
|
const by = srcPos[b * 3 + 1];
|
|
575
960
|
const bz = srcPos[b * 3 + 2];
|
|
576
961
|
|
|
577
|
-
//
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
edgePosArray[
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
962
|
+
// Create 4 vertices for this edge: (A-, A+, B+, B-)
|
|
963
|
+
// where +/- indicates offset perpendicular to the line
|
|
964
|
+
// Store the other endpoint position for each vertex
|
|
965
|
+
const baseVertexIndex = i * 4;
|
|
966
|
+
|
|
967
|
+
// Vertex 0: position at A, other endpoint is B, offset -1
|
|
968
|
+
edgePosArray[baseVertexIndex * 3] = ax;
|
|
969
|
+
edgePosArray[baseVertexIndex * 3 + 1] = ay;
|
|
970
|
+
edgePosArray[baseVertexIndex * 3 + 2] = az;
|
|
971
|
+
edgeOtherPosArray[baseVertexIndex * 3] = bx;
|
|
972
|
+
edgeOtherPosArray[baseVertexIndex * 3 + 1] = by;
|
|
973
|
+
edgeOtherPosArray[baseVertexIndex * 3 + 2] = bz;
|
|
974
|
+
edgeOffsetArray[baseVertexIndex] = -1.0;
|
|
975
|
+
edgeTypeArray[baseVertexIndex] = normalizedType;
|
|
976
|
+
|
|
977
|
+
// Vertex 1: position at A, other endpoint is B, offset +1
|
|
978
|
+
edgePosArray[(baseVertexIndex + 1) * 3] = ax;
|
|
979
|
+
edgePosArray[(baseVertexIndex + 1) * 3 + 1] = ay;
|
|
980
|
+
edgePosArray[(baseVertexIndex + 1) * 3 + 2] = az;
|
|
981
|
+
edgeOtherPosArray[(baseVertexIndex + 1) * 3] = bx;
|
|
982
|
+
edgeOtherPosArray[(baseVertexIndex + 1) * 3 + 1] = by;
|
|
983
|
+
edgeOtherPosArray[(baseVertexIndex + 1) * 3 + 2] = bz;
|
|
984
|
+
edgeOffsetArray[baseVertexIndex + 1] = 1.0;
|
|
985
|
+
edgeTypeArray[baseVertexIndex + 1] = normalizedType;
|
|
986
|
+
|
|
987
|
+
// Vertex 2: position at B, other endpoint is A, offset +1
|
|
988
|
+
edgePosArray[(baseVertexIndex + 2) * 3] = bx;
|
|
989
|
+
edgePosArray[(baseVertexIndex + 2) * 3 + 1] = by;
|
|
990
|
+
edgePosArray[(baseVertexIndex + 2) * 3 + 2] = bz;
|
|
991
|
+
edgeOtherPosArray[(baseVertexIndex + 2) * 3] = ax;
|
|
992
|
+
edgeOtherPosArray[(baseVertexIndex + 2) * 3 + 1] = ay;
|
|
993
|
+
edgeOtherPosArray[(baseVertexIndex + 2) * 3 + 2] = az;
|
|
994
|
+
edgeOffsetArray[baseVertexIndex + 2] = 1.0;
|
|
995
|
+
edgeTypeArray[baseVertexIndex + 2] = normalizedType;
|
|
996
|
+
|
|
997
|
+
// Vertex 3: position at B, other endpoint is A, offset -1
|
|
998
|
+
edgePosArray[(baseVertexIndex + 3) * 3] = bx;
|
|
999
|
+
edgePosArray[(baseVertexIndex + 3) * 3 + 1] = by;
|
|
1000
|
+
edgePosArray[(baseVertexIndex + 3) * 3 + 2] = bz;
|
|
1001
|
+
edgeOtherPosArray[(baseVertexIndex + 3) * 3] = ax;
|
|
1002
|
+
edgeOtherPosArray[(baseVertexIndex + 3) * 3 + 1] = ay;
|
|
1003
|
+
edgeOtherPosArray[(baseVertexIndex + 3) * 3 + 2] = az;
|
|
1004
|
+
edgeOffsetArray[baseVertexIndex + 3] = -1.0;
|
|
1005
|
+
edgeTypeArray[baseVertexIndex + 3] = normalizedType;
|
|
1006
|
+
|
|
1007
|
+
// Handle edge colors
|
|
1008
|
+
const edgeOverrideColor = edgeData[i].color;
|
|
1009
|
+
if (defined(edgeOverrideColor)) {
|
|
1010
|
+
for (let v = 0; v < 4; v++) {
|
|
1011
|
+
setColorFromOverride(baseVertexIndex + v, edgeOverrideColor);
|
|
1012
|
+
}
|
|
1013
|
+
} else if (defined(vertexColors)) {
|
|
1014
|
+
for (let v = 0; v < 4; v++) {
|
|
1015
|
+
assignVertexColor(baseVertexIndex + v, a);
|
|
1016
|
+
}
|
|
1017
|
+
} else {
|
|
1018
|
+
for (let v = 0; v < 4; v++) {
|
|
1019
|
+
setNoColor(baseVertexIndex + v);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
587
1022
|
|
|
588
|
-
|
|
589
|
-
|
|
1023
|
+
if (needsCumulativeDistance) {
|
|
1024
|
+
const cumDistA = srcCumDist[a];
|
|
1025
|
+
const cumDistB = srcCumDist[b];
|
|
1026
|
+
edgeCumDistArray[baseVertexIndex] = cumDistA;
|
|
1027
|
+
edgeCumDistArray[baseVertexIndex + 1] = cumDistA;
|
|
1028
|
+
edgeCumDistArray[baseVertexIndex + 2] = cumDistB;
|
|
1029
|
+
edgeCumDistArray[baseVertexIndex + 3] = cumDistB;
|
|
1030
|
+
}
|
|
590
1031
|
|
|
591
|
-
//
|
|
1032
|
+
// Set silhouette normal (same for all 4 vertices)
|
|
592
1033
|
let normalX = 0,
|
|
593
1034
|
normalY = 0,
|
|
594
|
-
normalZ = 1;
|
|
1035
|
+
normalZ = 1;
|
|
595
1036
|
|
|
596
1037
|
if (rawType === 1 && defined(edgeVisibility.silhouetteNormals)) {
|
|
597
1038
|
const mateVertexIndex = edgeData[i].mateVertexIndex;
|
|
@@ -599,9 +1040,7 @@ function createCPULineEdgeGeometry(
|
|
|
599
1040
|
mateVertexIndex >= 0 &&
|
|
600
1041
|
mateVertexIndex < edgeVisibility.silhouetteNormals.length
|
|
601
1042
|
) {
|
|
602
|
-
const
|
|
603
|
-
const normal = silhouetteNormals[mateVertexIndex];
|
|
604
|
-
|
|
1043
|
+
const normal = edgeVisibility.silhouetteNormals[mateVertexIndex];
|
|
605
1044
|
if (defined(normal)) {
|
|
606
1045
|
normalX = normal.x;
|
|
607
1046
|
normalY = normal.y;
|
|
@@ -610,17 +1049,14 @@ function createCPULineEdgeGeometry(
|
|
|
610
1049
|
}
|
|
611
1050
|
}
|
|
612
1051
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
// Set face normals for both edge endpoints
|
|
623
|
-
const faceNormalIdx = i * 6; // 6 floats per edge (2 normals * 3 components)
|
|
1052
|
+
for (let v = 0; v < 4; v++) {
|
|
1053
|
+
silhouetteNormalArray[(baseVertexIndex + v) * 3] = normalX;
|
|
1054
|
+
silhouetteNormalArray[(baseVertexIndex + v) * 3 + 1] = normalY;
|
|
1055
|
+
silhouetteNormalArray[(baseVertexIndex + v) * 3 + 2] = normalZ;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
// Set face normals (same for all 4 vertices)
|
|
1059
|
+
const faceNormalIdx = i * 6;
|
|
624
1060
|
const normalAX = edgeFaceNormals[faceNormalIdx];
|
|
625
1061
|
const normalAY = edgeFaceNormals[faceNormalIdx + 1];
|
|
626
1062
|
const normalAZ = edgeFaceNormals[faceNormalIdx + 2];
|
|
@@ -628,21 +1064,14 @@ function createCPULineEdgeGeometry(
|
|
|
628
1064
|
const normalBY = edgeFaceNormals[faceNormalIdx + 4];
|
|
629
1065
|
const normalBZ = edgeFaceNormals[faceNormalIdx + 5];
|
|
630
1066
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
// Face normal B for both endpoints
|
|
640
|
-
faceNormalBArray[normalIdx * 3] = normalBX;
|
|
641
|
-
faceNormalBArray[normalIdx * 3 + 1] = normalBY;
|
|
642
|
-
faceNormalBArray[normalIdx * 3 + 2] = normalBZ;
|
|
643
|
-
faceNormalBArray[(normalIdx + 1) * 3] = normalBX;
|
|
644
|
-
faceNormalBArray[(normalIdx + 1) * 3 + 1] = normalBY;
|
|
645
|
-
faceNormalBArray[(normalIdx + 1) * 3 + 2] = normalBZ;
|
|
1067
|
+
for (let v = 0; v < 4; v++) {
|
|
1068
|
+
faceNormalAArray[(baseVertexIndex + v) * 3] = normalAX;
|
|
1069
|
+
faceNormalAArray[(baseVertexIndex + v) * 3 + 1] = normalAY;
|
|
1070
|
+
faceNormalAArray[(baseVertexIndex + v) * 3 + 2] = normalAZ;
|
|
1071
|
+
faceNormalBArray[(baseVertexIndex + v) * 3] = normalBX;
|
|
1072
|
+
faceNormalBArray[(baseVertexIndex + v) * 3 + 1] = normalBY;
|
|
1073
|
+
faceNormalBArray[(baseVertexIndex + v) * 3 + 2] = normalBZ;
|
|
1074
|
+
}
|
|
646
1075
|
}
|
|
647
1076
|
|
|
648
1077
|
// Create vertex buffers
|
|
@@ -651,44 +1080,92 @@ function createCPULineEdgeGeometry(
|
|
|
651
1080
|
typedArray: edgePosArray,
|
|
652
1081
|
usage: BufferUsage.STATIC_DRAW,
|
|
653
1082
|
});
|
|
1083
|
+
|
|
654
1084
|
const edgeTypeBuffer = Buffer.createVertexBuffer({
|
|
655
1085
|
context,
|
|
656
1086
|
typedArray: edgeTypeArray,
|
|
657
1087
|
usage: BufferUsage.STATIC_DRAW,
|
|
658
1088
|
});
|
|
1089
|
+
|
|
659
1090
|
const silhouetteNormalBuffer = Buffer.createVertexBuffer({
|
|
660
1091
|
context,
|
|
661
1092
|
typedArray: silhouetteNormalArray,
|
|
662
1093
|
usage: BufferUsage.STATIC_DRAW,
|
|
663
1094
|
});
|
|
1095
|
+
|
|
664
1096
|
const faceNormalABuffer = Buffer.createVertexBuffer({
|
|
665
1097
|
context,
|
|
666
1098
|
typedArray: faceNormalAArray,
|
|
667
1099
|
usage: BufferUsage.STATIC_DRAW,
|
|
668
1100
|
});
|
|
1101
|
+
|
|
669
1102
|
const faceNormalBBuffer = Buffer.createVertexBuffer({
|
|
670
1103
|
context,
|
|
671
1104
|
typedArray: faceNormalBArray,
|
|
672
1105
|
usage: BufferUsage.STATIC_DRAW,
|
|
673
1106
|
});
|
|
674
1107
|
|
|
675
|
-
|
|
1108
|
+
const edgeOtherPosBuffer = Buffer.createVertexBuffer({
|
|
1109
|
+
context,
|
|
1110
|
+
typedArray: edgeOtherPosArray,
|
|
1111
|
+
usage: BufferUsage.STATIC_DRAW,
|
|
1112
|
+
});
|
|
1113
|
+
|
|
1114
|
+
const edgeOffsetBuffer = Buffer.createVertexBuffer({
|
|
1115
|
+
context,
|
|
1116
|
+
typedArray: edgeOffsetArray,
|
|
1117
|
+
usage: BufferUsage.STATIC_DRAW,
|
|
1118
|
+
});
|
|
1119
|
+
|
|
1120
|
+
const edgeColorBuffer = needsEdgeColorAttribute
|
|
1121
|
+
? Buffer.createVertexBuffer({
|
|
1122
|
+
context,
|
|
1123
|
+
typedArray: edgeColorArray,
|
|
1124
|
+
usage: BufferUsage.STATIC_DRAW,
|
|
1125
|
+
})
|
|
1126
|
+
: undefined;
|
|
1127
|
+
|
|
1128
|
+
const edgeCumDistBuffer = needsCumulativeDistance
|
|
1129
|
+
? Buffer.createVertexBuffer({
|
|
1130
|
+
context,
|
|
1131
|
+
typedArray: edgeCumDistArray,
|
|
1132
|
+
usage: BufferUsage.STATIC_DRAW,
|
|
1133
|
+
})
|
|
1134
|
+
: undefined;
|
|
1135
|
+
|
|
1136
|
+
// Create triangle indices for quads: (0,1,2, 0,2,3) for each quad
|
|
1137
|
+
const numTriangles = numEdges * 2;
|
|
1138
|
+
const numIndices = numTriangles * 3;
|
|
676
1139
|
const useU32 = totalVerts > 65534;
|
|
677
|
-
const
|
|
678
|
-
|
|
679
|
-
|
|
1140
|
+
const indices = useU32
|
|
1141
|
+
? new Uint32Array(numIndices)
|
|
1142
|
+
: new Uint16Array(numIndices);
|
|
1143
|
+
|
|
1144
|
+
for (let i = 0; i < numEdges; i++) {
|
|
1145
|
+
const baseVertex = i * 4;
|
|
1146
|
+
const baseIndex = i * 6;
|
|
1147
|
+
|
|
1148
|
+
// Triangle 1: (v0, v1, v2)
|
|
1149
|
+
indices[baseIndex] = baseVertex;
|
|
1150
|
+
indices[baseIndex + 1] = baseVertex + 1;
|
|
1151
|
+
indices[baseIndex + 2] = baseVertex + 2;
|
|
1152
|
+
|
|
1153
|
+
// Triangle 2: (v0, v2, v3)
|
|
1154
|
+
indices[baseIndex + 3] = baseVertex;
|
|
1155
|
+
indices[baseIndex + 4] = baseVertex + 2;
|
|
1156
|
+
indices[baseIndex + 5] = baseVertex + 3;
|
|
680
1157
|
}
|
|
681
1158
|
|
|
682
1159
|
const indexBuffer = Buffer.createIndexBuffer({
|
|
683
1160
|
context,
|
|
684
|
-
typedArray:
|
|
1161
|
+
typedArray: indices,
|
|
685
1162
|
usage: BufferUsage.STATIC_DRAW,
|
|
686
1163
|
indexDatatype: useU32
|
|
687
1164
|
? IndexDatatype.UNSIGNED_INT
|
|
688
1165
|
: IndexDatatype.UNSIGNED_SHORT,
|
|
689
1166
|
});
|
|
690
1167
|
|
|
691
|
-
// Create vertex array with
|
|
1168
|
+
// Create vertex array with all attributes
|
|
692
1169
|
const attributes = [
|
|
693
1170
|
{
|
|
694
1171
|
index: positionLocation,
|
|
@@ -725,75 +1202,96 @@ function createCPULineEdgeGeometry(
|
|
|
725
1202
|
componentDatatype: ComponentDatatype.FLOAT,
|
|
726
1203
|
normalize: false,
|
|
727
1204
|
},
|
|
1205
|
+
{
|
|
1206
|
+
index: edgeOtherPosLocation,
|
|
1207
|
+
vertexBuffer: edgeOtherPosBuffer,
|
|
1208
|
+
componentsPerAttribute: 3,
|
|
1209
|
+
componentDatatype: ComponentDatatype.FLOAT,
|
|
1210
|
+
normalize: false,
|
|
1211
|
+
},
|
|
1212
|
+
{
|
|
1213
|
+
index: edgeOffsetLocation,
|
|
1214
|
+
vertexBuffer: edgeOffsetBuffer,
|
|
1215
|
+
componentsPerAttribute: 1,
|
|
1216
|
+
componentDatatype: ComponentDatatype.FLOAT,
|
|
1217
|
+
normalize: false,
|
|
1218
|
+
},
|
|
728
1219
|
];
|
|
729
1220
|
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
// Handle FeatureIdAttribute objects directly using setIndex
|
|
738
|
-
if (defined(firstFeatureIdSet.setIndex)) {
|
|
739
|
-
const featureIdAttribute = primitive.attributes.find(
|
|
740
|
-
(attr) =>
|
|
741
|
-
attr.semantic === VertexAttributeSemantic.FEATURE_ID &&
|
|
742
|
-
attr.setIndex === firstFeatureIdSet.setIndex,
|
|
743
|
-
);
|
|
744
|
-
|
|
745
|
-
if (defined(featureIdAttribute)) {
|
|
746
|
-
const featureIds = defined(featureIdAttribute.typedArray)
|
|
747
|
-
? featureIdAttribute.typedArray
|
|
748
|
-
: ModelReader.readAttributeAsTypedArray(featureIdAttribute);
|
|
749
|
-
|
|
750
|
-
// Create edge feature ID buffer based on edge indices
|
|
751
|
-
const edgeFeatureIds = new Float32Array(totalVerts);
|
|
752
|
-
for (let i = 0; i < numEdges; i++) {
|
|
753
|
-
const a = edgeIndices[i * 2];
|
|
754
|
-
const featureId = a < featureIds.length ? featureIds[a] : 0;
|
|
755
|
-
edgeFeatureIds[i * 2] = featureId;
|
|
756
|
-
edgeFeatureIds[i * 2 + 1] = featureId;
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
return edgeFeatureIds;
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
return undefined;
|
|
765
|
-
};
|
|
766
|
-
|
|
767
|
-
const edgeFeatureIds = getFeatureIdForEdge();
|
|
768
|
-
const hasEdgeFeatureIds = defined(edgeFeatureIds);
|
|
769
|
-
|
|
770
|
-
if (hasEdgeFeatureIds) {
|
|
771
|
-
const edgeFeatureIdBuffer = Buffer.createVertexBuffer({
|
|
772
|
-
context,
|
|
773
|
-
typedArray: edgeFeatureIds,
|
|
774
|
-
usage: BufferUsage.STATIC_DRAW,
|
|
1221
|
+
if (needsEdgeColorAttribute) {
|
|
1222
|
+
attributes.push({
|
|
1223
|
+
index: edgeColorLocation,
|
|
1224
|
+
vertexBuffer: edgeColorBuffer,
|
|
1225
|
+
componentsPerAttribute: 4,
|
|
1226
|
+
componentDatatype: ComponentDatatype.FLOAT,
|
|
1227
|
+
normalize: false,
|
|
775
1228
|
});
|
|
1229
|
+
}
|
|
776
1230
|
|
|
1231
|
+
if (needsCumulativeDistance) {
|
|
777
1232
|
attributes.push({
|
|
778
|
-
index:
|
|
779
|
-
vertexBuffer:
|
|
1233
|
+
index: edgeCumDistLocation,
|
|
1234
|
+
vertexBuffer: edgeCumDistBuffer,
|
|
780
1235
|
componentsPerAttribute: 1,
|
|
781
1236
|
componentDatatype: ComponentDatatype.FLOAT,
|
|
782
1237
|
normalize: false,
|
|
783
1238
|
});
|
|
784
1239
|
}
|
|
785
1240
|
|
|
786
|
-
const
|
|
1241
|
+
const primitive = renderResources.runtimePrimitive.primitive;
|
|
1242
|
+
if (defined(primitive.featureIds) && primitive.featureIds.length > 0) {
|
|
1243
|
+
const firstFeatureIdSet = primitive.featureIds[0];
|
|
1244
|
+
|
|
1245
|
+
if (defined(firstFeatureIdSet.setIndex)) {
|
|
1246
|
+
const featureIdAttribute = primitive.attributes.find(
|
|
1247
|
+
(attr) =>
|
|
1248
|
+
attr.semantic === VertexAttributeSemantic.FEATURE_ID &&
|
|
1249
|
+
attr.setIndex === firstFeatureIdSet.setIndex,
|
|
1250
|
+
);
|
|
1251
|
+
|
|
1252
|
+
if (defined(featureIdAttribute)) {
|
|
1253
|
+
const featureIds = defined(featureIdAttribute.typedArray)
|
|
1254
|
+
? featureIdAttribute.typedArray
|
|
1255
|
+
: ModelReader.readAttributeAsTypedArray(featureIdAttribute);
|
|
1256
|
+
|
|
1257
|
+
const edgeFeatureIds = new Float32Array(totalVerts);
|
|
1258
|
+
for (let i = 0; i < numEdges; i++) {
|
|
1259
|
+
const a = edgeIndices[i * 2];
|
|
1260
|
+
const featureId = a < featureIds.length ? featureIds[a] : 0;
|
|
1261
|
+
// Set same feature ID for all 4 vertices of the quad
|
|
1262
|
+
for (let v = 0; v < 4; v++) {
|
|
1263
|
+
edgeFeatureIds[i * 4 + v] = featureId;
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
787
1266
|
|
|
788
|
-
|
|
789
|
-
|
|
1267
|
+
const edgeFeatureIdBuffer = Buffer.createVertexBuffer({
|
|
1268
|
+
context,
|
|
1269
|
+
typedArray: edgeFeatureIds,
|
|
1270
|
+
usage: BufferUsage.STATIC_DRAW,
|
|
1271
|
+
});
|
|
1272
|
+
|
|
1273
|
+
attributes.push({
|
|
1274
|
+
index: edgeFeatureIdLocation,
|
|
1275
|
+
vertexBuffer: edgeFeatureIdBuffer,
|
|
1276
|
+
componentsPerAttribute: 1,
|
|
1277
|
+
componentDatatype: ComponentDatatype.FLOAT,
|
|
1278
|
+
normalize: false,
|
|
1279
|
+
});
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
790
1282
|
}
|
|
791
1283
|
|
|
1284
|
+
const vertexArray = new VertexArray({
|
|
1285
|
+
context,
|
|
1286
|
+
attributes,
|
|
1287
|
+
indexBuffer,
|
|
1288
|
+
});
|
|
1289
|
+
|
|
792
1290
|
return {
|
|
793
1291
|
vertexArray,
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
1292
|
+
indexCount: numIndices,
|
|
1293
|
+
hasEdgeFeatureIds:
|
|
1294
|
+
defined(primitive.featureIds) && primitive.featureIds.length > 0,
|
|
797
1295
|
};
|
|
798
1296
|
}
|
|
799
1297
|
|