Skip to content

Commit 7addc1e

Browse files
committed
feat(objwriter): add support for vtkOBJWriter
1 parent 572238a commit 7addc1e

File tree

3 files changed

+415
-0
lines changed

3 files changed

+415
-0
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import '@kitware/vtk.js/favicon';
2+
3+
// Load the rendering pieces we want to use (for both WebGL and WebGPU)
4+
import '@kitware/vtk.js/Rendering/Profiles/Geometry';
5+
6+
import '@kitware/vtk.js/IO/Core/DataAccessHelper/HttpDataAccessHelper'; // HTTP + zip
7+
8+
import macro from '@kitware/vtk.js/macros';
9+
import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray';
10+
import vtkPolyData from '@kitware/vtk.js/Common/DataModel/PolyData';
11+
import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow';
12+
import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor';
13+
import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper';
14+
import vtkSphereSource from '@kitware/vtk.js/Filters/Sources/SphereSource';
15+
import vtkTexture from '@kitware/vtk.js/Rendering/Core/Texture';
16+
import vtkImageGridSource from '@kitware/vtk.js/Filters/Sources/ImageGridSource';
17+
import vtkOBJWriter from '@kitware/vtk.js/IO/Misc/OBJWriter';
18+
19+
// ----------------------------------------------------------------------------
20+
// Standard rendering code setup
21+
// ----------------------------------------------------------------------------
22+
23+
const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance();
24+
const renderer = fullScreenRenderer.getRenderer();
25+
const renderWindow = fullScreenRenderer.getRenderWindow();
26+
27+
const resetCamera = renderer.resetCamera;
28+
const render = renderWindow.render;
29+
30+
const gridSource = vtkImageGridSource.newInstance();
31+
gridSource.setDataExtent(0, 511, 0, 511, 0, 0);
32+
gridSource.setGridSpacing(16, 16, 0);
33+
gridSource.setGridOrigin(8, 8, 0);
34+
35+
const texture = vtkTexture.newInstance();
36+
texture.setInterpolate(true);
37+
texture.setInputConnection(gridSource.getOutputPort());
38+
39+
const sphereSource = vtkSphereSource.newInstance();
40+
sphereSource.setThetaResolution(64);
41+
sphereSource.setPhiResolution(32);
42+
43+
const actor = vtkActor.newInstance();
44+
const mapper = vtkMapper.newInstance();
45+
46+
// create a filter on the fly to generate tcoords from normals
47+
const tcoordFilter = macro.newInstance((publicAPI, model) => {
48+
macro.obj(publicAPI, model); // make it an object
49+
macro.algo(publicAPI, model, 1, 1); // mixin algorithm code 1 in, 1 out
50+
publicAPI.requestData = (inData, outData) => {
51+
// implement requestData
52+
if (!outData[0] || inData[0].getMTime() > outData[0].getMTime()) {
53+
// use the normals to generate tcoords :-)
54+
const norms = inData[0].getPointData().getNormals();
55+
56+
const newArray = new Float32Array(norms.getNumberOfTuples() * 2);
57+
const ndata = norms.getData();
58+
for (let i = 0; i < newArray.length; i += 2) {
59+
newArray[i] =
60+
Math.abs(Math.atan2(ndata[(i / 2) * 3], ndata[(i / 2) * 3 + 1])) /
61+
3.1415927;
62+
newArray[i + 1] = Math.asin(ndata[(i / 2) * 3 + 2] / 3.1415927) + 0.5;
63+
}
64+
65+
const da = vtkDataArray.newInstance({
66+
numberOfComponents: 2,
67+
values: newArray,
68+
});
69+
da.setName('tcoord');
70+
71+
const pd = vtkPolyData.newInstance();
72+
pd.setPolys(inData[0].getPolys());
73+
pd.setPoints(inData[0].getPoints());
74+
const cpd = pd.getPointData();
75+
cpd.addArray(da);
76+
cpd.setActiveTCoords(da.getName());
77+
outData[0] = pd;
78+
}
79+
};
80+
})();
81+
82+
tcoordFilter.setInputConnection(sphereSource.getOutputPort());
83+
mapper.setInputConnection(tcoordFilter.getOutputPort());
84+
85+
actor.setMapper(mapper);
86+
actor.addTexture(texture);
87+
88+
renderer.addActor(actor);
89+
resetCamera();
90+
render();
91+
92+
const writer = vtkOBJWriter.newInstance({
93+
textureFileName: 'grid.png',
94+
});
95+
console.log(writer);
96+
97+
writer.setInputData(sphereSource.getOutputData(), 0);
98+
writer.setInputData(gridSource.getOutputData(), 1);
99+
writer.setTextureFileName('grid.png');
100+
101+
// const objContent = writer.getOutputData();
102+
// const mtlContent = writer.getMtl();
103+
104+
const zip = writer.exportAsZIP();
105+
106+
// Can also use a static function to write to OBJ:
107+
// const fileContents = vtkOBJWriter.writeOBJ(reader.getOutputData());
108+
109+
// Add a download link for it
110+
const blob = new Blob([zip], {
111+
type: 'application/octet-steam',
112+
});
113+
const a = window.document.createElement('a');
114+
a.href = window.URL.createObjectURL(blob, {
115+
type: 'application/zip',
116+
});
117+
a.download = 'sphere.zip';
118+
a.text = 'Download';
119+
a.style.position = 'absolute';
120+
a.style.left = '50%';
121+
a.style.bottom = '10px';
122+
document.body.appendChild(a);
123+
a.style.background = 'white';
124+
a.style.padding = '5px';
125+
126+
global.writer = writer;
127+
global.fullScreenRenderer = fullScreenRenderer;

Sources/IO/Misc/OBJWriter/index.d.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import vtkPolyData from '../../../Common/DataModel/PolyData';
2+
import { vtkAlgorithm, vtkObject } from '../../../interfaces';
3+
4+
/**
5+
*
6+
*/
7+
export interface IOBJWriterInitialValues {}
8+
9+
type vtkOBJWriterBase = vtkObject & vtkAlgorithm;
10+
11+
export interface vtkOBJWriter extends vtkOBJWriterBase {
12+
/**
13+
*
14+
* @param inData
15+
* @param outData
16+
*/
17+
requestData(inData: any, outData: any): void;
18+
}
19+
20+
/**
21+
* Method used to decorate a given object (publicAPI+model) with vtkOBJWriter characteristics.
22+
*
23+
* @param publicAPI object on which methods will be bounds (public)
24+
* @param model object on which data structure will be bounds (protected)
25+
* @param {IOBJWriterInitialValues} [initialValues] (default: {})
26+
*/
27+
export function extend(
28+
publicAPI: object,
29+
model: object,
30+
initialValues?: IOBJWriterInitialValues
31+
): void;
32+
33+
/**
34+
* Method used to create a new instance of vtkOBJWriter
35+
* @param {IOBJWriterInitialValues} [initialValues] for pre-setting some of its content
36+
*/
37+
export function newInstance(
38+
initialValues?: IOBJWriterInitialValues
39+
): vtkOBJWriter;
40+
41+
/**
42+
*
43+
* @param {vktPolyData} polyData
44+
*/
45+
export function writeOBJ(polyData: vtkPolyData): vtkPolyData;
46+
47+
/**
48+
* vtkOBJWriter writes wavefront obj (.obj) files in ASCII form. OBJ files
49+
* contain the geometry including lines, triangles and polygons. Normals and
50+
* texture coordinates on points are also written if they exist.
51+
*/
52+
export declare const vtkOBJWriter: {
53+
newInstance: typeof newInstance;
54+
extend: typeof extend;
55+
writeOBJ: typeof writeOBJ;
56+
};
57+
export default vtkOBJWriter;

0 commit comments

Comments
 (0)