@@ -109,10 +109,10 @@ define([
109109 if ( 'showAnimationBar' === key_tokens [ key_tokens . length - 1 ] ) {
110110 // Show / Hide Animation bar
111111 var showAnimationBar = SplunkVisualizationUtils . normalizeBoolean ( this . _getEscapedProperty ( 'showAnimationBar' , config ) ) ;
112-
112+
113113 this . _toggleAnimationBar ( showAnimationBar ) ;
114114 return ;
115- }
115+ }
116116
117117 // Keep track of 2D-3D graph toggle
118118 this . hasToggledGraph = ( 'enable3D' === key_tokens [ key_tokens . length - 1 ] ) ;
@@ -281,17 +281,17 @@ define([
281281 if ( this . logging ) console . log ( 'updateView() - Error: no data' ) ;
282282 return ;
283283 }
284-
284+
285285 // check for data readiness
286286 if ( ! data . status ) {
287287 if ( this . logging ) console . log ( "Search job is still running. Please wait." ) ;
288288 // Trying to dispose here
289289 this . _disposeGraph ( $elem ) ;
290290 return ;
291291 }
292-
292+
293293 const isLarge = data . content . nodes . length > MIN_LARGE_GRAPH ;
294-
294+
295295 var enable3D = SplunkVisualizationUtils . normalizeBoolean ( this . _getEscapedProperty ( 'enable3D' , config ) ) ;
296296 var showAnimationBar = SplunkVisualizationUtils . normalizeBoolean ( this . _getEscapedProperty ( 'showAnimationBar' , config ) ) ;
297297 var showLinkArrows = SplunkVisualizationUtils . normalizeBoolean ( this . _getEscapedProperty ( 'showLinkArrows' , config ) ) ;
@@ -309,65 +309,60 @@ define([
309309
310310 // Show/Hide Animation Bar
311311 this . _toggleAnimationBar ( showAnimationBar ) ;
312-
313- // Dispose current graph
312+
313+ // Dispose current graph
314314 if ( this . hasToggledGraph ) {
315315 this . _disposeGraph ( $elem ) ;
316316 }
317-
318- // Create the required graph
317+
318+ // Create the required graph
319319 if ( enable3D ) {
320320 if ( this . graph == null ) {
321321 if ( this . logging ) console . log ( "updateView() - Loading [3D] graph" ) ;
322322 this . _load3DGraph ( $elem . get ( 0 ) , params ) ;
323323 }
324-
324+
325325 // Add node customisations to the 3D Graph
326326 this . graph . nodeThreeObject ( node => {
327- const obj = new THREE . Mesh ( ) ;
327+ const group = new THREE . Group ( ) ;
328328
329329 // Drawing nodes
330330 const useDefaultColor = node . has_custom_color < 1 ;
331- if ( ! useDefaultColor ) {
332- if ( node . color instanceof Array ) {
333- // Gradient
334- const geometry = new THREE . SphereGeometry ( ) ;
335- var material = new THREE . ShaderMaterial ( {
336- uniforms : {
337- color1 : {
338- value : new THREE . Color ( node . color [ 0 ] )
339- } ,
340- color2 : {
341- value : new THREE . Color ( node . color [ 1 ] )
342- }
343- } ,
344- vertexShader : `
345- varying vec2 vUv;
346-
347- void main() {
348- vUv = uv;
349- gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
350- }
351- ` ,
352- fragmentShader : `
353- uniform vec3 color1;
354- uniform vec3 color2;
355-
356- varying vec2 vUv;
357-
358- void main() {
359- gl_FragColor = vec4(mix(color1, color2, vUv.y), 1.0);
360- }
361- `
362- } ) ;
363- obj . add ( new THREE . Mesh ( geometry , material ) ) ;
331+ if ( ( ! useDefaultColor ) && ( node . color instanceof Array ) ) {
332+ // Gradient
333+ const geometry = new THREE . SphereGeometry ( ) ;
334+ const color1 = new THREE . Color ( node . color [ 0 ] ) ;
335+ const color2 = new THREE . Color ( node . color [ 1 ] ) ;
336+ const position = geometry . attributes . position ;
337+ const colors = [ ] ;
338+
339+ geometry . computeBoundingSphere ( ) ;
340+ const radius = geometry . boundingSphere . radius ;
341+
342+ // Apply vertex colors for the gradient
343+ for ( let i = 0 ; i < position . count ; i ++ ) {
344+ // Normalize vertex.y to [0, 1]
345+ const y = ( position . getY ( i ) / radius + 1 ) / 2 ;
346+ // Interpolate between color1 and color2 based on normalized y
347+ const vertexColor = color2 . clone ( ) . lerp ( color1 , y ) ;
348+ colors . push ( vertexColor . r , vertexColor . g , vertexColor . b ) ;
364349 }
365- }
366350
367- // No gradient
368- geometry = new THREE . SphereGeometry ( ) ;
369- material = new THREE . MeshBasicMaterial ( { color : useDefaultColor ? params [ 'ndColor' ] : node . color } ) ;
370- obj . add ( new THREE . Mesh ( geometry , material ) ) ;
351+ geometry . setAttribute ( 'color' , new THREE . Float32BufferAttribute ( colors , 3 ) ) ;
352+
353+ // Standard material using vertex colors instead of gradient shader
354+ const material = new THREE . MeshBasicMaterial ( {
355+ vertexColors : true
356+ } ) ;
357+ group . add ( new THREE . Mesh ( geometry , material ) ) ;
358+ } else {
359+ // No gradient
360+ geometry = new THREE . SphereGeometry ( ) ;
361+ material = new THREE . MeshBasicMaterial ( {
362+ color : useDefaultColor ? params [ 'ndColor' ] : node . color
363+ } ) ;
364+ group . add ( new THREE . Mesh ( geometry , material ) ) ;
365+ }
371366
372367 // Show labels if needed
373368 if ( params [ "showLabels" ] ) {
@@ -377,11 +372,11 @@ define([
377372 sprite . color = tinycolor ( params [ 'bgColor' ] ) . isLight ( ) ?
378373 "rgba(0,0,0,.8)" : "rgba(255,255,255,.8)" ;
379374 sprite . textHeight = 2 ;
380- sprite . position . y = 2 * NODE_R ;
381- obj . add ( sprite ) ;
375+ sprite . offsetY = NODE_R * 1.5 ;
376+ group . add ( sprite ) ;
382377 }
383378
384- return obj ;
379+ return group ;
385380 } ) ;
386381
387382 if ( this . logging ) console . log ( "updateView() - Rendering [3D] graph" ) ;
@@ -390,7 +385,7 @@ define([
390385 if ( this . logging ) console . log ( "updateView() - Loading [2D] graph" ) ;
391386 this . _load2DGraph ( $elem . get ( 0 ) , params ) ;
392387 }
393-
388+
394389 // Add node customisations to the 2D Graph
395390 this . graph . nodeCanvasObject ( ( node , ctx , globalScale ) => {
396391 // Drawing nodes
@@ -415,24 +410,26 @@ define([
415410 // Show labels if needed
416411 if ( params [ "showLabels" ] ) {
417412 const fontSize = 12 / globalScale ;
413+ const paddingScreenPx = 5 ;
414+ const verticalOffsetScreenUnits = ( 2 * NODE_R ) + paddingScreenPx / globalScale ;
418415 ctx . font = `${ fontSize } px Sans-Serif` ;
419416 ctx . fillStyle = tinycolor ( params [ 'bgColor' ] ) . isLight ( ) ?
420417 "rgba(0,0,0,.8)" : "rgba(255,255,255,.8)" ;
421418 ctx . textAlign = 'center' ;
422419 ctx . textBaseline = 'middle' ;
423- ctx . fillText ( node . name , node . x , node . y - ( 2 * NODE_R ) ) ;
420+ ctx . fillText ( node . name , node . x , node . y - verticalOffsetScreenUnits ) ;
424421 }
425422 } ) ;
426423
427424 if ( this . logging ) console . log ( "updateView() - Rendering [2D] graph" ) ;
428425 }
429-
430- this . graph . linkColor ( link => link . color =
426+
427+ this . graph . linkColor ( link => link . color =
431428 link . has_custom_color < 1 ? params [ 'lkColor' ] : link . color )
432429 . backgroundColor ( params [ "bgColor" ] )
433430 . dagMode ( params [ "dagMode" ] )
434- . linkDirectionalArrowLength ( showLinkArrows ? 3 .5 : 0 )
435- . linkDirectionalArrowRelPos ( 1 )
431+ . linkDirectionalArrowLength ( showLinkArrows ? 4 .5 : 0 )
432+ . linkDirectionalArrowRelPos ( 0.5 )
436433 . graphData ( data . content ) ;
437434 } ,
438435
@@ -570,7 +567,7 @@ define([
570567 if ( this . logging ) console . log ( "_toggleAnimationBar() - Entered {" + value + "}" ) ;
571568
572569 var $elem = $ ( 'div.graphviz-controllers[name=cntl' + this . uuid + ']' ) ;
573-
570+
574571 if ( value && ! $elem . hasClass ( "show" ) ) {
575572 $elem . toggleClass ( "show" ) ;
576573 } else if ( ! value && $elem . hasClass ( "show" ) ) {
0 commit comments