I use this method which works perfectly to draw a full circle(might be typos in code text I wrote from memory):
drawCircle(GLAutodrawble drawble){
GL gl = drawble.getGL();
gl.glTranslatef(0.0f,0.0f,-7.0f);
gl.glBeginf(GL_LINE_LOOP);
gl.glColorf(0.0f,0.0f,0.0);
final dobule PI = 3.141592654;
double angle = 0.0;
int points = 100;
for(int i =0; i < points;i++){
angle = 2 * PI * i / points;
gl.glVertexf((float)Math.cos(angle),(float)Math.sin(angle));
}
gl.glScalef(1.0f,1.0f,0.0f);
gl.glEnd();
}
I want to use the same priciples to make method to make a half circle, I don't get my head around what I should do with the cos sin stuff. Can anyone take a look and help me.
Thanks goes to all that thakes a look at the problem!
Replace :
angle = 2 * PI * i / points;
With :
angle = PI * i / points;
Notice I removed the 2 multiplier as 2*PI is 360 (in degrees) which is a full circle. PI (180 degrees) is half a circle
Change this line:
angle = 2 * PI * i / points;
to this:
angle = 1 * PI * i / points;
Drawing circle is like the drawing a lines , connecting them. And the points should too close to each other to create a smooth curve.
you can use the following code to draw a half circle in opengl.
float PI = 3.14
float step=5.0;// How far is the next point i.e it should be small value
glBegin(GL_LINE_STRIP)
for(float angle=0.0f,angle<=180; angle+=step)
{
float rad = PI*angle/180;
x = centerX+radius*cos(rad);
y = centerY+radius*sin(rad);
glVertex(x,y,0.0f);
}
glEnd();
Related
I have a camera that has X, Y and Z Coordinates.
The camera also has a Yaw and a pitch.
int cameraX = Camera.getX();
int cameraY = Camera.getY();
int cameraZ = Camera.getZ();
int cameraYaw = Camera.getYaw();
int cameraPitch = Camera.getPitch();
The yaw has 2048 units in 360 degrees, so at 160 degrees the getYaw() method will return 1024.
Currently I move the camera forward by just setting the Y + 1 in each loop.
Camera.setY(Camera.getY() + 1);
How would I set the camera X and Y to the direction I'm facing (The Yaw)?
I don't want to use the pitch in this situation, just the Yaw.
If I understand your question correctly, you're trying to get the camera to move in the direction you're looking (in 2D space, you're only moving horizontally).
I made a small LookAt header-only library for C++, but here is part of it rewritten in Java. What this code does is it takes a rotation and a distance, then calculates how far you need to move (in both the x and y coordinate) to get there.
// Returns how far you need to move in X and Y to get to where you're looking
// Rotation is in degrees, distance is how far you want to move
public static double PolarToCartesianX(double rotation, double distance) {
return distance * Math.cos(rotation * (Math.PI / 180.0D));
}
public static double PolarToCartesianY(double rotation, double distance) {
return distance * Math.sin(rotation * (Math.PI / 180.0D));
}
I want to draw an arc using center point,starting point,ending point on opengl surfaceview.I have tried this given below code so far. This function draws the expected arc if we give the value for start_line_angle and end_line_angle manually (like start_line_angle=0 and end_line_angle=90) in degree.
But I need to draw an arc with the given co-ordinates(center point,starting point,ending point) and calculating the start_line_angle and end_line_angle programatically.
This given function draws an arc with the given parameters but not giving the desire result. I've wasted my 2 days for this. Thanks in advance.
private void drawArc(GL10 gl, float radius, float cx, float cy, float start_point_x, float start_point_y, float end_point_x, float end_point_y) {
gl.glLineWidth(1);
int start_line_angle;
double sLine = Math.toDegrees(Math.atan((cy - start_point_y) / (cx - start_point_x))); //normal trigonometry slope = tan^-1(y2-y1)/(x2-x1) for line first
double eLine = Math.toDegrees(Math.atan((cy - end_point_y) / (cx - end_point_x))); //normal trigonometry slope = tan^-1(y2-y1)/(x2-x1) for line second
//cast from double to int after round
int start_line_Slope = (int) (sLine + 0.5);
/**
* mapping the tiriogonometric angle system to glsurfaceview angle system
* since angle system in trigonometric system starts in anti clockwise
* but in opengl glsurfaceview angle system starts in clock wise and the starting angle is 90 degree of general trigonometric angle system
**/
if (start_line_Slope <= 90) {
start_line_angle = 90 - start_line_Slope;
} else {
start_line_angle = 360 - start_line_Slope + 90;
}
// int start_line_angle = 270;
// int end_line_angle = 36;
//casting from double to int
int end_line_angle = (int) (eLine + 0.5);
if (start_line_angle > end_line_angle) {
start_line_angle = start_line_angle - 360;
}
int nCount = 0;
float[] stVertexArray = new float[2 * (end_line_angle - start_line_angle)];
float[] newStVertextArray;
FloatBuffer sampleBuffer;
// stVertexArray[0] = cx;
// stVertexArray[1] = cy;
for (int nR = start_line_angle; nR < end_line_angle; nR++) {
float fX = (float) (cx + radius * Math.sin((float) nR * (1 * (Math.PI / 180))));
float fY = (float) (cy + radius * Math.cos((float) nR * (1 * (Math.PI / 180))));
stVertexArray[nCount * 2] = fX;
stVertexArray[nCount * 2 + 1] = fY;
nCount++;
}
//taking making the stVertextArray's data in reverse order
reverseArray = new float[stVertexArray.length];//-2 so that no repeatation occurs of first value and end value
int count = 0;
for (int i = (stVertexArray.length) / 2; i > 0; i--) {
reverseArray[count] = stVertexArray[(i - 1) * 2 + 0];
count++;
reverseArray[count] = stVertexArray[(i - 1) * 2 + 1];
count++;
}
//reseting the counter to initial value
count = 0;
int finalArraySize = stVertexArray.length + reverseArray.length;
newStVertextArray = new float[finalArraySize];
/**Now adding all the values to the single newStVertextArray to draw an arc**/
//adding stVertextArray to newStVertextArray
for (float d : stVertexArray) {
newStVertextArray[count++] = d;
}
//adding reverseArray to newStVertextArray
for (float d : reverseArray) {
newStVertextArray[count++] = d;
}
Log.d("stArray", stVertexArray.length + "");
Log.d("reverseArray", reverseArray.length + "");
Log.d("newStArray", newStVertextArray.length + "");
ByteBuffer bBuff = ByteBuffer.allocateDirect(newStVertextArray.length * 4);
bBuff.order(ByteOrder.nativeOrder());
sampleBuffer = bBuff.asFloatBuffer();
sampleBuffer.put(newStVertextArray);
sampleBuffer.position(0);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(2, GL10.GL_FLOAT, 0, sampleBuffer);
gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, nCount * 2);
gl.glLineWidth(1);
}
To begin with the trigonometry you may not simply use the atan to find degrees of the angle. You need to check what quadrant the vector is in and increase or decrease the result you get from atan. Better yet use atan2 which should include both dx and dy and do the job for you.
You seem to create the buffer so that a point is created per degree. This is not the best solution as for large radius that might be too small and for small radius this is way too much. Tessellation should include the radius as well such that number of points N is N = abs((int)(deltaAngle*radius*tessellationFactor)) then use angleFragment = deltaAngle/N but make sure that N is greater then 0 (N = N?N:1). The buffer size is then 2*(N+1) of floats and the iteration if for(int i=0; i<=N; i++) angle = startAngle + angleFragment*i;.
As already pointed out you need to define the radius of the arc. It is quite normal to use an outside source the way you do and simply force it to that value but use the 3 points for center and the two borders. Some other options that usually make sense are:
getting the radius from the start line
getting the radius from the shorter of the two lines
getting the average of the two
interpolate the two to get an elliptic curve (explained below)
To interpolate the radius you need to get the two radiuses startRadius and endRadius. Then you need to find the overall radius which was already used as deltaAngle above (watch out when computing this one, it is more complicated as it seems, for instance drawing from 320 degrees to 10 degrees results in deltaAngle = 50). Anyway the radius for a specific point is then simply radius = startRadius + (endRadius-startRadius)*abs((angleFragment*i)/deltaAngle). This represents a simple linear interpolation in polar coordinate system which is usually used to interpolate vector in matrices and is the core functionality to get nice animations.
There are some other ways of getting the arc points which may be better performance wise but I would not suggest them unless and until you need to optimize your code which should be very late in production. You may simply keep stepping toward the next point and correcting the radius (this is only a concept):
vec2 start, end, center; // input values
float radius; // input value
// making the start and end relative to center
start -= center;
end -= center;
vec2 current = start/length(start) * radius; // current position starts in first vector
vec2 target = end/length(end) * radius; // should be the last point
outputBuffer[0] = current+center; // insert the first point
for(int i=1;; i++) { // "break" will need to exit the loop, we need index only for the buffer
vec2 step = vec2(current.y, -(current.x)); // a tangential vector from current start point according to center
step = step/length(step) / tessellationScale; // normalize and apply tessellation
vec2 next = current + step; // move tangentially
next = next/length(next) * radius; // normalize and set the
if(dot(current-target, next-target) > .0) { // when we passed the target vector
current = next; // set the current point
outputBuffer[i] = current+center; // insert into buffer
}
else {
current = target; // simply use the target now
outputBuffer[i] = current+center; // insert into buffer
break; // exit
}
}
UPDATE
Slick and JBox use radians that go in opposite directions, that's why I was having trouble.
I am making a game using JBox2D and Slick2D (per the title). So, because I couldn't find anything online about it, I wrote a bunch of code from scratch to convert between them. However, it seems as though the angles are different, even though both documentations say they use radians.
Here is my code:
//In the update function
angle = (float) (angle % 2*Math.PI);
mass = player.getMass();
position = player.getPosition();
if(input.isKeyDown(inputLeft)){
angle-=0.015f*turnBlocks.size()/mass; //turning, pt1
} else if(input.isKeyDown(inputRight)){
angle+=0.015f*turnBlocks.size()/mass;
}
player.setTransform(position, angle); //turning, pt2
if(input.isKeyDown(inputForward)){
float xv = (float)(0.25f * Math.sin(angle) *
thrustBlocks.size() / mass); //Converting angle to vector
float yv = (float)(0.25f * Math.cos(angle) *
thrustBlocks.size() / mass);
Vec2 curVel = player.getLinearVelocity();
xv = xv + curVel.x;
yv = yv + curVel.y;
player.setLinearVelocity(new Vec2(xv, yv));
}
and
//In the render function
g.setColor(Color.gray);
for(int mass = 0; mass < massBlocks.size(); mass++){
float boxx = (float)massBlocks.get(mass)[0];
float boxy = (float)massBlocks.get(mass)[1];
int[] slicklist = tr.toSlick(position.x+boxx, position.y+boxy);
boxx = (float)slicklist[0];
boxy = (float)slicklist[1];
float[] ps = {boxx-tr.xscale/2, boxy-tr.yscale/2,
boxx+tr.xscale/2, boxy-tr.yscale/2,
boxx+tr.xscale/2, boxy+tr.yscale/2,
boxx-tr.xscale/2, boxy+tr.yscale/2};
Polygon p = new Polygon(ps);
//turning, pt3
g.fill(p.transform(Transform.createRotateTransform(radAngle, slickx, slicky)));
}
When I run the above code (with the rest of it), I get the player block(s) moving in the direction it shows it is facing. However, the collision in Jbox2D is out of sync. Here is the pattern I have found:
1 unit = pi/4 in slick
Slick direction:
7___0___1
6___.___2
5___4___3
Jbox Direction:
5___0___3
2___.___6
7___4___1
Really, I have no idea what is going on. Can somebody help?
Okay. It turns out that even thought Slick's transform and JBox's angle are both radians, They go in opposite directions. So, I made the below code with the .getWorldPosition instead of transform.
float localJBoxX = thrustBlocks.get(count)[0];
float localJBoxY = thrustBlocks.get(count)[1];
float[] localEndCoords = {localJBoxX+0.5f, localJBoxY+0.5f,
localJBoxX-0.5f, localJBoxY+0.5f,
localJBoxX-0.5f, localJBoxY-0.5f,
localJBoxX+0.5f, localJBoxY-0.5f};
float[] slickCoords = new float[localEndCoords.length];
for(byte point = 0; point<localEndCoords.length/2; point++){
Vec2 localPoint = new Vec2(localEndCoords[point*2], localEndCoords[point*2+1]);
slickCoords[point*2] = (float)tr.toSlick(player.getWorldPoint(localPoint).x, player.getWorldPoint(localPoint).y)[0];
slickCoords[point*2+1] = (float)tr.toSlick(player.getWorldPoint(localPoint).x, player.getWorldPoint(localPoint).y)[1];
}
Polygon box = new Polygon(slickCoords);
g.fill(box.transform(new Transform())); //as to return a shape
I'm currently trying to implement a draw method for a circle however my only tools are drawing lines from multiple points (specifcally for this example, I have a "pen" that i can move to, then draw from that location to a new location on a grid.)
This is my current code
public void draw(WinPlotter plotter){
setPenColor(plotter);
plotter.moveTo(xo,yo); //xo,yo being original X and Y cords (origin)
for (int i = 0; i > 360; i++){
double x = Math.sin(i) * radius;
double y = Math.cos(i) * radius;
plotter.drawTo(x,y);
}
}
I'm not sure what i'm missing, but this actually won't output anything at all, I've tested to make sure that xo and yo are being passed to the method properly, so i'm confident that my problem lies in my logic of trying to draw a circle from lines.
EDIT:
public void draw(WinPlotter plotter){
setPenColor(plotter);
plotter.moveTo(xo,yo+radius);
for (int i = 0; i <= 360; i++){
double x = xo+ Math.sin(i * (Math.PI / 180)) * radius;
double y = yo+ Math.cos(i) * radius;
plotter.drawTo(x,y);
}
}
This is my fixed code. Still does not create circles, instead creates this (the circles are supposed to be on the top)
Issue 1: sin() and cos() are expecting inputs in radians, not degrees. To get radians, multiply i by Math.PI / 180.
Issue 2: The conditional in your loop is backward; you want i < 360, not i > 360. If you want to close the circle, use i <= 360 instead.
Issue 3: You're not adding xo and yo to the calculated x/y coordinates, so you're drawing all of the circle except the first point at the (0, 0) origin.
Issue 4: Your initial moveTo() goes to the center of the circle instead of the point on the circle at 0 degrees.
I'm trying to make a useful/generic 2D polygon class for an OpenGL ES renderer.
When I create a polygon, I give it several parameters:
Polygon(Vector3 centerpoint, int numVertices, float inPolySize)
Then, I try to generate the vertices. This is where i'm having a tough time. I need to determine the number of vertices, get an angle, find the x/y position of that angle, someone take the size into account, AND offset by the position.
OpenGL works with big arrays of data. Nothing is nice like Lists of Vector3's. Instead it's float[] arrays, with the first index being X1, second being Y1, third being Z1, fourth being X2, etc...
final int XPOS = 0;
final int YPOS = 1;
final int ZPOS = 2;
int mvSize = 3; // (x, y, z);
float[] vertices = new float[mvSize * mNumVertices];
for (int verticeIndex = 0; verticeIndex < mNumVertices; verticeIndex++)
{
double angle = 2 * verticeIndex * Math.PI / mNumVertices;
vertices[mvSize * verticeIndex + XPOS] = (((float)Math.cos(angle)) * mPolygonSize) + mPosition.GetX();
vertices[mvSize * verticeIndex + YPOS] = (((float)Math.sin(angle)) * mPolygonSize) + mPosition.GetY();
vertices[mvSize * verticeIndex + ZPOS] = mPolygonSize + mPosition.GetZ();
}
Unfortunatley, my triangle is never quite right. It's skewed a lot, the size doesn't seem right...
I figure i'm throwing the size into the wrong formula, can anyone help?
EDIT:
Here's some sample data
Polygon test = new Polygon( new Vector3(0, 1, 0), 3, .5f);
vertices[0] = -0.25
vertices[1] = 1.4330127
vertices[2] = 0.0
vertices[3] = -0.25
vertices[4] = 0.5669873
vertices[5] = 0.0
vertices[6] = 0.5
vertices[7] = 1.0
vertices[8] = 0.0
vertices[9] = -0.25
vertices[10] = 1.4330127
vertices[11] = 0.0
I can't believe I was this stupid. Basically, my render window was smaller than my screen. If my screen is a rectangle, my render window was a square.
This being the case, any triangle I draw that was up was clipped by my render window. To me, it looked like the triangle was skewed. Really, it was just clipped!
The Java math library takes radians as input, not degrees. I didn't see the angles you were using for your calculation, but if you're not converting to radians from degrees, you will get some skewed looking shapes, and would explain that your calculations are correct, but the expected result is off.