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

JSM Loaders: Create ES modules #15656

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
456 changes: 456 additions & 0 deletions examples/jsm/Volume.js

Large diffs are not rendered by default.

228 changes: 228 additions & 0 deletions examples/jsm/VolumeSlice.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
/**
* This class has been made to hold a slice of a volume data
* @class
* @author Valentin Demeusy / https://github.com/stity
* @param {Volume} volume The associated volume
* @param {number} [index=0] The index of the slice
* @param {string} [axis='z'] For now only 'x', 'y' or 'z' but later it will change to a normal vector
* @see Volume
*/
import {
ClampToEdgeWrapping,
DoubleSide,
LinearFilter,
Mesh,
MeshBasicMaterial,
PlaneBufferGeometry,
Texture,
} from "../../build/three.module.js";

var VolumeSlice = function ( volume, index, axis ) {

var slice = this;
/**
* @member {Volume} volume The associated volume
*/
this.volume = volume;
/**
* @member {Number} index The index of the slice, if changed, will automatically call updateGeometry at the next repaint
*/
index = index || 0;
Object.defineProperty( this, 'index', {
get: function () {

return index;

},
set: function ( value ) {

index = value;
slice.geometryNeedsUpdate = true;
return index;

}
} );
/**
* @member {String} axis The normal axis
*/
this.axis = axis || 'z';

/**
* @member {HTMLCanvasElement} canvas The final canvas used for the texture
*/
/**
* @member {CanvasRenderingContext2D} ctx Context of the canvas
*/
this.canvas = document.createElement( 'canvas' );
/**
* @member {HTMLCanvasElement} canvasBuffer The intermediary canvas used to paint the data
*/
/**
* @member {CanvasRenderingContext2D} ctxBuffer Context of the canvas buffer
*/
this.canvasBuffer = document.createElement( 'canvas' );
this.updateGeometry();


var canvasMap = new Texture( this.canvas );
canvasMap.minFilter = LinearFilter;
canvasMap.wrapS = canvasMap.wrapT = ClampToEdgeWrapping;
var material = new MeshBasicMaterial( { map: canvasMap, side: DoubleSide, transparent: true } );
/**
* @member {Mesh} mesh The mesh ready to get used in the scene
*/
this.mesh = new Mesh( this.geometry, material );
/**
* @member {Boolean} geometryNeedsUpdate If set to true, updateGeometry will be triggered at the next repaint
*/
this.geometryNeedsUpdate = true;
this.repaint();

/**
* @member {Number} iLength Width of slice in the original coordinate system, corresponds to the width of the buffer canvas
*/

/**
* @member {Number} jLength Height of slice in the original coordinate system, corresponds to the height of the buffer canvas
*/

/**
* @member {Function} sliceAccess Function that allow the slice to access right data
* @see Volume.extractPerpendicularPlane
* @param {Number} i The first coordinate
* @param {Number} j The second coordinate
* @returns {Number} the index corresponding to the voxel in volume.data of the given position in the slice
*/


};

VolumeSlice.prototype = {

constructor: VolumeSlice,

/**
* @member {Function} repaint Refresh the texture and the geometry if geometryNeedsUpdate is set to true
* @memberof VolumeSlice
*/
repaint: function () {

if ( this.geometryNeedsUpdate ) {

this.updateGeometry();

}

var iLength = this.iLength,
jLength = this.jLength,
sliceAccess = this.sliceAccess,
volume = this.volume,
canvas = this.canvasBuffer,
ctx = this.ctxBuffer;


// get the imageData and pixel array from the canvas
var imgData = ctx.getImageData( 0, 0, iLength, jLength );
var data = imgData.data;
var volumeData = volume.data;
var upperThreshold = volume.upperThreshold;
var lowerThreshold = volume.lowerThreshold;
var windowLow = volume.windowLow;
var windowHigh = volume.windowHigh;

// manipulate some pixel elements
var pixelCount = 0;

if ( volume.dataType === 'label' ) {

//this part is currently useless but will be used when colortables will be handled
for ( var j = 0; j < jLength; j ++ ) {

for ( var i = 0; i < iLength; i ++ ) {

var label = volumeData[ sliceAccess( i, j ) ];
label = label >= this.colorMap.length ? ( label % this.colorMap.length ) + 1 : label;
var color = this.colorMap[ label ];
data[ 4 * pixelCount ] = ( color >> 24 ) & 0xff;
data[ 4 * pixelCount + 1 ] = ( color >> 16 ) & 0xff;
data[ 4 * pixelCount + 2 ] = ( color >> 8 ) & 0xff;
data[ 4 * pixelCount + 3 ] = color & 0xff;
pixelCount ++;

}

}

} else {

for ( var j = 0; j < jLength; j ++ ) {

for ( var i = 0; i < iLength; i ++ ) {

var value = volumeData[ sliceAccess( i, j ) ];
var alpha = 0xff;
//apply threshold
alpha = upperThreshold >= value ? ( lowerThreshold <= value ? alpha : 0 ) : 0;
//apply window level
value = Math.floor( 255 * ( value - windowLow ) / ( windowHigh - windowLow ) );
value = value > 255 ? 255 : ( value < 0 ? 0 : value | 0 );

data[ 4 * pixelCount ] = value;
data[ 4 * pixelCount + 1 ] = value;
data[ 4 * pixelCount + 2 ] = value;
data[ 4 * pixelCount + 3 ] = alpha;
pixelCount ++;

}

}

}
ctx.putImageData( imgData, 0, 0 );
this.ctx.drawImage( canvas, 0, 0, iLength, jLength, 0, 0, this.canvas.width, this.canvas.height );


this.mesh.material.map.needsUpdate = true;

},

/**
* @member {Function} Refresh the geometry according to axis and index
* @see Volume.extractPerpendicularPlane
* @memberof VolumeSlice
*/
updateGeometry: function () {

var extracted = this.volume.extractPerpendicularPlane( this.axis, this.index );
this.sliceAccess = extracted.sliceAccess;
this.jLength = extracted.jLength;
this.iLength = extracted.iLength;
this.matrix = extracted.matrix;

this.canvas.width = extracted.planeWidth;
this.canvas.height = extracted.planeHeight;
this.canvasBuffer.width = this.iLength;
this.canvasBuffer.height = this.jLength;
this.ctx = this.canvas.getContext( '2d' );
this.ctxBuffer = this.canvasBuffer.getContext( '2d' );

if ( this.geometry ) this.geometry.dispose(); // dispose existing geometry

this.geometry = new PlaneBufferGeometry( extracted.planeWidth, extracted.planeHeight );

if ( this.mesh ) {

this.mesh.geometry = this.geometry;
//reset mesh matrix
this.mesh.matrix.identity();
this.mesh.applyMatrix( this.matrix );

}

this.geometryNeedsUpdate = false;

}

};

export { VolumeSlice };
78 changes: 78 additions & 0 deletions examples/jsm/curves/NURBSCurve.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* @author renej
* NURBS curve object
*
* Derives from Curve, overriding getPoint and getTangent.
*
* Implementation is based on (x, y [, z=0 [, w=1]]) control points with w=weight.
*
**/


/**************************************************************
* NURBS curve
**************************************************************/

import {
Curve,
Vector3,
Vector4,
} from '../../../build/three.module.js';
import { NURBSUtils } from './NURBSUtils';

var NURBSCurve = function ( degree, knots /* array of reals */, controlPoints /* array of Vector(2|3|4) */, startKnot /* index in knots */, endKnot /* index in knots */ ) {

Curve.call( this );

this.degree = degree;
this.knots = knots;
this.controlPoints = [];
// Used by periodic NURBS to remove hidden spans
this.startKnot = startKnot || 0;
this.endKnot = endKnot || ( this.knots.length - 1 );
for ( var i = 0; i < controlPoints.length; ++ i ) {

// ensure Vector4 for control points
var point = controlPoints[ i ];
this.controlPoints[ i ] = new Vector4( point.x, point.y, point.z, point.w );

}

};


NURBSCurve.prototype = Object.create( Curve.prototype );
NURBSCurve.prototype.constructor = NURBSCurve;


NURBSCurve.prototype.getPoint = function ( t ) {

var u = this.knots[ this.startKnot ] + t * ( this.knots[ this.endKnot ] - this.knots[ this.startKnot ] ); // linear mapping t->u

// following results in (wx, wy, wz, w) homogeneous point
var hpoint = NURBSUtils.calcBSplinePoint( this.degree, this.knots, this.controlPoints, u );

if ( hpoint.w != 1.0 ) {

// project to 3D space: (wx, wy, wz, w) -> (x, y, z, 1)
hpoint.divideScalar( hpoint.w );

}

return new Vector3( hpoint.x, hpoint.y, hpoint.z );

};


NURBSCurve.prototype.getTangent = function ( t ) {

var u = this.knots[ 0 ] + t * ( this.knots[ this.knots.length - 1 ] - this.knots[ 0 ] );
var ders = NURBSUtils.calcNURBSDerivatives( this.degree, this.knots, this.controlPoints, u, 1 );
var tangent = ders[ 1 ].clone();
tangent.normalize();

return tangent;

};

export { NURBSCurve };
60 changes: 60 additions & 0 deletions examples/jsm/curves/NURBSSurface.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* @author renej
* NURBS surface object
*
* Implementation is based on (x, y [, z=0 [, w=1]]) control points with w=weight.
*
**/


import { NURBSUtils } from "./NURBSUtils";
import {
Vector4,
} from "../../../build/three.module.js";

/**************************************************************
* NURBS surface
**************************************************************/

var NURBSSurface = function ( degree1, degree2, knots1, knots2 /* arrays of reals */, controlPoints /* array^2 of Vector(2|3|4) */ ) {

this.degree1 = degree1;
this.degree2 = degree2;
this.knots1 = knots1;
this.knots2 = knots2;
this.controlPoints = [];

var len1 = knots1.length - degree1 - 1;
var len2 = knots2.length - degree2 - 1;

// ensure Vector4 for control points
for ( var i = 0; i < len1; ++ i ) {

this.controlPoints[ i ] = [];
for ( var j = 0; j < len2; ++ j ) {

var point = controlPoints[ i ][ j ];
this.controlPoints[ i ][ j ] = new Vector4( point.x, point.y, point.z, point.w );

}

}

};


NURBSSurface.prototype = {

constructor: NURBSSurface,

getPoint: function ( t1, t2, target ) {

var u = this.knots1[ 0 ] + t1 * ( this.knots1[ this.knots1.length - 1 ] - this.knots1[ 0 ] ); // linear mapping t1->u
var v = this.knots2[ 0 ] + t2 * ( this.knots2[ this.knots2.length - 1 ] - this.knots2[ 0 ] ); // linear mapping t2->u

NURBSUtils.calcSurfacePoint( this.degree1, this.degree2, this.knots1, this.knots2, this.controlPoints, u, v, target );

}
};

export { NURBSSurface };
Loading