Bezier Patch Problem (probably not difficult)
I have been working with bezier patches (using NeHe''s code), and I need to make an object follow the contours of a patch. I don''t completely understand all the math involved in the patch yet, so if someone could help me out a little bit, that''d be great.
Check out www.gametutorials.com. They have a nice (OpenGL) bezier patch tutorial there. I haven''t looked at it myself, but try it out...
Hope this helps,
Crispy
Hope this helps,
Crispy
"Literally, it means that Bob is everything you can think of, but not dead; i.e., Bob is a purple-spotted, yellow-striped bumblebee/dragon/pterodactyl hybrid with a voracious addiction to Twix candy bars, but not dead."- kSquared
Thanks for the help. I figured out how to do it in 2D, but the patches I''m working with are 3D. I''m a little confused by how NeHe''s code works. Does it calculate the y curve, and then using the newly generated points, calculate the x curve? I''m probably missing something obvoius, so, if you know what it is...
Not sure I get exactly what you are willing to do...
You want to follow the contour of a bezier patch, right.
It means follow the outer bezier curves of the patch.
That''s quite easy.
Lets say you have the 4 points A B C D that define the bezier
curve (A and D being the beginning and the end, B and C being the control points).
The bezier curve is defined as a set of barycenters of those 4 points using the following weights :
k^3 for A
3*k^2*(1-k) for B
3*k*(1-k)^2 for C
(1-k)^3 for D
When k varies between 0 and 1, the corresponding barycenters follows the bezier curve from A to D.
Just repeat this for the 4 borders of your bezier patch, and you''re done.
Hope it helps.
You want to follow the contour of a bezier patch, right.
It means follow the outer bezier curves of the patch.
That''s quite easy.
Lets say you have the 4 points A B C D that define the bezier
curve (A and D being the beginning and the end, B and C being the control points).
The bezier curve is defined as a set of barycenters of those 4 points using the following weights :
k^3 for A
3*k^2*(1-k) for B
3*k*(1-k)^2 for C
(1-k)^3 for D
When k varies between 0 and 1, the corresponding barycenters follows the bezier curve from A to D.
Just repeat this for the 4 borders of your bezier patch, and you''re done.
Hope it helps.
SaM3d!, a cross-platform API for 3d based on SDL and OpenGL.The trouble is that things never get better, they just stay the same, only more so. -- (Terry Pratchett, Eric)
Okay, I understand the process now, but my object is constantly jumping up and down as I move him. I am loading the map from a file, and in one tile, the array for vertices stores them in this order:
[0][3]|--------|[0][0]
| |
| |
| |
[3][3]|--------|[3][0]
Here''s my code:
struct Vertex
{
double x,y,z;
};
struct Quad
{
Vertex Vertices[4][4];
float tex, divs;
int X,Y;
struct Quad* next;
struct Quad* previous;
};
struct TextureImage
{
GLubyte *imageData;
GLuint bpp;
GLuint width;
GLuint height;
GLuint texID;
TextureImage* next;
};
struct Unit
{
Vertex pos;
double px,py;
};
Vertex Bernstein(double u, Vertex *p) {
Vertex a, b, c, d, r;
a = pointTimes(pow(u,3), p[0]);
b = pointTimes(3*pow(u,2)*(1-u), p[1]);
c = pointTimes(3*u*pow((1-u),2), p[2]);
d = pointTimes(pow((1-u),3), p[3]);
r = pointAdd(pointAdd(a, b), pointAdd(c, d));
return r;
}
int DrawGLScene(struct Quad* Quads)
{
int loop = 0, u = 0, v;
float py, px, pyold;
struct TextureImage* temptex;
struct Quad* patch = InitQuads();
Vertex temp[4];
Vertex *unitvert = (Vertex*)malloc(sizeof(Vertex));
Vertex *last = (Vertex*)malloc(sizeof(Vertex)*(maxdivs));
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotated(xrot,1,0,0);
glTranslated(xtrans,-ytrans,ztrans);
glTranslatef(-100,-80,-80);
while (loop {
patch = ReadMap(loop, Quads);
temptex = ReadTextures(patch->tex);
glBindTexture(GL_TEXTURE_2D, temptex->texID);
if (!wireframe)
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
else
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
temp[0] = patch->Vertices[0][3];
temp[1] = patch->Vertices[1][3];
temp[2] = patch->Vertices[2][3];
temp[3] = patch->Vertices[3][3];
for (v=0;v<=patch->divs;v++) {
px = ((float)v)/((float)patch->divs);
last[v] = Bernstein(px, temp);
}
for (u=1;u<=patch->divs;u++) {
py = ((float)u)/((float)patch->divs);
pyold = ((float)u-1.0f)/((float)patch->divs);
temp[0] = Bernstein(py, patch->Vertices[0]);
temp[1] = Bernstein(py, patch->Vertices[1]);
temp[2] = Bernstein(py, patch->Vertices[2]);
temp[3] = Bernstein(py, patch->Vertices[3]);
glColor3f(0,0,0);
glBegin(GL_TRIANGLE_STRIP);
for (v=0;v<=patch->divs;v++) {
px = ((float)v)/((float)patch->divs);
glTexCoord2f(pyold, px);
glVertex3d(last[v].x, last[v].y, last[v].z);
last[v] = Bernstein(px, temp);
glTexCoord2f(py, px);
glVertex3d(last[v].x, last[v].y, last[v].z);
}
glEnd();
}
if (patch->Vertices[3][3].x <= unit.pos.x && patch->Vertices[0][0].x >= unit.pos.x)
{
if (patch->Vertices[3][3].y <= unit.pos.y && patch->Vertices[0][0].y >= unit.pos.y)
{
unit.py = (unit.pos.y-patch->Vertices[3][3].y)/(patch->Vertices[0][0].y-patch->Vertices[3][3].y);
temp[0] = Bernstein(unit.py, patch->Vertices[0]);
temp[1] = Bernstein(unit.py, patch->Vertices[1]);
temp[2] = Bernstein(unit.py, patch->Vertices[2]);
temp[3] = Bernstein(unit.py, patch->Vertices[3]);
unit.px = (unit.pos.x-patch->Vertices[3][3].x)/(patch->Vertices[0][0].x-patch->Vertices[3][3].x);
unitvert[0] = Bernstein(unit.px, temp);
glDisable(GL_TEXTURE_2D);
glColor3f(1,1,1);
glBegin(GL_QUADS);
glVertex3f(unit.pos.x,unit.pos.y,unitvert[0].z);
glVertex3f(unit.pos.x+1,unit.pos.y,unitvert[0].z);
glVertex3f(unit.pos.x+1,unit.pos.y+1,unitvert[0].z);
glVertex3f(unit.pos.x,unit.pos.y+1,unitvert[0].z);
glEnd();
glEnable(GL_TEXTURE_2D);
}
}
loop++;
}
}
Basically, what I''m doing is loading Tile coordinates from a linked list, and then drawing the tiles, and then I use the same formula (using the unit''s position on the tile (in %) to calculate another point on a bezier curve, but instead of drawing another point, I just place the unit at that point on the Z axis, but, for some reason my code isn''t working exactly the way I want it to. Sometimes it follows the patches, but occasionally (especially when it crosses between patches) it will jump up or down on the z axis.
[0][3]|--------|[0][0]
| |
| |
| |
[3][3]|--------|[3][0]
Here''s my code:
struct Vertex
{
double x,y,z;
};
struct Quad
{
Vertex Vertices[4][4];
float tex, divs;
int X,Y;
struct Quad* next;
struct Quad* previous;
};
struct TextureImage
{
GLubyte *imageData;
GLuint bpp;
GLuint width;
GLuint height;
GLuint texID;
TextureImage* next;
};
struct Unit
{
Vertex pos;
double px,py;
};
Vertex Bernstein(double u, Vertex *p) {
Vertex a, b, c, d, r;
a = pointTimes(pow(u,3), p[0]);
b = pointTimes(3*pow(u,2)*(1-u), p[1]);
c = pointTimes(3*u*pow((1-u),2), p[2]);
d = pointTimes(pow((1-u),3), p[3]);
r = pointAdd(pointAdd(a, b), pointAdd(c, d));
return r;
}
int DrawGLScene(struct Quad* Quads)
{
int loop = 0, u = 0, v;
float py, px, pyold;
struct TextureImage* temptex;
struct Quad* patch = InitQuads();
Vertex temp[4];
Vertex *unitvert = (Vertex*)malloc(sizeof(Vertex));
Vertex *last = (Vertex*)malloc(sizeof(Vertex)*(maxdivs));
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotated(xrot,1,0,0);
glTranslated(xtrans,-ytrans,ztrans);
glTranslatef(-100,-80,-80);
while (loop
patch = ReadMap(loop, Quads);
temptex = ReadTextures(patch->tex);
glBindTexture(GL_TEXTURE_2D, temptex->texID);
if (!wireframe)
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
else
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
temp[0] = patch->Vertices[0][3];
temp[1] = patch->Vertices[1][3];
temp[2] = patch->Vertices[2][3];
temp[3] = patch->Vertices[3][3];
for (v=0;v<=patch->divs;v++) {
px = ((float)v)/((float)patch->divs);
last[v] = Bernstein(px, temp);
}
for (u=1;u<=patch->divs;u++) {
py = ((float)u)/((float)patch->divs);
pyold = ((float)u-1.0f)/((float)patch->divs);
temp[0] = Bernstein(py, patch->Vertices[0]);
temp[1] = Bernstein(py, patch->Vertices[1]);
temp[2] = Bernstein(py, patch->Vertices[2]);
temp[3] = Bernstein(py, patch->Vertices[3]);
glColor3f(0,0,0);
glBegin(GL_TRIANGLE_STRIP);
for (v=0;v<=patch->divs;v++) {
px = ((float)v)/((float)patch->divs);
glTexCoord2f(pyold, px);
glVertex3d(last[v].x, last[v].y, last[v].z);
last[v] = Bernstein(px, temp);
glTexCoord2f(py, px);
glVertex3d(last[v].x, last[v].y, last[v].z);
}
glEnd();
}
if (patch->Vertices[3][3].x <= unit.pos.x && patch->Vertices[0][0].x >= unit.pos.x)
{
if (patch->Vertices[3][3].y <= unit.pos.y && patch->Vertices[0][0].y >= unit.pos.y)
{
unit.py = (unit.pos.y-patch->Vertices[3][3].y)/(patch->Vertices[0][0].y-patch->Vertices[3][3].y);
temp[0] = Bernstein(unit.py, patch->Vertices[0]);
temp[1] = Bernstein(unit.py, patch->Vertices[1]);
temp[2] = Bernstein(unit.py, patch->Vertices[2]);
temp[3] = Bernstein(unit.py, patch->Vertices[3]);
unit.px = (unit.pos.x-patch->Vertices[3][3].x)/(patch->Vertices[0][0].x-patch->Vertices[3][3].x);
unitvert[0] = Bernstein(unit.px, temp);
glDisable(GL_TEXTURE_2D);
glColor3f(1,1,1);
glBegin(GL_QUADS);
glVertex3f(unit.pos.x,unit.pos.y,unitvert[0].z);
glVertex3f(unit.pos.x+1,unit.pos.y,unitvert[0].z);
glVertex3f(unit.pos.x+1,unit.pos.y+1,unitvert[0].z);
glVertex3f(unit.pos.x,unit.pos.y+1,unitvert[0].z);
glEnd();
glEnable(GL_TEXTURE_2D);
}
}
loop++;
}
}
Basically, what I''m doing is loading Tile coordinates from a linked list, and then drawing the tiles, and then I use the same formula (using the unit''s position on the tile (in %) to calculate another point on a bezier curve, but instead of drawing another point, I just place the unit at that point on the Z axis, but, for some reason my code isn''t working exactly the way I want it to. Sometimes it follows the patches, but occasionally (especially when it crosses between patches) it will jump up or down on the z axis.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement