Skip to content
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

Decimate does not work well with three.js #60

Open
bcipolli opened this issue Oct 7, 2015 · 4 comments
Open

Decimate does not work well with three.js #60

bcipolli opened this issue Oct 7, 2015 · 4 comments

Comments

@bcipolli
Copy link

bcipolli commented Oct 7, 2015

If I decimate the individual ROI surfaces, parse using VTKLoader.js and try to display via three.js, I get about 33% of the surfaces having invalid vertex indices that cause a javascript error (see below):

(note: If I decimate the label vtk before exploding into ROIs, I don't have the problem, but the result doesn't look great):
image

This is either an issue with decimate or the VTKLoader code. @binarybottle could you help debug? A script to reproduce this issue is attached at the bottom (requires flask)

image

import glob
import json
import os
import threading
import webbrowser

import flask

from mindboggle.mio.vtks import freesurfer_surface_to_vtk, freesurfer_annot_to_vtk, explode_scalars
from mindboggle.guts.mesh import decimate_file


subj_path = os.environ['SUBJECTS_DIR']
fsavg_path = os.path.join(subj_path, 'fsaverage')

surf_file = os.path.join(fsavg_path, 'surf', 'lh.pial')
label_file = os.path.join(fsavg_path, 'label', 'lh.aparc.annot')

surf_vtk = 'lh_surf.vtk'
label_vtk = 'lh_label.vtk'

# Convert surface and labels to vtk, break into ROIs
print('Generating vtks')
if not os.path.exists(surf_vtk):
    freesurfer_surface_to_vtk(surf_file, surf_vtk)
if not os.path.exists(label_vtk):
    freesurfer_annot_to_vtk(label_file, surf_vtk, label_vtk)

# Break into ROIs
if True:
    # downsample_vtk(label_vtk, sample_rate=sample_rate)
    explode_scalars(label_vtk, output_stem='lh_roi_')
roi_dict = dict([(i, roi_vtk) for i, roi_vtk in enumerate(glob.glob('lh_roi_*.vtk'))])

    # Downsample
if True:
    print('Downsampling vtks')
    for roi_vtk in roi_dict.values():
        decimate_file(roi_vtk, reduction=0.5, output_vtk=roi_vtk,
                      save_vtk=True, smooth_steps=0)

# Create manifest file
with open('lh.json', 'wb') as fp:
    json.dump(dict(filename=roi_dict), fp)

# Create index.html
with open('bug.html', 'wb') as fp:
    fp.write("""
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>three.js webgl - loaders - vtk loader</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <link rel="stylesheet" type="text/css" href="http://cseweb.ucsd.edu/~bcipolli/roygbiv/style.css" />

        <script src="http://cseweb.ucsd.edu/~bcipolli/roygbiv/js/three.js"></script>
        <script src="http://cseweb.ucsd.edu/~bcipolli/roygbiv/js/Projector.js"></script>
        <script src="http://cseweb.ucsd.edu/~bcipolli/roygbiv/js/Detector.js"></script>
        <script src="http://cseweb.ucsd.edu/~bcipolli/roygbiv/js/TrackballControls.js"></script>
        <script src="http://cseweb.ucsd.edu/~bcipolli/roygbiv/js/VTKLoader.js"></script>
        <script src="http://cseweb.ucsd.edu/~bcipolli/roygbiv/js/jquery.min.js"></script>
        <script src="http://cseweb.ucsd.edu/~bcipolli/roygbiv/js/angular.min.js"></script>

        <script src="http://cseweb.ucsd.edu/~bcipolli/roygbiv/brain.js"></script>
    </head>

    <body>
        <div ng-app="navigator" ng-controller="NavigateController" ng-strict-di>
            <div id="nav-brain">
            </div>
        </div>

        <script>
            angular.module('navigator', [])
            .controller('NavigateController', ['$scope', function($scope) {
                $scope.brain = new Brain({
                    divID: "nav-brain",
                    manifest: 'lh.json'
                });
            }]);
        </script>
    </body>
</html>
""")

# Launch web server
app = flask.Flask('foo')

@app.route('/<path:path>')
def send_all(path):
    return flask.send_from_directory('.', path)

threading.Timer(2.5, lambda: webbrowser.open('http://127.0.0.1:5121/bug.html')).start()
#
#print('Launching server.')
#app.debug = True
app.run(port=5121)
@bcipolli
Copy link
Author

bcipolli commented Oct 7, 2015

My current workaround: if, after decimating, I call explode_scalars to simply read/rewrite the file, it works (edit: workaround using read_vtk/write_vtk is also good):
image

I'm not sure if the file format is not compatible with three.js, or if the vtk loading code is simply more robust to errors.

@binarybottle
Copy link
Member

@bcipolli -- So that I'm clear, do you believe that the decimation function is saving the files in a format not compatible with three.js, and that reading/rewriting (with explode_scalars() or with read_vtk()/write_vtk()) results in a three.js-amenable format?

@bcipolli
Copy link
Author

@binarybottle Yes, that's my belief.

@binarybottle
Copy link
Member

Perhaps writing out the vtk file using vtk.vtkPolyDataWriter() in the decimate() function might not be the way to go. I'm not sure what to replace it with, but given that you found a workaround, would you mind submitting a pull request to include the read/rewrite so that the output of the function will behave well for future roygbiv/three.js work? Were you able to do so for files with multiple labels?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants