# 3D shape with a bad seam

**URL:** https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218
**Category:** Coding Questions
**Created:** [August 6, 2019, 9:23pm UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218 "2019-08-06T21:23:35Z")
**Posts on this page:** 19
**Page:** 1

<div class="post-metadata">

### Author: ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)
#### Post date: [August 6, 2019, 9:23pm UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/1 "2019-08-06T21:23:35Z")

</div>

Hello all,

I produced a 3D quadt\_strip shape, but not only one row but multiple.

It’s kind of a circle (Moebius strip).

Unfortunately I have a big seam (horizontal right side) I cannot get rid of.

Can someone check my logic please? This gets called from setup() and is shown later.

Chrisir

 ![Unbenannt](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/6/65fd239400b4e7d75ddabc7016f4407a98111910.jpeg)

```auto

// defining a QUAD_STRIP shape 

int i2_span=100; 

void initMainItem() {

  // https://de.wikipedia.org/wiki/M%C3%B6biusband

  boolean grid=false; 

  moebius1=createShape(); 
  moebius1.beginShape(QUAD_STRIP);

  if (grid) {
    // only grid 
    moebius1.noFill();
    moebius1.stroke(0);
  } else {
    // full fill
    moebius1.fill(255, 0, 0);
    moebius1.noStroke();
  }

  // i2 -> radius (how wide the red strip is) 
  // i3 / i -> alpha (angle) 

  for (int i2=-i2_span; i2<i2_span; i2++) {
    for (int i3=0; i3<360+1; i3++) {

      int i=i3; 
      if (i>360) 
        i=i-360; 

      makeVertex3D(i2, i); 

      makeVertex3D(i2+1, i); 

      //
    }//for
    //
  }//for 

  // ---------------------------------

  /*
   for (int i2=-i2_span; i2<i2_span-1; i2+=1) {
   
   float r = i2/i2_span; 
   float alpha=radians(359); 
   PVector v = new PVector(
   cos(alpha) * ( 1+ ((r/2) * cos ( alpha / 2 ) ) ), 
   sin(alpha) * ( 1+ ((r/2) * cos ( alpha / 2 ) ) ), 
   (r/2) * sin(alpha/2));
   v.mult(factor1);
   v.y+=yadd1;
   // moebius1.vertex(v.x, v.y, v.z);
   
   r = (i2+1)/i2_span;  
   alpha=radians(0);
   v = new PVector(
   cos(alpha) * ( 1+ ((r/2) * cos ( alpha / 2 ) ) ), 
   sin(alpha) * ( 1+ ((r/2) * cos ( alpha / 2 ) ) ), 
   (r/2) * sin(alpha/2));
   v.mult(factor1);
   v.y+=yadd1;
   // moebius1.vertex(v.x, v.y, v.z);
   //
   }//for
   
   */

  moebius1.endShape();

  println("");
  println (">>>>"
    +leaves.size());
}//func

void makeVertex3D( int i2, int i) {

  float factor1=220; 
  float yadd1= 200; 

  float r = i2/i2_span; 
  float alpha=radians(i); 
  PVector v = new PVector(
    cos(alpha) * ( 1+ ((r/2) * cos ( alpha / 2 ) ) ), 
    sin(alpha) * ( 1+ ((r/2) * cos ( alpha / 2 ) ) ), 
    (r/2) * sin(alpha/2));
  v.mult(factor1);
  v.y+=yadd1;
  moebius1.vertex(v.x, v.y, v.z);
}
//

```

---

<div class="post-metadata">

### Author: ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)
#### Post date: [August 6, 2019, 11:00pm UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/2 "2019-08-06T23:00:25Z")

</div>

I was tinkering with this and added a vertex after for loops.

This cleaned it up but may not be the best solution:

```auto
      makeVertex3D(i2, i); 
      makeVertex3D(i2+1, i);
      }
    //moebius1.stroke(0);
    makeVertex3D(-50, 1); //Added
    } 
  moebius1.endShape(); 
  }

```

I did something similar in past and recall issues with closing my Moebius strip:

[![](https://img.youtube.com/vi/IoYBfe5UGEI/maxresdefault.jpg "Mobius Strip") ](https://www.youtube.com/watch?v=IoYBfe5UGEI)

🙂

Update:

I revisited my code from a year ago and updated it based on my suggestion to you!  
I was overlapping to close shape but replaced it with a clean “close” of the shape:

```auto
  beginShape(QUAD_STRIP);
  for (float th1 = th_ini; th1<th_fin + 0; th1+=TAU/100) // was th_fin + TAU/100 to overlap
    {
    R = 350;
    float v = 60;
    float u = th1;
    mobPlot = mobius2(R, v, u); 
    vertex(mobPlot[0], mobPlot[1], mobPlot[2]);   
    mobPlot = mobius2(R, -v, u);
    vertex(mobPlot[0], mobPlot[1], mobPlot[2]);  
    }
    
  if (close)
    {
    mobPlot = mobius2(R, -60, 0); 
    vertex(mobPlot[0], mobPlot[1], mobPlot[2]);   
    mobPlot = mobius2(R, 60, 0);
    vertex(mobPlot[0], mobPlot[1], mobPlot[2]);  
    }
  endShape(); 
  }

```

Mobius2() based on formulas from:

> **[Möbius strip](https://en.wikipedia.org/wiki/M%C3%B6bius_strip)**
>
> In mathematics, a Möbius strip, Möbius band, or Möbius loop\[a\] is a surface that can be formed by attaching the ends of a strip of paper together with a half-twist. As a mathematical object, it was discovered by Johann Benedict Listing and August Ferdinand Möbius in 1858, but it had already appeared in Roman mosaics from the third century CE. The Möbius strip is a non-orientable surface, meaning that within it one cannot consistently distinguish clockwise from counterclockwise turns. Every n...

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/0/014e5763a6d9050320f2af8fc67d0b938d6bea60.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/4/43f754490d9d56ab60ee4fba223fd35d65aed318.png)

---

<div class="post-metadata">

### Author: ![kll](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kll/32/964_2.png) [@kll](https://discourse.processing.org/u/kll)
#### Post date: [August 7, 2019, 1:40am UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/3 "2019-08-07T01:40:55Z")

</div>

very good, i had the same problem at first when i play with the

> klein bottle

see [here](http://kll.engineering-news.org/kllfusion01/articles.php?article_id=154#here6)

---

<div class="post-metadata">

### Author: ![quark](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/quark/32/26_2.png) [@quark](https://discourse.processing.org/u/quark)
#### Post date: [August 7, 2019, 7:54am UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/4 "2019-08-07T07:54:50Z")

</div>

> [@glv](#):
>
> for (float th1 = th\_ini; th1\<th\_fin + 0; th1+=TAU/100)

It is almost certain that it is due to rounding errors on the floating point numbers I would change the loop to something like this

```auto
float nbrSlicess;
float delta = TAU / (nbrSteps +1); 
for(int s = 0; s < nbrSteps; s++){
  th1 = s * delta + th_ini
  ...

```

You would have to sort out how this fits your program but `th1+=TAU/100` will generate rounding errors every time it is executed.

---

<div class="post-metadata">

### Author: ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)
#### Post date: [August 7, 2019, 11:11am UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/5 "2019-08-07T11:11:33Z")

</div>

Bringing back focus to original post:

> [@3D shape with a bad seam](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/1):
>
> Hello all, I produced a 3D quadt\_strip shape, but not only one row but multiple. It’s kind of a circle (Moebius strip). Unfortunately I have a big seam (horizontal right side) I cannot get rid of. Can someone check my logic please? This gets called from setup() and is shown later. Chrisir // defining a QUAD\_STRIP shape int i2\_span=100; void initMainItem() { // https://de.wikipedia.org/wiki/M%C3%B6biusband boolean grid=false; moebius1=createShape(); moebius1.…

@Chrisir Thanks for inspiring me to visit this topic again! I spent a few hours on my original versions last night and they are in a much better state.

🙂

---

<div class="post-metadata">

### Author: ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)
#### Post date: [August 7, 2019, 12:31pm UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/6 "2019-08-07T12:31:39Z")

</div>

Thank you all for the inspiring discussion!

I have to look into it later.

---

<div class="post-metadata">

### Author: ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)
#### Post date: [August 7, 2019, 8:56pm UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/7 "2019-08-07T20:56:03Z")

</div>

> [@glv](#):
>
> this

@glv  
so your new line is between the two brackets of the for-loops?

It’s much better but I still have a weak seam.

Is this correct?

```auto

// defining a QUAD_STRIP shape 

int i2_span=100; 

void initMainItem() {

  // https://de.wikipedia.org/wiki/M%C3%B6biusband

  boolean grid=false; 

  moebius1=createShape(); 
  moebius1.beginShape(QUAD_STRIP);

  if (grid) {
    // only grid 
    moebius1.noFill();
    moebius1.stroke(0);
  } else {
    // full fill
    moebius1.fill(255, 0, 0);
    moebius1.noStroke();
  }

  // i2 -> radius (how wide the red strip is) 
  // i3 / i -> alpha (angle) 

  for (int i2=-i2_span; i2<i2_span; i2++) {
    for (int i3=0; i3<361; i3++) {

      int i=i3; 
      if (i>360) 
        i=i-360; 

      makeVertex3D(i2, i); 
      makeVertex3D(i2+1, i); 
      //
    }//for
    //
    makeVertex3D(-50, 1); //Added !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    //
  }//for

  // ---------------------------------
  
  moebius1.endShape();

  println("");
  println (">>>>"
    +leaves.size());
}//func

void makeVertex3D( int i2, int i) {

  float factor1 = 220; 
  float yadd1 = 200; 

  float r = i2/i2_span; 
  float alpha=radians(i); 
  PVector v = new PVector(
    cos(alpha) * ( 1+ ((r/2) * cos ( alpha / 2 ) ) ), 
    sin(alpha) * ( 1+ ((r/2) * cos ( alpha / 2 ) ) ), 
    (r/2) * sin(alpha/2));
  v.mult(factor1);
  v.y+=yadd1;
  moebius1.vertex(v.x, v.y, v.z);
}
//

```

---

<div class="post-metadata">

### Author: ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)
#### Post date: [August 9, 2019, 12:32pm UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/8 "2019-08-09T12:32:12Z")

</div>

I just tinkered with your code and did not present a solution.

I posted my Mobius strip work in the Gallery for the masses to enjoy viewing.

🙂

---

<div class="post-metadata">

### Author: ![quark](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/quark/32/26_2.png) [@quark](https://discourse.processing.org/u/quark)
#### Post date: [August 9, 2019, 2:59pm UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/9 "2019-08-09T14:59:21Z")

</div>

I suggested the gap was caused by rounding errors due to repeated addition of irrational numbers. I did provide some starting code but have decided to provide a full solution showing how to avoid the gap. The code below produced this Mobius Strip.  
 ![18](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/c/c601ba9fe392acd364fcbc43fdc76dc957ebb814.png)

```auto
import peasy.*;

PeasyCam pcam;

PVector[] s;
// Radius of Mobius strip
float r = 100;
// Width of mobius strip
float w = 40;
// Number of slices round the strip
int nbrSlices = 20;

void setup() {
  size(400, 400, P3D);
  pcam = new PeasyCam(this, 300);
  // Calculate strip
  s = new PVector[nbrSlices * 2];
  float deltaT = TWO_PI / (nbrSlices - 1);
  // Calculate strip vertices
  for (int i = 0; i < nbrSlices; i++) {
    float t = i * deltaT;
    float t2 = t / 2;
    float cos_t2 = cos(t2);
    float sin_t2 = sin(t2);
    float cos_t = cos(t);
    float sin_t = sin(t);
    s[i] = new PVector( (r + w*cos_t2)*cos_t, (r + w*cos_t2)*sin_t, w * sin_t2 );
    s[nbrSlices + i] = new PVector( (r - w*cos_t2)*cos_t, (r - w*cos_t2)*sin_t, -w * sin_t2 );
  }
  // Draw mobius
}

void draw() {
  background(0);
  lights();
  stroke(255);
  strokeWeight(2);
  fill(200, 30, 30);
  beginShape(QUAD_STRIP);
  for (int i = 0; i < nbrSlices; i++) {
    vertex(s[i].x, s[i].y, s[i].z);
    vertex(s[i+nbrSlices].x, s[i+nbrSlices].y, s[i+nbrSlices].z);
  }
  endShape();
}

```

---

<div class="post-metadata">

### Author: ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)
#### Post date: [August 9, 2019, 4:06pm UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/10 "2019-08-09T16:06:00Z")

</div>

suggested the gap was caused by rounding errors due to repeated addition of irrational numbers

Thanks a ton.

I didn’t think this was referring to my code since I don’t add up things.

---

<div class="post-metadata">

### Author: ![quark](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/quark/32/26_2.png) [@quark](https://discourse.processing.org/u/quark)
#### Post date: [August 9, 2019, 5:23pm UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/11 "2019-08-09T17:23:52Z")

</div>

No, I was referring to glv’s code.

Even so it highlights a problem many beginners don’t know about i.e. limited accuracy of floating point numbers in computing

---

<div class="post-metadata">

### Author: ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)
#### Post date: [August 11, 2019, 2:12pm UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/12 "2019-08-11T14:12:19Z")

</div>

@Chrisir

Some nice work in the Gallery! Pleased to see you closed the gap.

I explored this further with **my code** (updated since last posts) so just adding to topic:

1. There is no gap at the seam (first and last QUAD\_STRIP joining).
2. There is a “lighting issue” at the last “QUAD\_STRIP” at the seam.
3. I suspect the “lighting” of the “QUAD\_STRIP” is related to this topic:  
[https://processing.org/reference/normal\_.html](https://processing.org/reference/normal_.html)
4. I used some normal() methods in code and it displays a smooth transition but the lighting was not correct (see link above). I will explore this further.
5. I extended my Möbius strip shape by adding additional QUAD\_STRIPS that were **transparent** and this provided a clean transition at the seam.
6. I coloured the Möbius strip with a gradient (color wheel) and used the “extra transparent QUAD\_STRIPS” for a smooth transition for this effect.
7. I have **fixed location** lights() (start of loop) and rotate my Möbius shape after and this is when I see the “lighting issues” at the seam. If the light is rotated along with Möbius shape the lighting issues do not present themselves (expected since this view appeared seamless).

Your post helped me with my SPHEREs:

> **[Processing 2.x and 3.x Forum](https://forum.processing.org/two/discussion/8504/group-pshape-with-sphere-solved)**
>
> Processing is an electronic sketchbook, a language and a worldwide community. This is its forum.

🙂

---

<div class="post-metadata">

### Author: ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)
#### Post date: [August 11, 2019, 2:27pm UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/13 "2019-08-11T14:27:14Z")

</div>

Integers in loops are indeed preferred practice:  
[https://help.semmle.com/wiki/display/CCPPOBJ/Avoid+floats+in+for+loops](https://help.semmle.com/wiki/display/CCPPOBJ/Avoid+floats+in+for+loops)  
[https://chortle.ccsu.edu/Java5/Notes/chap42/ch42\_6.html](https://chortle.ccsu.edu/Java5/Notes/chap42/ch42_6.html)  
[https://www.quora.com/Can-we-use-floating-point-control-variables-in-the-case-of-iteration-in-C++-Is-it-always-wise-to-use-them](https://www.quora.com/Can-we-use-floating-point-control-variables-in-the-case-of-iteration-in-C++-Is-it-always-wise-to-use-them)

This did not affect my code (I did not have a gap) but I will be transitioning to this preferred practice.

🙂

---

<div class="post-metadata">

### Author: ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)
#### Post date: [August 11, 2019, 2:34pm UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/14 "2019-08-11T14:34:37Z")

</div>

> [@glv](#):
>
> If the light is rotated along with Möbius shape the lighting issues do not present themselves

Could you show me how this is achieved? How do you rotate the lights() (and what kind?) ?

Thanks for the great Input!

---

<div class="post-metadata">

### Author: ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)
#### Post date: [August 11, 2019, 2:52pm UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/15 "2019-08-11T14:52:04Z")

</div>

Using quark’s example:

> [@quark](#):
>
> The code below produced this Mobius Strip.

1. PeasyCam is rotating everything including the lights(); try the example with noStrokes() and nbrSlices = 50. There is a noticeable issue at seam ((QUAD\_STRIP) but not so apparent as next step 2.

2. Remove all the references to PeasyCam and add this and increase nbrSlices = 50:

> float theta;  
> void draw() {  
> background(0);  
> lights();  
> translate(width/2, height/2);  
> rotateX(theta);  
> theta += TAU/1000;  
> noStroke();
> 
> // stroke(255);  
> // strokeWeight(2);

And I see the same “lighting issues” that I discussed:  
 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/6/6c09a52cb4038cbc5d68790ad103d20c269e7749.png)

I wanted to see if the “lighting issues” were present in this example and they are for my use of lights().

The description here discusses this issue:

> **[normal() / Reference](https://processing.org/reference/normal_.html)**
>
> Sets the current normal vector. Used for drawing three-dimensional shapes and surfaces, normal() specifies a vector perpendicular to a shape's surface which, in turn, determines how lighting af…

> Sets the current normal vector. Used for drawing three dimensional shapes and surfaces, **normal()** specifies **a vector perpendicular to a shape’s surface which, in turn, determines how lighting affects it. Processing attempts to automatically assign normals to shapes, but since that’s imperfect,** this is a better option when you want more control.

🙂

---

<div class="post-metadata">

### Author: ![quark](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/quark/32/26_2.png) [@quark](https://discourse.processing.org/u/quark)
#### Post date: [August 11, 2019, 4:07pm UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/16 "2019-08-11T16:07:58Z")

</div>

If you only use ambient light you don’t have the problem because the surface normals are ignored. If you un-comment the directional light line the problem appears because of the way Processing estimates the normal vector.

````auto
float theta;

PVector[] s;
// Radius of Mobius strip
float r = 100;
// Width of mobius strip
float w = 40;
// Number of slices round the strip
int nbrSlices = 50;

void setup() {
  size(400, 400, P3D);
  // Calculate strip
  s = new PVector[nbrSlices * 2];
  float deltaT = TWO_PI / (nbrSlices - 1);
  // Calculate strip vertices
  for (int i = 0; i < nbrSlices; i++) {
    float t = i * deltaT;
    float t2 = t / 2;
    float cos_t2 = cos(t2);
    float sin_t2 = sin(t2);
    float cos_t = cos(t);
    float sin_t = sin(t);
    s[i] = new PVector( (r + w*cos_t2)*cos_t, (r + w*cos_t2)*sin_t, w * sin_t2 );
    s[nbrSlices + i] = new PVector( (r - w*cos_t2)*cos_t, (r - w*cos_t2)*sin_t, -w * sin_t2 );
  }
}

void draw() {
  translate(width/2, height/2);
  background(0);
  ambientLight(200,200,200);
  // directionalLight(100,100,100, 0,1,1);
  noStroke();
  fill(200, 15, 15);
  rotateX(theta);
  theta += TAU / 200;
  beginShape(QUAD_STRIP);
  for (int i = 0; i < nbrSlices; i++) {
    vertex(s[i].x, s[i].y, s[i].z);
    vertex(s[i+nbrSlices].x, s[i+nbrSlices].y, s[i+nbrSlices].z);
  }
  endShape();
}```
````

---

<div class="post-metadata">

### Author: ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)
#### Post date: [August 11, 2019, 5:47pm UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/17 "2019-08-11T17:47:49Z")

</div>

> [@glv](#):
>
> I extended my Möbius strip shape by adding additional QUAD\_STRIPS that were **transparent** and this provided a clean transition at the seam.

Elaborating on what I did to work around using lights() which includes ambient() and directionall():

```auto
public void mobius2(int steps, float r, float v, float u)
  { 
  m2 = createShape();
  m2.beginShape(QUAD_STRIP);
    
  for (int step = 0; step < (steps+1)+2; step++)
    {
    u = step*(TAU/steps);  
           
   if (step > steps) 
     m2.fill(255, 255, 0, 0);
   else 
     m2.fill(255, 255, 0, 255);  
 
    mobEq(r, -v, u);
    m2.vertex(x, y, z);
    mobEq(r, v, u);
    m2.vertex(x, y, z);
    }
  m2.endShape();
  }

```

I will post my example code later; time to go for a hike in the woods for some fresh air!

🙂

---

<div class="post-metadata">

### Author: ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)
#### Post date: [August 11, 2019, 5:54pm UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/18 "2019-08-11T17:54:48Z")

</div>

Thanks for the insight.

That narrows it down to directionalLight(100,100,100, 0,1,1);  
and normals (see description for anyone visiting topic):  
[https://processing.org/reference/normal\_.html](https://processing.org/reference/normal_.html)

I much prefer lights() and have my workaround working.

No one viewing sketch will ever know what I did. 🤐

🙂

---

<div class="post-metadata">

### Author: ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)
#### Post date: [August 13, 2019, 2:42am UTC](https://discourse.processing.org/t/3d-shape-with-a-bad-seam/13218/19 "2019-08-13T02:42:03Z")

</div>

> [@glv](#):
>
> I will post my example code later

The example is posted in the gallery:

> [@Möbius Strip Animation](https://discourse.processing.org/t/mobius-strip-animation/13273/6):
>
> Seamless **Möbius** strip
