why are these rotations so glitchy?

edited January 2015 in Questions about Code

Im going to post some code that I have posted in about 3 or 4 different questions. and now, its time for a new one!! yay!!

lol, sorry for asking so many noob questions, but something really has me confused here.

I have this code to make a box fly around the screen and rotate as it does it. It is coming along nicely, but for the rotations, some non-desirable stuff starts happening when the rotation parameters get above 90 (particularly rotateX).

You can comment out line 73 to see what it looks like normally. You can also turn on axes by un-commenting 36

Its not BAD but I wanted to see if i could get it to rotate in a more consistent manner, so, because I know what the rotations look like when both rotateX and rotateY are below 90, I thought I would write a conditional to check if the value is above 90 and then map it down to its <90 equivalent. (working under the premise that from the user's perspective -94 degrees looks the same as -4 degrees.) I thought it would be seamless, but for some reason It's not and you can easily tell when the switch is happening.

can someone explain why this is? all of my tests indicate that the two should look the same.

Here is the code, ignore the dance_queue stuff. The relevant code is ~60-82 and the regulate_rotation_parameters() function

int w = 1500;
int h = 800;

PVector location = new PVector(w/2,h/2,0);
PVector last_location=location.get();
float move_scale=50;


PVector noises = new PVector(0,0,0);



int count=0;
int dance_queue = 0;
color box_color = color(40,40,40);
float box_size = ((w+h)/2)/5;
boolean axes=false;


PVector rotation = new PVector(0,0,0);
float rotation_scale=(90/box_size);


float off=box_size;
PVector final_min = new PVector(-off,-off,-h);
PVector final_max = new PVector(w+off,h+off,h/2);

boolean paused=false;
void setup()
{
  size(1500,800,P3D);
  background(255,255,255);
  fill(box_color);
  noStroke();
  seed_noises();
  //axes=true;
}

void draw()
{
  if(keyPressed) paused=!paused;
  if(!paused)
  {
    background(255);
    directionalLight(100, 100, 100, 0.5, 0.65, -0.5);
    directionalLight(100, 100, 100, 0.5, 0, -1);

    float a = 0.01;
    noises.add(a,a,a);
    if(count<dance_queue)
    {  
      float s = count * rotation_scale*2;
      float scale = radians(s);
      rotation.x=map(newNoise(noises.x,0,0),-1,1,-scale, scale);
      rotation.y=map(newNoise(noises.y,0,0),-1,1,-scale, scale);
      count++;       
    }
    else
    {
      last_location=location.get();
      float[] l = location.array();
      float[] n = noises.array();

      for(int i=0;i<2;i++)
      {
        float natural_movement = map(newNoise(n[i], 0, 0),-1,1,-move_scale,move_scale);
        l[i] = regulate_boundary_intervention(natural_movement,i,a); //point the cube back in the right direction if necessary.
      }
      location=new PVector(l[0],l[1],l[2]); 
      float r=rotation_scale;
      rotation.x+=radians((location.x-last_location.x)*rotation_scale);
      rotation.y+=-radians(((location.y-last_location.y)*rotation_scale)+((location.z-last_location.z)*rotation_scale));  
      regulate_rotation_parameters();      
    }    
    translate(location.x,location.y,location.z); 
    rotateX(rotation.y);
    rotateY(rotation.x);
    //rotateZ(adjusted_rotation.z);
    noStroke();
    box(box_size);
    if(axes) draw_axes(); 
  }
}

void seed_noises()
{
  int seed=(int) random(6,30);
  noises.x=random(1000)*seed-4;
  noises.y=random(1000)*seed-2;
  noises.z=random(1000)*seed;  
}

float regulate_boundary_intervention(float desired_movement, int i, float noise_incr)
{ 
  float off=-(location.z/1.5);
  if(i==2) off=0;
  float[] loc = location.get().array();
  float[] fMin = final_min.array();
  float[] fMax = final_max.array();
  float new_location = loc[i]+desired_movement;
  boolean location_approved = ((new_location>(fMin[i]-off)) && (new_location<(fMax[i]+off)));
  if (location_approved)
  {
    return new_location;
  }

  float[] ns = noises.get().array();
  while(!location_approved)
  {
    ns[i]+=noise_incr;
    desired_movement = map(newNoise(ns[i], 0, 0),-1,1,-move_scale,move_scale);
    new_location=loc[i]+desired_movement;
    location_approved = ((new_location>(fMin[i]-off)) && (new_location<(fMax[i]+off)));
  }  
  noises=new PVector(ns[0],ns[1],ns[2]);
  return new_location;
}


void regulate_rotation_parameters()
{
  float yRot = degrees(rotation.y);
  float xRot = degrees(rotation.x);


  if(abs(yRot)>90) 
  {
    if (yRot<0)
    {

      println(yRot);
      yRot = map(yRot,-180,-90,-90,0);
      println(yRot);
      println("\n");

    }
    else
    {
      println(yRot);
      yRot = map(yRot,90,180,0,90);
      println(yRot);
      println("\n");
    }
    rotation.y=radians(yRot);
  }

  if(abs(xRot)>90) 
  {
    if (xRot<0)
    {
      println(xRot);
      xRot = map(xRot,-180,-90,-90,0);
      println(xRot);
      println("\n");
    }
    else
    {
      println(xRot);
      xRot = map(xRot,90,180,0,90);  
      println(xRot); 
      println("\n");
    }
    rotation.x=radians(xRot);
  } 

}

void draw_axes()
{
  stroke(0,255,0);
  line(-w/2,0,0,0);
  stroke(255,0,0);
  line(0,0,w/2,0);
  stroke(0,0,255);
  line(0,0,0,-h/2);
  stroke(255,0,255);
  line(0,0,0,h/2);
}



//================================================================
//Chinchbug's Implementation of Ken Perlin's Improved Noise Algorithm
//See <a href="http://mrl.nyu.edu/~perlin/paper445.pdf" target="_blank" rel="nofollow">http://mrl.nyu.edu/~perlin/paper445.pdf</a>;
//================================================================

int p[];

//================================================================

float newNoise(float x, float y, float z) {
  //returns value between -1 and +1
  if (p == null) setupPermutationTable();
  int X = floor(x) & 255;
  int Y = floor(y) & 255;
  int Z = floor(z) & 255;
  x -= floor(x);
  y -= floor(y);
  z -= floor(z);
  float u = fade(x);
  float v = fade(y);
  float w = fade(z);    
  int A = p[X]+Y;
  int AA = p[A]+Z;
  int AB = p[A+1]+Z;
  int B = p[X+1]+Y;
  int BA = p[B]+Z;
  int BB = p[B+1]+Z;

  return lerp2(w, lerp2(v, lerp2(u, grad(p[AA], x, y, z), grad(p[BA], x-1, y, z)),
       lerp2(u, grad(p[AB], x, y-1, z), grad(p[BB], x-1, y-1, z))),
       lerp2(v, lerp2(u, grad(p[AA+1], x, y, z-1), grad(p[BA+1], x-1, y, z-1)),
       lerp2(u, grad(p[AB+1], x, y-1, z-1), grad(p[BB+1], x-1, y-1, z-1))));
 }

//================================================================

 float fade(float t) { 
   return ((t*6 - 15)*t + 10)*t*t*t; 
 }

//================================================================

 float lerp2(float t, float a, float b) { 
   return (b - a)*t + a;
 }

//================================================================

 float grad(int hash, float x, float y, float z) {
   int h = hash & 15;
   float u = h<8 ? x : y;
   float v = h<4 ? y : h==12||h==14 ? x : z;
   return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
 }

//================================================================

void setupPermutationTable() {
  int permutation[] = { 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 
      233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 
      6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 
      11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 
      68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 
      229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 
      143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 
      169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 
      3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 
      85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 
      170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 
      43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 
      185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 
      191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 
      31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 
      254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 
      66, 215, 61, 156, 180 };

  p = new int[512];
  for (int i=0; i < 256 ; i++)
    p[i] = p[i+256] = permutation[i];
}
Tagged:

Answers

  • Answer ✓

    i like that.

    (working under the premise that from the user's perspective -94 degrees looks the same as -4 degrees.)

    that would be true with one rotation, but you have two. rotating by x degrees in the x axis changes the axis of revolution for the y rotation. you can see this with the axes on - they suddenly flip (when you change from -94 to -4).

    i'd just delete the regulate_rotation_parameters() thing, that's the cause of the glitch. unless you can explain better what you mean by "rotate in a more consistent manner"

  • edited January 2015

    what I mean can best be demonstrated if you play with the for loop parameters on line 64.

    first make it only move in the x direction.

    then make it only move in the y direction.

    this is what I want the rotations to look like in general. However, when, for example, the rotateX=90 when the cube moves in the x direction the cube does not rotate in the same way (it makes it look like its doing a rotateZ)

  • ah, ok, so it doesn't look as though it's rolling.

    again, i think that's because your second rotation is around an axis that's been rotated by the first rotation - if you rotate 90 degrees around x then your y is now pointing along z, like you describe.

    using quaternions is, i believe, the way around this. but then i've been trying to get my head around them for years and haven't managed it yet. (translate to 4 dimensions, rotate there, translate back into 3 dimension iirc)

  • edited January 2015

    looking at: http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation

    the core idea here seems to be about getting the new vector given theta and the original vector (rotation vector) but how do i get theta in the first place

Sign In or Register to comment.