# How to switch from normal mode to smooth mode?

**URL:** https://discourse.vtk.org/t/how-to-switch-from-normal-mode-to-smooth-mode/15650
**Category:** vtk.js
**Created:** [May 19, 2025, 11:48am UTC](https://discourse.vtk.org/t/how-to-switch-from-normal-mode-to-smooth-mode/15650 "2025-05-19T11:48:02Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![Bek1](https://discourse.vtk.org/user_avatar/discourse.vtk.org/bek1/32/10006_2.png) [@Bek1](https://discourse.vtk.org/u/Bek1)
#### Post date: [May 19, 2025, 11:48am UTC](https://discourse.vtk.org/t/how-to-switch-from-normal-mode-to-smooth-mode/15650/1 "2025-05-19T11:48:02Z")

</div>

Hi.  
Here is minimal code:

```typescript
function Modal(props: { stlBuffer: ArrayBuffer }) {
  const vtkContext = useRef<any>({});
  const vtkContainerRef = useRef(null);

  useEffect(() => {
    const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({ rootContainer: vtkContainerRef.current });
    const renderer = fullScreenRenderer.getRenderer();
    const renderWindow = fullScreenRenderer.getRenderWindow();
    const actor = vtkActor.newInstance();
    const mapper = vtkMapper.newInstance({ scalarVisibility: false });
    const smoothFilter = vtkWindowedSincPolyDataFilter.newInstance();
    const normals = vtkPolyDataNormals.newInstance();
    actor.setMapper(mapper);
    renderer.addActor(actor);

    const stlReader = vtkSTLReader.newInstance();
    stlReader.setRemoveDuplicateVertices(1);
    stlReader.parseAsArrayBuffer(props.stlBuffer);
    const originalPolyData = stlReader.getOutputData()

    vtkContext.current = { originalPolyData, fullScreenRenderer, renderer, renderWindow, actor, mapper, smoothFilter, normals };
  }, []);

  function makeNormalMode() {
    const { mapper, renderWindow, renderer, originalPolyData } = vtkContext.current;
    mapper.setInputData(originalPolyData);
    renderer.resetCamera();
    renderWindow.render();
  }

  function makeSmoothMode() {
    const { smoothFilter, normals, mapper, renderWindow, renderer, originalPolyData } = vtkContext.current;
    smoothFilter.setInputData(originalPolyData);
    normals.setInputData(smoothFilter.getOutputData());
    mapper.setInputData(normals.getOutputData());
    renderer.resetCamera();
    renderWindow.render();
  }

  return (
    <div>
      <Button onClick={makeNormalMode}>normal mode</Button>
      <Button onClick={makeSmoothMode}>smooth mode</Button>
      <div className="relative"><div ref={vtkContainerRef} className="relative h-[400px]"</div>
      </div>
    </div>
  );
}

```

i clicked on “normal mode” button:

 ![image](https://discourse.vtk.org/uploads/default/original/2X/b/bae36f6d4053a2ddc344fd644a7b2ddc3e425c38.png)

then clicked on “smooth mode” button and there is some issue:

 ![image](https://discourse.vtk.org/uploads/default/original/2X/4/40c6b778b4dd1f7fcbb6c246d2becf5998d817a0.png)

But if i click on “smooth mode” button first it works good:

 ![image](https://discourse.vtk.org/uploads/default/original/2X/5/5df98515bdcc4458dac4b04dcc90dc6648b32775.png)

How to switch properly between them?  
Thanks

---

<div class="post-metadata">

### Author: ![finetjul](https://discourse.vtk.org/user_avatar/discourse.vtk.org/finetjul/32/154_2.png) [@finetjul](https://discourse.vtk.org/u/finetjul)
#### Post date: [May 19, 2025, 12:13pm UTC](https://discourse.vtk.org/t/how-to-switch-from-normal-mode-to-smooth-mode/15650/2 "2025-05-19T12:13:38Z")

</div>

If you call `setInputData()` that means you must `update()` filters manually.

It is preferable to use `setInputConnection()` instead.

---

<div class="post-metadata">

### Author: ![Bek1](https://discourse.vtk.org/user_avatar/discourse.vtk.org/bek1/32/10006_2.png) [@Bek1](https://discourse.vtk.org/u/Bek1)
#### Post date: [May 19, 2025, 12:27pm UTC](https://discourse.vtk.org/t/how-to-switch-from-normal-mode-to-smooth-mode/15650/3 "2025-05-19T12:27:11Z")

</div>

Here is updated code:

```typescript
function StlModal2(props: { stlBuffer: ArrayBuffer }) {
  const vtkContext = useRef<any>({});
  const vtkContainerRef = useRef(null);

  useEffect(() => {
    const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({ rootContainer: vtkContainerRef.current });
    const renderer = fullScreenRenderer.getRenderer();
    const renderWindow = fullScreenRenderer.getRenderWindow();
    const actor = vtkActor.newInstance();
    const mapper = vtkMapper.newInstance({ scalarVisibility: false });
    const smoothFilter = vtkWindowedSincPolyDataFilter.newInstance();
    const normals = vtkPolyDataNormals.newInstance();
    actor.setMapper(mapper);
    renderer.addActor(actor);

    const stlReader = vtkSTLReader.newInstance();
    stlReader.setRemoveDuplicateVertices(1);
    stlReader.parseAsArrayBuffer(props.stlBuffer);
    const originalPolyData = stlReader.getOutputPort()

    vtkContext.current = { originalPolyData, fullScreenRenderer, renderer, renderWindow, actor, mapper, smoothFilter, normals };
  }, []);

  function makeNormalMode() {
    const { mapper, renderWindow, renderer, originalPolyData } = vtkContext.current;
    mapper.setInputConnection(originalPolyData);
    renderer.resetCamera();
    renderWindow.render();
  }

  function makeSmoothMode() {
    const { smoothFilter, normals, mapper, renderWindow, renderer, originalPolyData } = vtkContext.current;
    smoothFilter.setInputConnection(originalPolyData);
    normals.setInputConnection(smoothFilter.getOutputPort());
    mapper.setInputConnection(normals.getOutputPort());
    normals.update() 

    renderer.resetCamera();
    renderWindow.render();
  }

  return (
    <div>
      <Button onClick={makeNormalMode}>normal mode</Button>
      <Button onClick={makeSmoothMode}>smooth mode</Button>
      <div className="relative">
        <div ref={vtkContainerRef} className="relative h-[400px]"></div>
      </div>
    </div>
  );
}

```

i’ve used setInputConnection everywhere and it did not help. The only thing that changed is that when switching to smooth mode it gets laggy (normals.update() from your previous answer has no effect for some reason )

---

<div class="post-metadata">

### Author: ![finetjul](https://discourse.vtk.org/user_avatar/discourse.vtk.org/finetjul/32/154_2.png) [@finetjul](https://discourse.vtk.org/u/finetjul)
#### Post date: [May 19, 2025, 12:39pm UTC](https://discourse.vtk.org/t/how-to-switch-from-normal-mode-to-smooth-mode/15650/4 "2025-05-19T12:39:46Z")

</div>

the following is incorrect:  
`mapper.setInputConnection(originalPolyData);`

You can only do:  
`mapper.setInputConnection(reader.getOutputPort());`  
or  
`mapper.setInputData(originalPolyData);`

You can’t use a polydata in place of an output port.

---

<div class="post-metadata">

### Author: ![Bek1](https://discourse.vtk.org/user_avatar/discourse.vtk.org/bek1/32/10006_2.png) [@Bek1](https://discourse.vtk.org/u/Bek1)
#### Post date: [May 19, 2025, 12:47pm UTC](https://discourse.vtk.org/t/how-to-switch-from-normal-mode-to-smooth-mode/15650/5 "2025-05-19T12:47:26Z")

</div>

originalPolyData is getOutputPort, i just forgot to rename it in my code.

```typescript
const originalPolyData = stlReader.getOutputPort()

```

Or i misunderstood you?

---

<div class="post-metadata">

### Author: ![finetjul](https://discourse.vtk.org/user_avatar/discourse.vtk.org/finetjul/32/154_2.png) [@finetjul](https://discourse.vtk.org/u/finetjul)
#### Post date: [May 19, 2025, 12:50pm UTC](https://discourse.vtk.org/t/how-to-switch-from-normal-mode-to-smooth-mode/15650/6 "2025-05-19T12:50:00Z")

</div>

My bad, I did not read carefully.  
Not sure why it is laggy…

Can you share your code ?

---

<div class="post-metadata">

### Author: ![Bek1](https://discourse.vtk.org/user_avatar/discourse.vtk.org/bek1/32/10006_2.png) [@Bek1](https://discourse.vtk.org/u/Bek1)
#### Post date: [May 19, 2025, 12:58pm UTC](https://discourse.vtk.org/t/how-to-switch-from-normal-mode-to-smooth-mode/15650/7 "2025-05-19T12:58:15Z")

</div>

I open the component above like this:

```typescript
 <DropdownMenuItem
              onClick={async e => {
                const stlRequest = await fetch(`http://localhost:3004/pacs/get-stl/regular`, {
                  method: 'POST',
                  body: OhifDicomSegblob,
                });
                const stlBlob = await stlRequest.blob();
                const arrayBuffer = await stlBlob.arrayBuffer();

                uiModalService.show({
                  content: Modal,
                  contentProps: { stlBuffer: arrayBuffer },
                });
              }}
            >
              STL
            </DropdownMenuItem>

```

Thats it. Just get some stl blob, convert to array buffer and show modal. Should i share something else?  
Being laggy is not the main problem. It would be great to have solution to issue of rendering when switching

---

<div class="post-metadata">

### Author: ![finetjul](https://discourse.vtk.org/user_avatar/discourse.vtk.org/finetjul/32/154_2.png) [@finetjul](https://discourse.vtk.org/u/finetjul)
#### Post date: [May 19, 2025, 1:39pm UTC](https://discourse.vtk.org/t/how-to-switch-from-normal-mode-to-smooth-mode/15650/8 "2025-05-19T13:39:18Z")

</div>

I meant code without React nor Ohif. Something in 100% VTK.js (with CodeSandBox for example).

---

<div class="post-metadata">

### Author: ![Bek1](https://discourse.vtk.org/user_avatar/discourse.vtk.org/bek1/32/10006_2.png) [@Bek1](https://discourse.vtk.org/u/Bek1)
#### Post date: [May 19, 2025, 2:14pm UTC](https://discourse.vtk.org/t/how-to-switch-from-normal-mode-to-smooth-mode/15650/9 "2025-05-19T14:14:42Z")

</div>

Here is full index.html

```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://unpkg.com/vtk.js"></script>
</head>

<body>
    <div>
        <section>
            <label for="stlFile">Select STL File:</label>
            <input type="file" id="stlFile" accept=".stl">
        </section>

        <section>
            <button id="normalModeBtn">Normal Mode</button>
            <button id="smoothModeBtn">Smooth Mode</button>
        </section>

        <div id="vtkContainer" style="width: 500px; height: 400px; position: relative;"></div>
    </div>

    <script>
        let originalPortData = null;
        let fullScreenRenderer = null;
        let renderer = null;
        let renderWindow = null;
        let actor = null;
        let mapper = null;
        let smoothFilter = null;
        let normals = null;
        let stlReader = null;
        let interactor = null;

        const fileInput = document.getElementById('stlFile');
        const normalModeBtn = document.getElementById('normalModeBtn');
        const smoothModeBtn = document.getElementById('smoothModeBtn');
        const vtkContainer = document.getElementById('vtkContainer');

        fullScreenRenderer = vtk.Rendering.Misc.vtkFullScreenRenderWindow.newInstance({
            rootContainer: vtkContainer,
        });

        renderer = fullScreenRenderer.getRenderer();
        renderWindow = fullScreenRenderer.getRenderWindow();
        interactor = renderWindow.getInteractor();

        actor = vtk.Rendering.Core.vtkActor.newInstance();
        mapper = vtk.Rendering.Core.vtkMapper.newInstance({ scalarVisibility: false });
        smoothFilter = vtk.Filters.General.vtkWindowedSincPolyDataFilter.newInstance();
        normals = vtk.Filters.Core.vtkPolyDataNormals.newInstance();

        actor.setMapper(mapper);
        renderer.addActor(actor);

        stlReader = vtk.IO.Geometry.vtkSTLReader.newInstance();
        stlReader.setRemoveDuplicateVertices(1);

        fileInput.addEventListener('change', (event) => {
            const file = event.target.files[0];
            if (!file) return;

            const reader = new FileReader();
            reader.onload = function (e) {
                const fileBuffer = e.target.result;
                stlReader.parseAsArrayBuffer(fileBuffer);
                originalPortData = stlReader.getOutputPort();
            };
            reader.readAsArrayBuffer(file);
        });

        function makeNormalMode() {
            if (!originalPortData) return;
            mapper.setInputConnection(originalPortData);
            renderer.resetCamera();
            renderWindow.render();
        }

        function makeSmoothMode() {
            if (!originalPortData) return;
            smoothFilter.setInputConnection(originalPortData);
            normals.setInputConnection(smoothFilter.getOutputPort());
            mapper.setInputConnection(normals.getOutputPort());
            renderer.resetCamera();
            renderWindow.render();
        }

        normalModeBtn.addEventListener('click', makeNormalMode);
        smoothModeBtn.addEventListener('click', makeSmoothMode);
    </script>
</body>

</html>

```

also, here is STL for testing - [https://drive.google.com/file/d/1wbOWwy2U4FiHTY9HlLP8YC0OIQQJSZOx/view?usp=sharing](https://drive.google.com/file/d/1wbOWwy2U4FiHTY9HlLP8YC0OIQQJSZOx/view?usp=sharing)

---

<div class="post-metadata">

### Author: ![finetjul](https://discourse.vtk.org/user_avatar/discourse.vtk.org/finetjul/32/154_2.png) [@finetjul](https://discourse.vtk.org/u/finetjul)
#### Post date: [May 19, 2025, 5:09pm UTC](https://discourse.vtk.org/t/how-to-switch-from-normal-mode-to-smooth-mode/15650/10 "2025-05-19T17:09:02Z")

</div>

I fixed the slowness (due to infinite pipeline execution)

> <https://github.com/Kitware/vtk-js/pull/3253>
>
> \### Context
> https://discourse.vtk.org/t/how-to-switch-from-normal-mode-to-smoot…h-mode/15650
> 
> \### Results
> No infinite pipeline execution
> 
> \### Changes
> \- \[\] Documentation and TypeScript definitions were updated to match those changes
> 
> \### PR and Code Checklist
> 
> \- \[x\] \[semantic-release\](https://github.com/semantic-release/semantic-release) commit messages
> \- \[x\] Run \`npm run reformat\` to have correctly formatted code
> 
> \### Testing
> 
> \- \[\] This change adds or fixes unit tests 
> \- \[x\] Tested environment:
> - \*\*vtk.js\*\*: master
> - \*\*OS\*\*: Windows 11
> - \*\*Browser\*\*: Chrome

Regarding the rendering glitch, it seems to be an issue from the WebGL rendering.  
The vtkMapper does not seem to support changing the “input”.  
It works fine when visualizing your application in WebGPU though (add `?viewAPI=WebGPU` in your url).

One quick solution is to use a different mapper when you change your mode.

FYI @sankhesh
