Skip to content

Commit 5df0b14

Browse files
committed
implement picking
1 parent 28509ff commit 5df0b14

File tree

5 files changed

+99
-117
lines changed

5 files changed

+99
-117
lines changed

lib/cone-position.glsl

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
vec3 getOrthogonalVector(vec3 v) {
2+
// Return up-vector for only-z vector.
3+
// Return ax + by + cz = 0, a point that lies on the plane that has v as a normal and that isn't (0,0,0).
4+
// From the above if-statement we have ||a|| > 0 U ||b|| > 0.
5+
// Assign z = 0, x = -b, y = a:
6+
// a*-b + b*a + c*0 = -ba + ba + 0 = 0
7+
if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {
8+
return normalize(vec3(-v.y, v.x, 0.0));
9+
} else {
10+
return normalize(vec3(0.0, v.z, -v.y));
11+
}
12+
}
13+
14+
// Calculate the cone vertex and normal at the given index.
15+
//
16+
// The returned vertex is for a cone with its top at origin and height of 1.0,
17+
// pointing in the direction of the vector attribute.
18+
//
19+
// Each cone is made up of a top vertex, a center base vertex and base perimeter vertices.
20+
// These vertices are used to make up the triangles of the cone by the following:
21+
// segment + 0 top vertex
22+
// segment + 1 perimeter vertex a+1
23+
// segment + 2 perimeter vertex a
24+
// segment + 3 center base vertex
25+
// segment + 4 perimeter vertex a
26+
// segment + 5 perimeter vertex a+1
27+
// Where segment is the number of the radial segment * 6 and a is the angle at that radial segment.
28+
// To go from index to segment, floor(index / 6)
29+
// To go from segment to angle, 2*pi * (segment/segmentCount)
30+
// To go from index to segment index, index - (segment*6)
31+
//
32+
vec3 getConePosition(vec3 d, float index, float coneOffset, out vec3 normal) {
33+
34+
const float segmentCount = 8.0;
35+
36+
index = mod(index, segmentCount * 6.0);
37+
38+
float segment = floor(index/6.0);
39+
float segmentIndex = index - (segment*6.0);
40+
41+
normal = -normalize(d);
42+
43+
if (segmentIndex == 3.0) {
44+
return mix(vec3(0.0), -d, coneOffset);
45+
}
46+
47+
// angle = 2pi * ((segment + ((segmentIndex == 1.0 || segmentIndex == 5.0) ? 1.0 : 0.0)) / segmentCount)
48+
float nextAngle = float(segmentIndex == 1.0 || segmentIndex == 5.0);
49+
float angle = 2.0 * 3.14159 * ((segment + nextAngle) / segmentCount);
50+
51+
vec3 v1 = mix(d, vec3(0.0), coneOffset);
52+
vec3 v2 = v1 - d;
53+
54+
vec3 u = getOrthogonalVector(d);
55+
vec3 v = normalize(cross(u, d));
56+
57+
vec3 x = u * cos(angle) * length(d)*0.25;
58+
vec3 y = v * sin(angle) * length(d)*0.25;
59+
vec3 v3 = v2 + x + y;
60+
if (segmentIndex <= 2.0) {
61+
vec3 tx = u * sin(angle);
62+
vec3 ty = v * -cos(angle);
63+
vec3 tangent = tx + ty;
64+
normal = normalize(cross(v3 - v1, tangent));
65+
}
66+
67+
if (segmentIndex == 0.0) {
68+
return mix(d, vec3(0.0), coneOffset);
69+
}
70+
return v3;
71+
}
72+
73+
#pragma glslify: export(getConePosition)

lib/conemesh.js

+7-36
Original file line numberDiff line numberDiff line change
@@ -787,43 +787,13 @@ proto.pick = function(pickData) {
787787

788788
var cellId = pickData.value[0] + 256*pickData.value[1] + 65536*pickData.value[2]
789789
var cell = this.cells[cellId]
790-
var positions = this.positions
791-
792-
var simplex = new Array(cell.length)
793-
for(var i=0; i<cell.length; ++i) {
794-
simplex[i] = positions[cell[i]]
795-
}
796-
797-
var data = closestPoint(
798-
simplex,
799-
[pickData.coord[0], this._resolution[1]-pickData.coord[1]],
800-
this._model,
801-
this._view,
802-
this._projection,
803-
this._resolution)
804-
805-
if(!data) {
806-
return null
807-
}
808-
809-
var weights = data[2]
810-
var interpIntensity = 0.0
811-
for(var i=0; i<cell.length; ++i) {
812-
interpIntensity += weights[i] * this.intensity[cell[i]]
813-
}
790+
var pos = this.positions[cell[1]].slice(0, 3)
814791

815792
return {
816-
position: data[1],
817-
index: cell[data[0]],
818-
cell: cell,
819-
cellId: cellId,
820-
intensity: interpIntensity,
821-
822-
vectorScale: this.vectorScale,
823-
coneScale: this.coneScale,
824-
coneOffset: this.coneOffset,
825-
826-
dataCoordinate: this.positions[cell[data[0]]]
793+
// corresponding to input indices
794+
index: Math.floor(cell[1] / 48),
795+
position: pos,
796+
dataCoordinate: pos
827797
}
828798
}
829799

@@ -892,9 +862,10 @@ function createPointShader(gl) {
892862
}
893863

894864
function createPickShader(gl) {
895-
var shader = createShader(gl, pickShader.vertex, pickShader.fragment)
865+
var shader = createShader(gl, pickShader.vertex, pickShader.fragment, null, pickShader.attributes)
896866
shader.attributes.position.location = 0
897867
shader.attributes.id.location = 1
868+
shader.attributes.vector.location = 5
898869
return shader
899870
}
900871

lib/pick-vertex.glsl

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11
precision mediump float;
22

3-
attribute vec3 position;
3+
#pragma glslify: getConePosition = require(./cone-position.glsl)
4+
5+
attribute vec3 vector;
6+
attribute vec4 position;
47
attribute vec4 id;
58

69
uniform mat4 model, view, projection;
710

11+
uniform float vectorScale;
12+
uniform float coneScale;
13+
uniform float coneOffset;
14+
815
varying vec3 f_position;
916
varying vec4 f_id;
1017

1118
void main() {
12-
gl_Position = projection * view * model * vec4(position, 1.0);
19+
vec3 normal;
20+
vec4 conePosition = model * vec4(position.xyz, 1.0) + vec4(getConePosition(mat3(model) * ((vectorScale * coneScale) * vector), position.w, coneOffset, normal), 0.0);
21+
gl_Position = projection * view * conePosition;
1322
f_id = id;
14-
f_position = position;
15-
}
23+
f_position = position.xyz;
24+
}

lib/shaders.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ exports.pickShader = {
2020
vertex: pickVertSrc,
2121
fragment: pickFragSrc,
2222
attributes: [
23-
{name: 'position', type: 'vec3'},
24-
{name: 'id', type: 'vec4'}
23+
{name: 'position', type: 'vec4'},
24+
{name: 'id', type: 'vec4'},
25+
{name: 'vector', type: 'vec3'}
2526
]
2627
}

lib/triangle-vertex.glsl

+3-75
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
precision mediump float;
22

33
#pragma glslify: inverse = require(glsl-inverse)
4+
#pragma glslify: getConePosition = require(./cone-position.glsl)
45

56
attribute vec3 vector;
67
attribute vec4 color, position;
@@ -23,84 +24,11 @@ varying vec3 f_normal
2324
varying vec4 f_color;
2425
varying vec2 f_uv;
2526

26-
27-
vec3 getOrthogonalVector(vec3 v) {
28-
// Return up-vector for only-z vector.
29-
// Return ax + by + cz = 0, a point that lies on the plane that has v as a normal and that isn't (0,0,0).
30-
// From the above if-statement we have ||a|| > 0 U ||b|| > 0.
31-
// Assign z = 0, x = -b, y = a:
32-
// a*-b + b*a + c*0 = -ba + ba + 0 = 0
33-
if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {
34-
return normalize(vec3(-v.y, v.x, 0.0));
35-
} else {
36-
return normalize(vec3(0.0, v.z, -v.y));
37-
}
38-
}
39-
40-
// Calculate the cone vertex and normal at the given index.
41-
//
42-
// The returned vertex is for a cone with its top at origin and height of 1.0,
43-
// pointing in the direction of the vector attribute.
44-
//
45-
// Each cone is made up of a top vertex, a center base vertex and base perimeter vertices.
46-
// These vertices are used to make up the triangles of the cone by the following:
47-
// segment + 0 top vertex
48-
// segment + 1 perimeter vertex a+1
49-
// segment + 2 perimeter vertex a
50-
// segment + 3 center base vertex
51-
// segment + 4 perimeter vertex a
52-
// segment + 5 perimeter vertex a+1
53-
// Where segment is the number of the radial segment * 6 and a is the angle at that radial segment.
54-
// To go from index to segment, floor(index / 6)
55-
// To go from segment to angle, 2*pi * (segment/segmentCount)
56-
// To go from index to segment index, index - (segment*6)
57-
//
58-
vec3 getConePosition(vec3 d, float index, out vec3 normal) {
59-
60-
const float segmentCount = 8.0;
61-
62-
index = mod(index, segmentCount * 6.0);
63-
64-
float segment = floor(index/6.0);
65-
float segmentIndex = index - (segment*6.0);
66-
67-
normal = -normalize(d);
68-
69-
if (segmentIndex == 3.0) {
70-
return mix(vec3(0.0), -d, coneOffset);
71-
}
72-
73-
// angle = 2pi * ((segment + ((segmentIndex == 1.0 || segmentIndex == 5.0) ? 1.0 : 0.0)) / segmentCount)
74-
float nextAngle = float(segmentIndex == 1.0 || segmentIndex == 5.0);
75-
float angle = 2.0 * 3.14159 * ((segment + nextAngle) / segmentCount);
76-
77-
vec3 v1 = mix(d, vec3(0.0), coneOffset);
78-
vec3 v2 = v1 - d;
79-
80-
vec3 u = getOrthogonalVector(d);
81-
vec3 v = normalize(cross(u, d));
82-
83-
vec3 x = u * cos(angle) * length(d)*0.25;
84-
vec3 y = v * sin(angle) * length(d)*0.25;
85-
vec3 v3 = v2 + x + y;
86-
if (segmentIndex <= 2.0) {
87-
vec3 tx = u * sin(angle);
88-
vec3 ty = v * -cos(angle);
89-
vec3 tangent = tx + ty;
90-
normal = normalize(cross(v3 - v1, tangent));
91-
}
92-
93-
if (segmentIndex == 0.0) {
94-
return mix(d, vec3(0.0), coneOffset);
95-
}
96-
return v3;
97-
}
98-
9927
void main() {
10028
// Scale the vector magnitude to stay constant with
10129
// model & view changes.
10230
vec3 normal;
103-
vec4 conePosition = model * vec4(position.xyz, 1.0) + vec4(getConePosition(mat3(model) * ((vectorScale * coneScale) * vector), position.w, normal), 0.0);
31+
vec4 conePosition = model * vec4(position.xyz, 1.0) + vec4(getConePosition(mat3(model) * ((vectorScale * coneScale) * vector), position.w, coneOffset, normal), 0.0);
10432
normal = normalize(normal * inverse(mat3(model)));
10533

10634
// vec4 m_position = model * vec4(conePosition, 1.0);
@@ -112,4 +40,4 @@ void main() {
11240
f_eyeDirection = eyePosition - conePosition.xyz;
11341
f_lightDirection = lightPosition - conePosition.xyz;
11442
f_uv = uv;
115-
}
43+
}

0 commit comments

Comments
 (0)