-
-
Notifications
You must be signed in to change notification settings - Fork 385
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(polydatacellnormals): compute cell normals #2436
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import 'vtk.js/Sources/favicon'; | ||
|
||
// Load the rendering pieces we want to use (for both WebGL and WebGPU) | ||
import 'vtk.js/Sources/Rendering/Profiles/Geometry'; | ||
|
||
import vtkFullScreenRenderWindow from 'vtk.js/Sources/Rendering/Misc/FullScreenRenderWindow'; | ||
import vtkActor from 'vtk.js/Sources/Rendering/Core/Actor'; | ||
import vtkMapper from 'vtk.js/Sources/Rendering/Core/Mapper'; | ||
import vtkLineSource from 'vtk.js/Sources/Filters/Sources/LineSource'; | ||
import vtkSphereSource from 'vtk.js/Sources/Filters/Sources/SphereSource'; | ||
|
||
import vtkPolyDataNormals from 'vtk.js/Sources/Filters/Core/PolyDataNormals'; | ||
|
||
// ---------------------------------------------------------------------------- | ||
// Standard rendering code setup | ||
// ---------------------------------------------------------------------------- | ||
|
||
const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance(); | ||
const renderer = fullScreenRenderer.getRenderer(); | ||
const renderWindow = fullScreenRenderer.getRenderWindow(); | ||
|
||
const computeNormals = vtkPolyDataNormals.newInstance(); | ||
|
||
const sphere = vtkSphereSource.newInstance({ | ||
thetaResolution: 4, | ||
phiResolution: 4, | ||
}); | ||
const polydata = sphere.getOutputData(); | ||
|
||
const mapper = vtkMapper.newInstance(); | ||
const actor = vtkActor.newInstance(); | ||
|
||
actor.setMapper(mapper); | ||
mapper.setInputData(polydata); | ||
|
||
renderer.addActor(actor); | ||
|
||
computeNormals.setInputData(polydata); | ||
computeNormals.setComputeCellNormals(true); | ||
computeNormals.update(); | ||
|
||
const cellNormals = computeNormals.getOutputData().getCellData().getNormals(); | ||
|
||
const pointsData = polydata.getPoints().getData(); | ||
const polysData = polydata.getPolys().getData(); | ||
|
||
let numberOfPoints = 0; | ||
const cellPointIds = [0, 0, 0]; | ||
let normalId = 0; | ||
|
||
for (let c = 0; c < polysData.length; c += numberOfPoints + 1) { | ||
numberOfPoints = polysData[c]; | ||
|
||
if (numberOfPoints < 3) { | ||
continue; // eslint-disable-line | ||
} | ||
|
||
for (let i = 1; i <= 3; ++i) { | ||
cellPointIds[i - 1] = 3 * polysData[c + i]; | ||
} | ||
|
||
const v1 = pointsData.slice(cellPointIds[0], cellPointIds[0] + 3); | ||
const v2 = pointsData.slice(cellPointIds[1], cellPointIds[1] + 3); | ||
const v3 = pointsData.slice(cellPointIds[2], cellPointIds[2] + 3); | ||
|
||
const center = [ | ||
(v1[0] + v2[0] + v3[0]) / 3, | ||
(v1[1] + v2[1] + v3[1]) / 3, | ||
(v1[2] + v2[2] + v3[2]) / 3, | ||
]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like a good candidate to be exposed publicly in vtkTriangle as a static function. |
||
|
||
const line = vtkLineSource.newInstance({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how about an arrow source instead ? (alternatively, you can consider vtkGlyphMapper3D) |
||
point1: center, | ||
point2: [ | ||
center[0] + cellNormals[normalId++], | ||
center[1] + cellNormals[normalId++], | ||
center[2] + cellNormals[normalId++], | ||
], | ||
}); | ||
|
||
const lineMapper = vtkMapper.newInstance(); | ||
const lineActor = vtkActor.newInstance(); | ||
|
||
lineActor.setMapper(lineMapper); | ||
lineMapper.setInputData(line.getOutputData()); | ||
renderer.addActor(lineActor); | ||
} | ||
|
||
// Display the resulting STL | ||
renderer.resetCamera(); | ||
renderWindow.render(); | ||
|
||
global.renderer = renderer; | ||
global.renderWindow = renderWindow; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,11 @@ import vtkMath from 'vtk.js/Sources/Common/Core/Math/index'; | |
import vtkPolyData from 'vtk.js/Sources/Common/DataModel/PolyData'; | ||
import vtkTriangle from 'vtk.js/Sources/Common/DataModel/Triangle'; | ||
|
||
export const NormalType = { | ||
CELL: 'cell', | ||
POINT: ' point', | ||
}; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does not seem used, is it ? |
||
// ---------------------------------------------------------------------------- | ||
// vtkPolyDataNormals methods | ||
// ---------------------------------------------------------------------------- | ||
|
@@ -69,6 +74,49 @@ function vtkPolyDataNormals(publicAPI, model) { | |
return normalsData; | ||
}; | ||
|
||
publicAPI.vtkPolyDataCellNormalsExecute = (polyData) => { | ||
const pointsData = polyData.getPoints().getData(); | ||
const polysData = polyData.getPolys().getData(); | ||
const numPolys = polyData.getPolys().getNumberOfCells(); | ||
|
||
if (!pointsData || !polysData) { | ||
return null; | ||
} | ||
|
||
const normalsData = new Float32Array(numPolys * 3); | ||
|
||
let normalsIndex = 0; | ||
let numberOfPoints = 0; | ||
const cellPointIds = [0, 0, 0]; | ||
|
||
for (let c = 0; c < polysData.length; c += numberOfPoints + 1) { | ||
numberOfPoints = polysData[c]; | ||
|
||
if (numberOfPoints < 3) { | ||
continue; // eslint-disable-line | ||
} | ||
|
||
for (let i = 1; i <= 3; ++i) { | ||
cellPointIds[i - 1] = 3 * polysData[c + i]; | ||
} | ||
|
||
const cellNormal = []; | ||
|
||
vtkTriangle.computeNormal( | ||
pointsData.slice(cellPointIds[0], cellPointIds[0] + 3), | ||
pointsData.slice(cellPointIds[1], cellPointIds[1] + 3), | ||
pointsData.slice(cellPointIds[2], cellPointIds[2] + 3), | ||
cellNormal | ||
); | ||
|
||
normalsData[normalsIndex++] = cellNormal[0]; | ||
normalsData[normalsIndex++] = cellNormal[1]; | ||
normalsData[normalsIndex++] = cellNormal[2]; | ||
} | ||
|
||
return normalsData; | ||
}; | ||
|
||
publicAPI.requestData = (inData, outData) => { | ||
const numberOfInputs = publicAPI.getNumberOfInputPorts(); | ||
|
||
|
@@ -105,6 +153,13 @@ function vtkPolyDataNormals(publicAPI, model) { | |
|
||
output.getPointData().setNormals(outputNormals); | ||
|
||
if (model.computeCellNormals) { | ||
const outputCellNormalsData = | ||
publicAPI.vtkPolyDataCellNormalsExecute(input); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's too bad you are recomputing the normals that were computed when doing points normals. Can you please modify |
||
|
||
output.getCellData().setNormals(outputCellNormalsData); | ||
} | ||
|
||
outData[0] = output; | ||
}; | ||
} | ||
|
@@ -130,6 +185,8 @@ export function extend(publicAPI, model, initialValues = {}) { | |
|
||
macro.algo(publicAPI, model, 1, 1); | ||
|
||
macro.setGet(publicAPI, model, ['computeCellNormals']); | ||
|
||
/* Object specific methods */ | ||
|
||
vtkPolyDataNormals(publicAPI, model); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indent pb