Rotate Vertex

Pages: 12
Hi,

How exactly does one rotate a traingle by one of its vertices? I think, that I need a combo matrix because not only will the vertex be rotating, but the position of the traingle will be changing as well.

What we can do is start by declaring Matrix4 type varaible. How about 'c' for combo? Then a loop that iterates through each vertex and multiplies the data in 'c' by the old points..

What I am confused with is the combo matrix. I used yaw. Do I need to use all three? Pitch and roll as well? The below is a snippet from my windows application. It sets 1 vertex of a triangle to the origin, and almost rotates the triangle 360 degrees with respect to that vertex, but not quite...I think that the issue may be in the 3D rotation formula that I used. Like I mentioned above, I used Yaw. I don't think that is correct and I was hoping to seek guidence for that here tonight.

What I am trying to get happen is for when the user specifies an angle, I want my traingle to transform and rotate by one of its vertices.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
void DrawStuffs()
{    
    Vector3 pts[3]; // array to hold our vertices for the poly
    Vector3 newPts[3];  // new vertices for poly
    
    
    Matrix4 rz; // rotation matrix
    static Matrix4 c;  // composition matrix
    
     // make the current rotation matrix
    rz.makeRotationMatrixZ(angle);
    

    c = Multiply(rz, c);
	
    // set up the original points for the triangle
    pts[0].set(	50,  50, 0); // A
    pts[1].set(100, 100, 0);     // B
    pts[2].set(100,   0, 0);     // C

         // Translate the chosen vertex, Ax, Ay, Az to the origin
	pts[0].x = 0;
	pts[0].y = 0;
	pts[0].z = 1;
	
    // transform the original triangle points 
    for (int i=0; i < 3; i++) 
    {
        newPts[i] = Multiply(c, pts[i]); // multiplying rows and columns, where do I add?		
                    // Seems to be the first column for Yaw (rotating y-axis)
		c.m[0][0] = cos(angle);
		c.m[0][1] = 0;
		c.m[0][2] = -sin(angle);
		c.m[0][3] = 0;
                    
                   // second column for yaw.
		c.m[1][0] = 0;
		c.m[1][1] = 1;
		c.m[1][2] = 0;
		c.m[1][3] = 0;

                    // Third column for  yaw.
		c.m[2][0] = sin(angle);
		c.m[2][1] = 0;
		c.m[2][2] = cos(angle);
		c.m[2][3] = 1;
// fourth
                                c.m[3][0] = 0;
 		c.m[3][1] = 0;
		c.m[3][2] = 0;
		c.m[3][3] = 1;
		
	
}

	newPts[0].x = 50; // translate to back where we started
	newPts[0].y = 50;
	newPts[0].z = 0;
	

	// draw the triangle lines..
    DrawLine(newPts[0].x, newPts[0].y, newPts[1].x, newPts[1].y, green);
    DrawLine(newPts[1].x, newPts[1].y, newPts[2].x, newPts[2].y, green);
    DrawLine(newPts[2].x, newPts[2].y, newPts[0].x, newPts[0].y, green);

	
    // draw the points
    PGraphics->Draw();
}


The above code places the triangle away from the origin. But am not able to move it about the vertex I chose even with specifing an angle of rotation. If I comment out an entire column from the yaw rotation matrix, it will rotate, but it deforms and appears to scale, rather than just rotate.

Since I am rotating the traingle with respect to one of its vertices, I should not be using that in the rotating matrix?

As always, any help is very much appreciated.
Last edited on
Hmmm, there are a number of things which seem fishy here.

line 14 - You are multiplying by a matrix which has not been initialized. I hope the default constructor is good to you.

line 29 - You are doing the multiplication before the body of the loop -- Your last iteration through the loop will essentially be thrown away.

Fix those, and things may make more sense.
The steps you need to take are these:
1. translate the whole mesh, so that a chosen vertex is at the origin
2. rotate the mesh as much as you want
3. translate the mesh back to it's previous position

It may seem more clear to do it step by step:
for each vertex, multiply it by MatrixTranslation(-pt[0].x, -pt[0].y, -pt[0].z)
for each vertex, multiply it by MatrixRotationZ(my_angle)
for each vertex, multiply it by MatrixTranslation(pt[0].x, pt[0].y, pt[0].z)

Though, thats a waste of resources. You can do it immediately:
Matrix c = MatrixTranslation(-pt[0].x, -pt[0].y, -pt[0].z) * MatrixRotationZ(my_angle) * MatrixTranslation(pt[0].x, pt[0].y, pt[0].z)
for each vertex, multiply it by c
Hi,

Thanks very much for the replies. Apparently, even with the help their are still some issues. hamesterman, the code snippet below gets the triangle rotating about one of its verticies, and the triangle can rotate a full 360 degrees, but when it reaches the 180 degree mark, it streches (scales itself). I am not sure if that is correct?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
DrawStuffs()
{
     Matrix4 rz;                         // current rotation matrix about z axis
     static Matrix4 c;                   // composition matrix

// set up the original points for the triangle
    pts[0].set(	50,  50, 0);
    pts[1].set(100, 100, 0);
    pts[2].set(100,   0, 0);
	
	
    rz.makeTranslationMatrix(-(pts[0].x = 50), -(pts[0].y = 50), pts[0].z = 0);
	
	rz.makeRotationMatrixZ(angle);
	// update the composite matrix

	c = Multiply(rz, c);

	// transform the original triangle points into the new points for drawing
    for (int i=0; i < 3; i++) {   
		newPts[i] = Multiply(c, pts[i]); // Get new set of coordinates by multiplying for each iteration.

		// translate position for each vertex
		rz.makeTranslationMatrix(-(pts[i].x), -(pts[i].y), -(pts[i].z));
		rz.makeRotationMatrixY(angle);
		rz.makeTranslationMatrix(pts[i].x, pts[i].y, pts[i].z);
		
	}

	rz.makeTranslationMatrix(newPts[0].x = 50, newPts[0].y = 50, newPts[0].z = 0);
	
	// draw the triangle lines 0-1, 1-2, 2-0
    DrawLine(newPts[0].x, newPts[0].y, newPts[1].x, newPts[1].y, green);
    DrawLine(newPts[1].x, newPts[1].y, newPts[2].x, newPts[2].y, green);
    DrawLine(newPts[2].x, newPts[2].y, newPts[0].x, newPts[0].y, green);

	
    // draw the points
    PGraphics->Draw();
}


I noticed that I get no rotation (the triangle is stuck even when i want rotate more) if i use the "static Matrix4 c" varaible. The 'c' matrix4 type varaible is for my combo matrix, but it prevents rotation when i use it in-place of rz...
Last edited on
What library are you using?
For example, when you have
1
2
3
rz.makeTranslationMatrix(-(pts[i].x), -(pts[i].y), -(pts[i].z));
rz.makeRotationMatrixY(angle);
rz.makeTranslationMatrix(pts[i].x, pts[i].y, pts[i].z);
does this mean that rz is first multiplied by a translation matrix, then by rotation matrix and then again, by a translation matrix? are you sure, this doesn't just overwrite the value in rz?

If it does multiply, then your code should probably look like this
1
2
3
4
5
6
7
8
9
10
<set up the original triangle...>
Matrix4 rz;
rz.makeTranslationMatrix(-(pts[i].x), -(pts[i].y), -(pts[i].z));
rz.makeRotationMatrixY(angle);
rz.makeTranslationMatrix(pts[i].x, pts[i].y, pts[i].z);

for (int i=0; i < 3; i++) 
   newPts[i] = Multiply(rz, pts[i]);

<draw the triangle..>
I am using a "gmath.h" file, which has the following function defintions relevent to my problem:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
void makeTranslationMatrix(double dx, double dy, double dz) {
        // makes a translation matrix
        m[0][0] = 1.0;  m[0][1] = 0.0;  m[0][2] = 0.0;  m[0][3] = dx;   
        m[1][0] = 0.0;  m[1][1] = 1.0;  m[1][2] = 0.0;  m[1][3] = dy;   
        m[2][0] = 0.0;  m[2][1] = 0.0;  m[2][2] = 1.0;  m[2][3] = dz;   
        m[3][0] = 0.0;  m[3][1] = 0.0;  m[3][2] = 0.0;  m[3][3] = 1.0;   
    }

Vector3 Multiply(Matrix4 m, Vector3 a) { // using this to multiply matrix c or rz and the pts vector
    // returns result = m * a
    Vector3 result;
    result.x = m.m[0][0] * a.x + m.m[0][1] * a.y + m.m[0][2] * a.z + m.m[0][3] * a.w;
    result.y = m.m[1][0] * a.x + m.m[1][1] * a.y + m.m[1][2] * a.z + m.m[1][3] * a.w;
    result.z = m.m[2][0] * a.x + m.m[2][1] * a.y + m.m[2][2] * a.z + m.m[2][3] * a.w;
    result.w = m.m[3][0] * a.x + m.m[3][1] * a.y + m.m[3][2] * a.z + m.m[3][3] * a.w;
    return result;
}

// multiplies vector a by matrix m
Vector3 Multiply(Vector3 a, Matrix4 m) {
    // returns result = a * m
    Vector3 result;
    result.x = a.x * m.m[0][0] + a.y * m.m[1][0] + a.z * m.m[2][0] + a.w * m.m[3][0];
    result.y = a.x * m.m[0][1] + a.y * m.m[1][1] + a.z * m.m[2][1] + a.w * m.m[3][1];
    result.z = a.x * m.m[0][2] + a.y * m.m[1][2] + a.z * m.m[2][2] + a.w * m.m[3][2];
    result.w = a.x * m.m[0][3] + a.y * m.m[1][3] + a.z * m.m[2][3] + a.w * m.m[3][3];
    return result;
}

// multiply x X y using loops
Matrix4 Multiply(Matrix4 x, Matrix4 y) {
    int i, j, k;
    Matrix4 result;

    for(i=0; i < 4; i++) {
        for(j=0; j < 4; j++) {
            result.m[i][j] = 0.0;
            for(k=0; k < 4; k++) {
                result.m[i][j] += x.m[i][k] * y.m[k][j];    
            }
        }
    }
    return result;
}

void makeRotationMatrixZ(double angle) {
        double angleInRads = angle * DTOR; // where DTOR is = 0.01745329251994;     // degrees to radians
        makeRotationMatrixZ(sin(angleInRads), cos(angleInRads));
    }

    void makeRotationMatrixZ(double sinA, double cosA){
        // makes rotation matrix about Z-axis
        m[0][0] =  cosA; m[0][1] = -sinA;  m[0][2] = 0.0;  m[0][3] = 0.0;   
        m[1][0] =  sinA; m[1][1] =  cosA;  m[1][2] = 0.0;  m[1][3] = 0.0;   
        m[2][0] =   0.0; m[2][1] =   0.0;  m[2][2] = 1.0;  m[2][3] = 0.0;   
        m[3][0] =   0.0; m[3][1] =   0.0;  m[3][2] = 0.0;  m[3][3] = 1.0;   
    }
well. It seems that no multiplication is involved. Then the code woul be like this
1
2
3
4
5
6
7
8
9
10
11
12
<set up the original triangle...>
Matrix4 t1, rz, t2;
t1.makeTranslationMatrix(-(pts[i].x), -(pts[i].y), -(pts[i].z));
rz.makeRotationMatrixY(angle);
t2.makeTranslationMatrix(pts[i].x, pts[i].y, pts[i].z);

Matrix4 c = Multiply(Multiply(t1, rz), t2);

for (int i=0; i < 3; i++) 
   newPts[i] = Multiply(c, pts[i]);

<draw the triangle..>


As I suspected, the main problem was that you kept overwriting you matrices instead of multiplying them.
Last edited on
The display is a single line if I iterate for each point after your matrix declarations (functions using t1, rz and t2). when using 0 for an index, yeilds no rotation. Shouldn't c be static?
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<set up the original triangle...>
pts[0].set(50,50,0);
pts[1].set(100,100,0);
pts[2].set(100,0,0);

Matrix4 t1, rz, t2; // declare two translation matrix varaibles and a rotation varaible, rz.

// translate one vertex to the origin
t1.makeTranslationMatrix(-(pts[0].x = 50), -(pts[0].y = 50), -(pts[0].z = 1)); // dx = -50, dy = -50

// rotate about the angle the user has inputted
rz.makeRotationMatrixY(angle);

//translate to a different position
t2.makeTranslationMatrix(pts[0].x = 50, pts[0].y = 50, pts[0].z = 1);


// the two steps above is a combo matrix, so declare a Matrix4 'c' varaible

// varaible 'c' holds the data of first translation multipled by its rotation and that result is multiplied by t2
Matrix4 c = Multiply(Multiply(t1, rz), t2);

// get the new points
for (int i=0; i < 3; i++) 
   newPts[i] = Multiply(c, pts[i]);


<draw the triangle..>


Your advice has been excellent, I do have a question about the undeclared 'i' varaible right before the new Matrix4 type varaible declarations: t1 and t2. I think I should be translating the first point. If I iterate through them, the mesh is deformed..
Last edited on
Oh sorry. i is there because I simply copy pasted from your for loop..

By the way, why do you write stuff like makeTranslationMatrix(-(pts[0].x = 50), -(pts[0].y = 50), -(pts[0].z = 1));? You have already defined pts[0]. You don't need to reassign its x y and z.
I figured that ^_^

I thought that I had three steps to the process as you explained earilier:

1
2
3
4
The steps you need to take are these:
1. translate the whole mesh, so that a chosen vertex is at the origin
2. rotate the mesh as much as you want
3. translate the mesh back to it's previous position 


Given the set of coordinates:
1
2
3
pts[0].set(50,50,0);
pts[1].set(100,100,0);
pts[2].set(100,0,0);


I would then translate a vertex (whichever) to the origin. I chose the first pt, so translating to the origin would be:

 
t1.makeTranslationMatrix(-(pts[0].x = 50), -(pts[0].y = 50), -(pts[0].z = 1));? 


So then I rotate it and make another translation:

1
2
3
// rotate about the angle the user has inputted
rz.makeRotationMatrixY(angle);
t2.makeTranslationMatrix(pts[0].x, pts[0].y, pts[0].z);


We then multiply:
 
Matrix4 c = Multiply(Multiply(t2, rz), t1);


and loop through each point to get new points:

1
2
for (int i=0; i < 3; i++)
newPts[i] = Multiply(c, pts[i]); // Get new set of coordinates	 


then we draw each new point:
1
2
3
DrawLine(newPts[0].x, newPts[0].y, newPts[1].x, newPts[1].y, green);
DrawLine(newPts[1].x, newPts[1].y, newPts[2].x, newPts[2].y, green);
DrawLine(newPts[2].x, newPts[2].y, newPts[0].x, newPts[0].y, green);


This is not working :(
Last edited on
What does it do?
--It doesn't rotate.

I need to be able to keep clicking "Draw" which keeps rotating the triangle by the specified value. That is why I think the matrix4 type varaible 'c' needs to be static..

how do I upload an ss? ;x
Last edited on
Well yeah. I suggest you make angle static. Or even better pass it as an argument.
Going from 'rotating by a fixed angle' and 'rotating by a little bit move on every frame' isn't the hard part. The question is, did the triangle rotate?
I don't know why it is not rotating. Before it would, but that was with only using rz outside of the Multiply() function.
OK. If I specifiy a different angle (different to the original upon first execution) it will rotate, But i need to be able to hold enter and see it move, not keep going back and choose a different angle value..
your app could look something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
void draw_trinagle(float angle){
   //...
}

int main(){
   float angle = 0;
   while(true){
      if(ENTER key is down){
         angle += 0.01;
         draw_triangle(angle);
      }
   }
}
Well, I thought that a static declaration would allow the matrix in my program to retain its values from one function call to the next (like a global variable). So each time that I press the "Draw" button the program would add another 5 degrees is added to the rotation, if I were to do enter 5 for the degree..

Last edited on
And also, the whole triangle is rotating, i just it rotate about the chosen vertex..
Why doesn't this work?:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

// set up the original points for the triangle
    pts[0].set(50,  50, 0); // Vertex A
    pts[1].set(100, 100, 0); // Vertex B
    pts[2].set(100,   0, 0);   // Vertex C
	

      // Translate the whole mesh so that the vertex, A(Ax, Ay, Az) is at the origin
     c.makeTranslationMatrix(-pts[0].x, -pts[0].y, -pts[0].z); //dx = -50, dy = -50, dz = 0
	
     // rotate and mulitply
     rz.makeRotationMatrixZ(angle);
     c = Multiply(c, rz); // multiply our previous translation by our current rotation. "combine"
	
     // use a new varaible for translation BACK to the original positon
     t1.makeTranslationMatrix(pts[0].x, pts[0].y, pts[0].z); // dx = 50, dy = 50, dz = 0
    
     // Multiply our previous translation by our previous rotation, and then by c: "Preform Composition"
     c = Multiply(Multiply(t1, rz), c)

    // Draw our new points
    for (int i=0; i<3; i++) {
		newPts[i] = Multiply(c, pts[i]);
	}

<draw triangle>


I guess i am just not getting this. I can program hash tables, doubly linked lists, concepts around STL vectors and containors, and this 3 step program is giving me trouble?

:////

Pages: 12