I am learning opengl but having problem rendering sphere. I can draw and bind the texture of polygon normally but when I try to use the same method to the sphere drew by triangle strip, it just didn't went well. Part of the texture is broken. (Pic on below)
May I know what did I do wrongly? Sorry if this is an obvious question.
Here are the code of sphere :
(before adding the texture part, the sphere can be displayed normally)
private void drawSphere(GL gl) {
Position spherePosition = state.getSpherePosition();
final float PI = 3.141592f;
gl.glPushMatrix();
if(spheretexture == null){
setSphereTexture();
}
gl.glTranslated(spherePosition.getX(), spherePosition.getY(), spherePosition.getZ());
float[] ambientDiffuse = new float[] {255.0f, 255.0f, 255.0f, 1.0f};
gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT_AND_DIFFUSE, ambientDiffuse, 0);
gl.glEnable(GL_BLEND);
gl.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
float x, y, z, alpha, beta; // Storage for coordinates and angles
float radius = 25f;
int gradation = 10;
for (alpha = 0.0f; alpha < PI; alpha += PI / gradation) {
spheretexture.enable();
spheretexture.bind();
gl.glBegin(GL_TRIANGLE_STRIP);
for (beta = 0.0f; beta < 2.01 * PI; beta += PI / gradation) {
x = (float) (radius * Math.cos(beta) * Math.sin(alpha));
y = (float) (radius * Math.sin(beta) * Math.sin(alpha));
z = (float) (radius * Math.cos(alpha));
gl.glTexCoord2f(beta / (2.0f * PI), alpha / PI);
gl.glVertex3f(x, y, z);
x = (float) (radius * Math.cos(beta) * Math.sin(alpha + PI / gradation));
y = (float) (radius * Math.sin(beta) * Math.sin(alpha + PI / gradation));
z = (float) (radius * Math.cos(alpha + PI / gradation));
gl.glTexCoord2f(beta / (2.0f * PI), alpha / PI + 1.0f / gradation);
gl.glVertex3f(x, y, z);
}
gl.glEnd();
spheretexture.disable();
gl.glDisable(GL_BLEND);
gl.glPopMatrix();
}
}
Output picture:
The major issue is that the top cap of the sphere is drawn twice. That causes Z-fighting. Note, first it is drawn buy the strip between PI-PI/gradation and PI and then it is drawn by the strip between PI and PI+PI/gradation. That is caused, because the outer loop does one an extra pass. Change it to:
for (alpha = 0.0f; alpha < PI-PI/gradation; alpha += PI / gradation) {
// [...]
}
or even better
for (int i = 0; i < gradation; ++ i ) {
float alpha = PI * (float)i / (float)(gradation);
// [...]
}
Related
I want to change the color of the strokes but I can't figure out how to do this correctly I looked up a tutorial and it showed me the hu stuff in the code. That it changes the hu in the for loop but it just remains one color.. In my case yellowish
void setup(){
size(500,500);
colorMode(HSB);
}
float t = 0;
float tn = 0;
void draw(){
background(0);
translate(width / 2, height / 2);
noFill();
stroke(255);
strokeWeight(2);
float hu = 0;
beginShape();
//add vertices...
for(float theta = 0; theta <= 8 * PI; theta += 0.001){
float rad = r(theta,
1, //a
1, //b
sin(tn) * 0.1 + 5, //m
cos(tn) / 2, //n1
sin(t) * 0.5 + 0.5, //n2
cos(t) * 0.5 + 0.5 //n3
);
float x = rad * cos(theta) * 50;
float y = rad * sin(theta) * 50;
stroke(hu, 255, 255);
vertex(x,y);
hu += 1;
if(hu > 255){
hu = 0;
}
}
endShape();
t += 0.1;
tn += 0.1;
}
float r(float theta, float a, float b, float m, float n1, float n2, float n3){
return pow(pow(abs(cos(m * theta / 4.0) / a), n2) +
pow(abs(sin(m * theta / 4.0) / b), n3), -1.0 / n1) ;
}
Please consult the Processing reference for the beginShape function:
The P2D and P3D renderers allow stroke() and fill() to be altered on a per-vertex basis, but the default renderer does not.
In other words, you can't change the stroke color like this with the default renderer. You could just use the P2D renderer instead:
size(500, 500, P2D);
If you need to use the default renderer for some reason, then you're going to have to draw the lines yourself instead of relying on the vertex function.
this is a more math related question.
In my android app I have a canvas that draws a line from start to endpoint.
I also have an angle attribute to rotate the line.
I tried to apply the code bellow to my cocept, but it jumps around weirdly, not pointing in the direction it is supposed to. (0deg = horizontal line)
//Coordinates for P1 and P2
int startx = 0;
int starty = 66;
int endx = 420;
int endy = 66;
//Alpha
float angle = 0.000F;
final float radius = 209.500F;
final float extra_radius = 20.000F; //required later - don't mind it
private void reCal(float[] vals) {
float xAcc = vals[0]*(-1);
float yAcc = vals[1]*(-1);
angle = yAcc / 10.000F * 90.000F;
final float rRadius = radius + extra_radius;
startx = (int) (radius - Math.cos(angle) * rRadius); //left
endx = (int) (radius + Math.cos(angle) * rRadius); //right
starty = 66 + (int) (Math.sin(angle) * rRadius); //top
endy = 66 - (int) (Math.sin(angle) * rRadius); //bot
}
Are their any type conversions that might cause this, or is my math wrong?
UPDATE:
I looked at Math.cos(angle) and Math.sin(angle) at runtime.They jump around between 0 and 1, even if angle is only changed by a little amount.
Now I am wondering: DO THE METHODS TAKE RAD OR DEG AS PARAMETER? (I need deg, obviously)
if you want to rotate a line starting at [cx, cy] and length of dx, use that code snippet:
canvas.save();
canvas.rotate(angle, cx, cy);
canvas.drawLine(cx, cy, cx + dx, cy, paint);
canvas.restore();
(Question is at bottom)Im learning opengl(using lwjgl) and done some drawing of flat shape through sending buffers. Now I need to draw many spheres in single buffer. In my last question, I was advised to use geometry instancing but I dont know how to use any shader language in java yet so I'm trying to make multiple objects in single buffer just like in the examples.
What I tried to generate two spheres by QUAD_STRIP style(using lwjgl's own GLU.Sphere() function to fill the buffers):
n=c1*(c2+1);
float rr=(float) Math.random();
float gg=(float) Math.random();
float bb=(float) Math.random();
float aa=(float) Math.random();
positions = new float[c1 * (c2+1) * 3*2 *2];
normals = new float[c1 * (c2+1) * 3*2 *2];
colors = new float[c1 * (c2+1) * 4*2 *2];
int counter=0;
float drho = 3.141593F / 32.0f;
float dtheta = 6.283186F / 32.0f;
float ds = 1.0F / 32.0f;
float dt = 1.0F / 32.0f;
float t = 1.0F;
/*first sphere*/
for (int i = 0; i < 32; i++) {
float rho = i * drho;
float s = 0.0F;
for (int j = 0; j <= 32; j++) {
float theta = j == 32 ? 0.0F : j * dtheta;
float x = (float) (-Math.sin(theta) * Math.sin(rho));
float y = (float) (Math.cos(theta) * Math.sin(rho));
float z = (float) (1.0f * Math.cos(rho));
normals[counter*3+0]=x*1.0f;normals[counter*3+1]=y*1.0f;normalscounter*3+2]=z*1.0f;
colors[counter*4+0]=rr;colors[counter*4+1]=gg;colors[counter*4+2]=bb;colors[counter*4+3]=1.0f/*aa*/;
positions[counter*3+0]=x*r;positions[counter*3+1]=y*r;positions[counter*3+2]=z*r;
counter++;
x = (float) (-Math.sin(theta) * Math.sin(rho + drho));
y = (float) (Math.cos(theta) * Math.sin(rho + drho));
z = (float) (1.0f * Math.cos(rho + drho));
normals[counter*3+0]=x*1.0f;normals[counter*3+1]=y*1.0f;normals[counter*3+2]=z*1.0f;
colors[counter*4+0]=rr;colors[counter*4+1]=gg;colors[counter*4+2]=bb;colors[counter*4+3]=1.0f/*aa*/;
positions[counter*3+0]=x*r;positions[counter*3+1]=y*r;positions[counter*3+2]=z*r;
counter++;
s += ds;
}
t -= dt;
}
/* first sphere end */
/* second sphere generation */
{
drho = 3.141593F / 32.0f;
dtheta = 6.283186F / 32.0f;
ds = 1.0F / 32.0f;
dt = 1.0F / 32.0f;
t = 1.0F;
for (int i = 0; i < 32; i++) {
float rho = i * drho;
float s = 0.0F;
for (int j = 0; j <= 32; j++) {
float theta = j == 32 ? 0.0F : j * dtheta;
float x = (float) (-Math.sin(theta) * Math.sin(rho));
float y = (float) (Math.cos(theta) * Math.sin(rho));
float z = (float) (1.0f * Math.cos(rho));
normals[counter*3+0]=x*1.0f;normals[counter*3+1]=y*1.0f;normals[counter*3+2]=z*1.0f;
colors[counter*4+0]=rr;colors[counter*4+1]=gg;colors[counter*4+2]=bb;colors[counter*4+3]=1.0f/*aa*/;
positions[counter*3+0]=x*r+1.0f;positions[counter*3+1]=y*r+1.0f;positions[counter*3+2]=z*r+1.0f;
counter++;
x = (float) (-Math.sin(theta) * Math.sin(rho + drho));
y = (float) (Math.cos(theta) * Math.sin(rho + drho));
z = (float) (1.0f * Math.cos(rho + drho));
normals[counter*3+0]=x*1.0f;normals[counter*3+1]=y*1.0f;normals[counter*3+2]=z*1.0f;
colors[counter*4+0]=rr;colors[counter*4+1]=gg;colors[counter*4+2]=bb;colors[counter*4+3]=1.0f/*aa*/;
positions[counter*3+0]=x*r+1.0f;positions[counter*3+1]=y*r+1.0f;positions[counter*3+2]=z*r+1.0f;
counter++;
s += ds;
}
t -= dt;
}
}
/*second sphere end*/
positionsBuf=BufferUtils.createFloatBuffer(c1 * (c2+1) * 3*2 *2);
positionsBuf.put(positions);
positionsBuf.rewind();
colorsBuf=BufferUtils.createFloatBuffer(c1 * (c2+1) * 4*2 *2);
colorsBuf.put(colors);
colorsBuf.rewind();
normalsBuf=BufferUtils.createFloatBuffer(c1 * (c2+1) * 3*2 *2);
normalsBuf.put(normals);
normalsBuf.rewind();
As you can see, below image shows how two spheres are drawn. There is an unwanted link between two.
Most probably the rope is caused by the last point of first sphere and first point of second sphere. Is there some kind of delimiter/drawing-hint to separate two drawings in the same buffer?
Here is how they are drawn:
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,sphereBufferCol.get(0));
GL11.glColorPointer(4, GL11.GL_FLOAT, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, sphereBufferPos.get(0));
GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, sphereBufferNormal.get(0));
GL11.glNormalPointer(GL11.GL_FLOAT, 0, 0);
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
GL11.glEnableClientState(GL11.GL_NORMAL_ARRAY);
//Each sphere is generated 32 by 32 quadstriparray and each having two sets of two points and there are two spheres
GL11.glDrawArrays(GL11.GL_QUAD_STRIP, 0, 32*33*2 *2);
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);
GL11.glDisableClientState(GL11.GL_NORMAL_ARRAY);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
Question: How can I make that rope-like thing disappear without decreasing performance? Maybe putting zero to last and first points' alpha value can make it invisible but wouldnt that cause two holes on each sphere and decrease performance because of many lines on the screen?
All vertex values will be altered by opencl interoperability so single drawing call is needed to draw whole 10000+ spheres.
There seem to be a number of options:
use multiple buffers
use quads instead of quad strips
use primitive restart
use degenerate triangles, i.e. add the last vertex twice
use [instanced rendering] (http://www.opengl.org/wiki/Vertex_Rendering#Instancing)
If you are on newer hardware and want to use quad strips, I'd prefer using primitive restart.
Please note that this is just the result of a quick assessment and anchecked (I personally don't use quad strips or even tri strips that often ;) ).
I'm trying to simulate an analog stick on a mobile platform.
I calculate a stick vector which based on the position of the finger and the radius of the stick returns a value from -1 to 1.
public void calcStickVector(float x, float y)
{
float cx = getCenterX();
float cy = getCenterY();
float distX = x - cx;
float distY = y - cy;
distX /= getRadius();
distY /= getRadius();
distX = JMath.clamp(-1.0f, 1.0f, distX);
distY = JMath.clamp(-1.0f, 1.0f, distY);
stickVector.x = distX;
stickVector.y = distY;
}
public RectF getInnerStickRect()
{
float r = getInnerRadius();
float cx = getCenterX() + (getRadius() * getStickVector().x);
float cy = getCenterY() + (getRadius() * getStickVector().y);
innerStickRect.left = cx - r;
innerStickRect.top = cy - r;
innerStickRect.right = cx + r;
innerStickRect.bottom = cy + r;
return innerStickRect;
}
It almost works, but visually the inner stick, when moved around seems to form a square rather than going around in a circle. Is there something wrong with my logic?
Thanks
As it is, you really are making a box with 1's as the corners. You need to normalize the vector(divide x and y by distance) instead of dividing by radius and clamping.
double dist = Math.sqrt(distX*distX) + (distY*distY));
distX /= dist;
distY /= dist;
I am having an issue with my program; currently it rotates around a set point, and can rotate models around it. Of course, this is a problem as I want it to be a first-person perspective, and currently, it rotates around a point in front of the viewer, instead of the perspective of the viewer. Here is the trigonometric calculations:
protected void drawWireframe(Graphics g) {
double theta = Math.PI * -azimuth / 180.0D;
double phi = Math.PI * elevation / 180.0D;
float cosT = (float) Math.cos(theta);
float sinT = (float) Math.sin(theta);
float cosP = (float) Math.cos(phi);
float sinP = (float) Math.sin(phi);
float cosTcosP = cosT * cosP;
float cosTsinP = cosT * sinP;
float sinTcosP = sinT * cosP;
float sinTsinP = sinT * sinP;
float near = 6.0F;
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
for (int i = 0; i < tiles.size(); i++) {
Point[] points = new Point[vertices.length];
for (int j = 0; j < points.length; j++) {
float x0 = -(tiles.get(i).getX() + xmod + vertices[j]
.getX());
float y0 = (tiles.get(i).getY() + ymod + vertices[j].getY());
float z0 = -(tiles.get(i).getZ() + zmod + vertices[j]
.getZ());
float x1 = cosT * x0 + sinT * z0;
float y1 = -sinTsinP * x0 + cosP * y0 + cosTsinP * z0;
float z1 = cosTcosP * z0 - sinTcosP * x0 - sinP * y0;
if (z1 + near > 0) {
x1 = x1 * near / (z1 + near);
y1 = y1 * near / (z1 + near);
points[j] = new Point((int) (Math.max(getWidth(),
getHeight()) / 2 - (Math.max(getWidth(),
getHeight()) / near) * x1), (int) (Math.max(
getWidth(), getHeight()) / 2 - (Math.max(
getWidth(), getHeight()) / near) * y1));
}
}
}
}
How would I go about moving the rotational point without actually modifying the xmod, ymod and zmod (these are used for movements like jumping, walking, running, crouching... etc)
I know how to figure out how to get the new x, y and z positions, I just don't know how to apply them; if I add them to the mods, it creates a weird loop-d-loop. If I add them to the x1, y1, z1's it doesn't cover the z not rotating from the perspective.
To change the rotation point, you effectively need three transforms:
Translate the coordinate system so that the rotation point becomes the origin.
Perform a rotation around the origin
Translate the coordinate system back again.
This can be factored a number of ways, but that's the basic priniciple: translate->rotate->translate.
The way you "move the rotation point" of an object is by translating the object so that the rotation point is at the origin; do the rotation; then translate the object back. All of this is done in memory, between frames - the user never actually sees the object moving to the origin and back.
By the way, all this stuff is significantly easier if you understand vectors and matrix transformations - as you've seen yourself, without them the code can get out of hand.
Using vectors/matrices, all your code above could be reduced to only a few lines.