How can i make line segments from THREE.CatmullRomCurve3 to have different colors

Hello Friends,

I have an interesting challenge that wanted to see how to solve. I have 7 vertices that define different segments of a curved line that i am connecting to different circles per screen shot below. My issue is i want each segment of this line between the two circles to have a different color. So here is the code fragment:

pointcurve = [ [114, 136, 52], [106, 136, 64], 
                      [112, 80, 64], [100, 80, 70], [154, 230, 54],
                     [176, 212, 50], [180, 232, 64] ];
 const curve = new THREE.CatmullRomCurve3(
        pointcurve.map((e)=>{
               return  new THREE.Vector3(e[0], e[1],e[2])
                   })
                   );
                   curve.closed = false;
                   curve.tension = .1;
    const vertices = [];

    curve.getPoints(800).forEach((e)=>{
        
        vertices.push(
                e.x, e.y, e.z
                    );
      });

     const colors = [];
     
      for (let x=0; x < vertices.length; x++) {

          colors.push(Math.random(), Math.random(), Math.random());
         
      }

    const geometry = new THREE.BufferGeometry();

    geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );

    geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );

When i create random colors i want each color to paint a segment of the line based on the pointcurve arrays. But when i call the following api:
let vertices = curve.getPoints(800);
The vertices now contain many many more little vertices which are neccassary to smooth each line. But if i go through the vertices array and color each element, then i end up with a single line between the two circles with multiple colors, but in reality i want that segment of the line to have the same color. And the next segment between the other circles to have a different color.
So how do i know how many of these little vertices beling to the same line so i can paint them the same color?

Here is a screen shot of the actual lines drawn in 3d:

I want each line between the circles to have a different color. But i dont want the same line between the two circles to have multiple colors. So, I need to know how to calculate the boundary of vertices for each line segment so i can pain them the same color.

Thanks

Iā€™d try with 133 segments per curve fragment, because 800/(7-1) ā‰ˆ 133.

Thanks @PavelBoytchev for the suggestion. I did add the above calculation and while it does paint the lines with a color, but it is not exact. As you can see one line is green, and then the second line is half green and half yellow. And then two other line are again the same orange color.
So, I am wondering if there i s a sure bet way to do this. As I said I am deviding into equal segments and count those but it is not exact at all.

Here is updated code:

let colorArray = [];
colorArray.push(new THREE.Color('rgb(62, 193, 35)'));
    colorArray.push(new THREE.Color('rgb(248, 255, 14)'));
    colorArray.push(new THREE.Color('rgb(255, 0, 0)'));
    colorArray.push(new THREE.Color('rgb(34, 0, 255)'));
    colorArray.push(new THREE.Color('rgb(171, 0, 255)'));
     colorArray.push(new THREE.Color('rgb(255, 171, 0)'));
     colorArray.push(new THREE.Color('rgb(255, 0, 230)'));
     colorArray.push(new THREE.Color('rgb(161, 37, 37)'));
     colorArray.push(new THREE.Color('rgb(164, 182, 153)'));
     colorArray.push(new THREE.Color('rgb(164, 182, 153)'));
     colorArray.push(new THREE.Color('rgb(255, 255, 255)'));
           
               pointcurve = [ [114, 136, 52], [106, 136, 64], 
                      [112, 80, 64], [100, 80, 70], [154, 230, 54],
                     [176, 212, 50], [180, 232, 64] ];

               const SPLINE_SIZE_PER_SEGMENT = 133;
                    
                           
              const curve = new THREE.CatmullRomCurve3(
                        pointcurve.map((e)=>{
                               return  new THREE.Vector3(e[0], e[1],e[2])
                                   })
                                   );
                                   curve.closed = false;
                                   curve.tension = .1;
                    const vertices = [];

                    let count = (pointcurve.length) * SPLINE_SIZE_PER_SEGMENT;
                    // multiply by 3 since each vertice has three coordinates
                    let segmentSize = SPLINE_SIZE_PER_SEGMENT * 3; 
                    
                    curve.getPoints(count).forEach((e)=>{
                        
                        vertices.push(
                                e.x, e.y, e.z
                                    );
                      });

                   

                      const colors = [];
                      for (let x=0; x < vertices.length; x++) {

                          /***********
                             IMPORTANT PART:
                             This colorArrayIndex will bump by one every 399 times (133 * 3). 
                              number 3 accounts for x,y,z in the vertices
                              which has a length of 2796 for this set of points. This change will get a new color from the array
                           ******************/
                          colorArrayIndex = Math.trunc(x/segmentSize); 
                         
                          colors.push(colorArray[colorArrayIndex].r, colorArray[colorArrayIndex].g, colorArray[colorArrayIndex].b)

                          
                    
                      }


                    const geometry = new THREE.BufferGeometry();

                    geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );

                    geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );

Thanks again for your good input so far

Where is this ā€œ-1ā€ in your code? pointcurve.length is the number of control points, not the number of fragments.

If you have an online debuggable example (e.g. in CodePen), it would be better.

When I try it, it works fine:

const CURVE_FRAGMENTS = pointCurve.length-1; // Note: it is length-1
const SEGMENTS_PER_FRAGMENT = 40;
const SEGMENTS = CURVE_FRAGMENTS * SEGMENTS_PER_FRAGMENT;

var points = curve.getPoints( SEGMENTS ),
	geometry = new THREE.BufferGeometry().setFromPoints( points );

1 Like

Thanks @PavelBoytchev. Sorry for the confusion. I forgot to add the -1 in the code above. But even with that my lines where not colored at the right boundaries. I cant post the code in jsfiddle because it is part of a big application and hard to isolate for debugging environments. That is why I just pasted the portion that was pertinent. Would you be kind enough to post the code that created the above image so i can take a look. Specially at the logic for coloring each line segment.
Thanks again for all your help

No need to share the whole big application. It is just a few coordinates and a curve:

https://codepen.io/boytchev/full/BaerEGq

I hope this would be enough for you to fix the issue. Iā€™d not have spare time to provide additional examples or assistance.

Good luck with your project.

4 Likes

Thanks a lot @PavelBoytchev. That code fragment you provided will be a great help here. Much appreciate all your help.

Using your code fragment helped me solve the problem. Thanks again @PavelBoytchev :pray: