We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
Page Index Toggle Pages: 1
3d draw (Read 1653 times)
3d draw
Jun 4th, 2005, 11:29pm
 
I've just been messing with this code from Pitaru and the old forum. I'm having a problem with the modelX, modelY, modelZ and screenX, screenY matrix calcs.

Can anyone see how to solve the problem of the long Z addition that occurs after the transformXYX();

It may have something to do with the mouse position. What I'd like to be able to do is always draw from the last position and not have the line draw from the last position to the post-rotated mouse coords.

It seems to require a separate cursor that follows the model transform and starts drawing again from the last position without the leap to mouseX and Y shift caused by using rotate. Is there a way of locking the mouse, or a cursor to the model, yet still allows for mouse movement ?

Sorry for the waffle!!

Code:


int pointCount = 255; // max number of vertexes to save in the shape

// 3 arrays for 3 dimensions...
float[] xpoints = new float[pointCount];
float[] ypoints = new float[pointCount];
float[] zpoints = new float[pointCount];

float x,y,z,ax,ay,az;
int first, last;
float angleX, angleY;
int lastMouseX = 0;
int lastMouseY = 0;
boolean doOnce = false;

void setup()
{
size(400, 400, OPENGL);
first = 0;
last = pointCount - 1;
//smooth();
}

void draw() {
background(255);

applyRotation();


// If mouse btn is pressed, start rotating the stage ...
if (mousePressed){

doOnce = true;
setRotation();
drawShape();
// When mouse btn is not pressed, continue drawing the 'wire'...
} else {
// If mouse btn was just release, do this once...
if ( doOnce){
doOnce = false;

drawShape();
transformXYZ();

// Otherwise, continue drawing the 'wire' ...
} else {
evolveShape();
captureMouse();
drawShape();
}


}

}


// This is Ben Fry's algorythm for re-calculating all existing vertexes, after the stage has been rotated.
void transformXYZ(){

// for every existing vertex in the array...
for(int i = 0; i < pointCount; i++){
x = xpoints[i];
y = ypoints[i];
z = zpoints[i];

// The guts of the algorythm, which uses the 'model matrix' (m00, m01 ..).
// This 'model matrix' is affected by all stage transformations/rotations.
/*
ax = (g.m00*x + g.m01*y + g.m02*z + g.m03);
ay = (g.m10*x + g.m11*y + g.m12*z + g.m13);
az = (g.m20*x + g.m21*y + g.m22*z + g.m23);
*/

ax = modelX(x, y, z);
ax+= screenX(x,y,z);
ay = modelY(x, y, z);
ay+= screenY(x,y,z);
az = modelZ(x, y,z);
az+= screenZ(x,y,z);

xpoints[i] = ax;
ypoints[i] = ay;
zpoints[i] = az;

}

angleX = 0;
angleY = 0;
}

// Draw the 'wire' onto the stage...
void drawShape(){

stroke(100);
beginShape(LINE_STRIP);

for(int j = 0; j < pointCount; j++) {
int i = (first + j) % pointCount;
// stroke( 100 + 155 -(int)((j*100/pointCount) *1.55f) );
curveVertex(xpoints[i], ypoints[i], zpoints[i]);
}
endShape();
}


// We maitain cpu performance by limitting the number of vertices in the 'wire'.
// The size of wire is set by the variable 'pointCount'.
void evolveShape(){
last++;
if (last == pointCount) last = 0;
first++;
if (first == pointCount) first = 0;
}

// Rotate the stage according to the mouse-drag.
void setRotation(){
// If the mouse was dragged more than 3 pixels...
if ( abs(mouseX- lastMouseX) > 1){
angleX += (mouseX- lastMouseX - 1)*0.0008f ;
if(angleX > TWO_PI) { angleX = 0; }
}
// same for Y..
if ( abs(mouseY- lastMouseY) > 1){
angleY += (mouseY- lastMouseY - 1)*0.0008f ;
if(angleY > TWO_PI) { angleY = 0; }
}
}

// Do the actual rotation/transformation of the stage.
void applyRotation(){
translate(width/2, height/2, 0);
rotateY(angleX);
rotateX(-angleY);
translate(-width/2, -height/2, 0);
}

// Capture the mouse coordinates.
void captureMouse(){

xpoints[last] = mouseX;
ypoints[last] = mouseY;
zpoints[last] = 0;

// Buffer the latest coordinates.
lastMouseX = mouseX;
lastMouseY = mouseY;
}

Re: 3d draw
Reply #1 - Jun 5th, 2005, 12:06am
 
You mean those lines that gets made when you rotate and the last point of drawing skips to the current mouseposition of the mousebuttonrelease?
if so my suggestion is to lock the mouse with a
java.awt.Robot,
get the applets current screen position with
Point p = this.getLocationOnScreen();
and set mouseposition with
try { Robot r = new Robot(); } catch(AWTException a){println(a);}
and in draw, on mousepressed
r.mouseMove(lastMX+p.x,lastMY+p.y);

Theeeen, you have to rewrite the rotation so that it rotates around the current mouseposition.. that should be possible, but i'm not great at rotation-math, so that part you'll have to figure out Wink

-seltar
Re: 3d draw
Reply #2 - Jun 5th, 2005, 1:07pm
 

That's the ticket! Hopefully I'll get some sense out of it.

Thanks for the input.

Re: 3d draw
Reply #3 - Jul 15th, 2005, 10:53am
 
I've just dug this out again and the robot only solves part of the problem.

I'd be grateful if anyone could get this code functioning properly.

I think tying the last vertex to the current mouseX/ Y might eliminate the need for a robot and will take care of the snatching to post rotation modified mouse position.

The main problem seems to be in the transformXYZ, given the Z snatch that seems to occur after each rotation.

I've simplified it and eliminated the curveVertex and use an ordinary line function instead, but I'm stumped.

Code:


import processing.opengl.*;



int pointCount = 255; // max number of vertexes to save in the shape

// 3 arrays for 3 dimensions...
float[] xpoints = new float[pointCount];
float[] ypoints = new float[pointCount];
float[] zpoints = new float[pointCount];

float x,y,z,ax,ay,az;
int first, last;
float angleX, angleY;
int lastMouseX = 0;
int lastMouseY = 0;
boolean doOnce = false;

void setup()
{
size(400, 400, OPENGL);
first = 0;
last = pointCount - 1;
//smooth();
}

void draw() {
background(255);

applyRotation();


// If mouse btn is pressed, start rotating the stage ...
if (mousePressed){

doOnce = true;
setRotation();
drawShape();
// When mouse btn is not pressed, continue drawing the 'wire'...
} else {
// If mouse btn was just release, do this once...
if ( doOnce){
doOnce = false;

drawShape();
transformXYZ();

// Otherwise, continue drawing the 'wire' ...
} else {

if(pmouseX != mouseX || pmouseY != mouseY) {
evolveShape();
captureMouse();
}
drawShape();
}


}

}


// This is Ben Fry's algorythm for re-calculating all existing vertexes, after the stage has been rotated.
void transformXYZ(){

// for every existing vertex in the array...
for(int i = 0; i < pointCount; i++){

x = xpoints[i];
y = ypoints[i];
z = zpoints[i];

ax = modelX(x, y, z);
ax+= screenX(x,y,z);
ay = modelY(x, y, z);
ay+= screenY(x,y,z);
az = modelZ(x, y,z);
az+= screenZ(x,y,z);

xpoints[i] = ax;
ypoints[i] = ay;
zpoints[i] = az;

}

angleX = 0;
angleY = 0;
}

// Draw the 'wire' onto the stage...
void drawShape(){

stroke(100);

for(int j = 0; j < pointCount-1; j++) {
int i = (first + j) % pointCount;
int k = (i+1) % pointCount;

line(xpoints[i], ypoints[i], zpoints[i],xpoints[k], ypoints[k], zpoints[k]);
}

}


// We maitain cpu performance by limitting the number of vertices in the 'wire'.
// The size of wire is set by the variable 'pointCount'.
void evolveShape(){
last++;
if (last == pointCount) last = 0;
first++;
if (first == pointCount) first = 0;
}

// Rotate the stage according to the mouse-drag.
void setRotation(){
// If the mouse was dragged more than 3 pixels...
if ( abs(mouseX- lastMouseX) > 1){
angleX += ((mouseX- lastMouseX)*0.0008f) %TWO_PI ;
// if(angleX > TWO_PI) { angleX = 0; }
}
// same for Y..
if ( abs(mouseY- lastMouseY) > 1){
angleY += ((mouseY- lastMouseY)*0.0008f) % TWO_PI ;
// if(angleY > TWO_PI) { angleY = 0; }
}
}

// Do the actual rotation/transformation of the stage.
void applyRotation(){
translate(width/2, height/2, 0);
rotateY(angleX);
rotateX(angleY);
translate(-width/2, -height/2, 0);
}

// Capture the mouse coordinates.
void captureMouse(){

xpoints[last] = mouseX;
ypoints[last] = mouseY;
zpoints[last] = 0;

// Buffer the latest coordinates.
lastMouseX = mouseX;
lastMouseY = mouseY;
}

Re: 3d draw
Reply #4 - Jul 15th, 2005, 4:29pm
 
Hey Mark,

I played around with it and decided I didn't like what Ben's algorithm was doing to the Z axis. So, instead, I rewrote the code to manually compute the X, Y rotation and the effect on each vertex position as you rotate.

This shouldn't put any more load on the processor then before, you're still donig the same math but through different methods.

I left in the same drawing style, but I did briefly test clicking the left mouse to draw and rotating with the right mouse allowing you to rotate to the exact position/view and then drawing the next step.

A step further on from that would be to 'break' the line when you release the left mouse, and start drawing afresh elsewhere on the screen.

To make the optimization look better, it may be an idea to gradient the last 10-20 lines so that they fade to white or completely transparent.

Heres is my code, I put it in P3D and scaled it down - but if you run it locally in OpenGL it is of course much faster at larger resolutions.

http://mkv25.net/applets/_3dDraw/
Re: 3d draw
Reply #5 - Jul 15th, 2005, 4:54pm
 

That certainly seems to take care of it! Thanks a lot. This one's been lurking around for some time and I can only think in 2D, so you can imagine the diffculty I've been having.

Nice one!
Page Index Toggle Pages: 1