I am making a simple 3D Game in which I am moving in a maze. Now I want to implement collecting teapots which are randomly disturbed in the area. The random drawing of teapots is working perfectly. Now I need to make collisions. For that I would like to use AABB algorithm.
Here is how I initialize coords of teapots so they are disturbed in the maze where isn't wall:
for(int i=0; i<5;i++) {
x = random.nextInt(21);
y = random.nextInt(21);
while(wall[x][y]) {
x = random.nextInt(21);
y = random.nextInt(21);
}
if(!wall[x][y]) {
teapot[x][y] = true;
}
}
Here is how I render teapots:
gl.glLoadIdentity();
//render konviček
for(int i=0;i<21;i++) {
for(int j=0; j<21; j++) {
if(labyrinth.getDonut()[i][j]) {
gl.glTranslatef((float) i, 0f, (float) j);
wallTexture.disable(gl);
gl.glColor3f(1.0f, 0.0f, 0.0f);
glut.glutSolidTeapot(0.2);
gl.glTranslatef((float) -i, 0f, (float) -j);
}
}
}
My question is, how to simply implement the AABB algorithm. I know I am supposed to draw a cube around those teapots, however I can't figure out how to code it.
I already have my checkCollision(double X, double Z); method prepared, so I really just need to draw the box around the teapot and get its coordinates.
Related
I have the following code (in Processing Software) which I want to stop the particles before they leave the screen…
So I dont know how to stop them near the edges of the screen…
Please advice…
Thanks
Particle [] pickles = new Particle [100];
void setup () {
size (500, 500);
smooth ();
for (int i=0; i<pickles.length; i++) {
pickles [i] = new Particle ();
}
}
void draw () {
background (0); //clear the background
for (int i=0; i<pickles.length; i++) {
pickles[i].update();
}
}
class Particle {
float x;
float y;
float velX ; // speed or velocity
float velY;
Particle () {
//x and y position to be in middle of screen
x = width/2;
y = height/2;
velX = random (-10, 10);
velY = random (-10, 10);
}
void update () {
x+=velX;
y+=velY;
fill (255);
ellipse (x, y, 10, 10);
}
}
You can check whether a particle is going outside the bounds of the screen by comparing its x and y values to the screen dimensions. For example:
if(x < 0){
// particle is off left edge of screen
}
else if(x > width){
// particle is off right edge of screen
}
When you detect one of these conditions, you can do a number of things:
Remove the particle from the array so it stops using system resources after it leaves the screen
Wrap the value around to the other side of the screen
Have it bounce off the edge by reversing its velocity
Which approach you take depends on exactly what you want to happen.
Shameless self-promotion: here is a tutorial on collision detection in Processing, which includes the above approaches.
I have a Texture that needed to be erase on some point of game. I think its best to clarify my question with picture.
Below is the actual texture.
It is place inside an actor and being call inside the draw after adding to stage.
Below is the partial code of the texture
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
batch.draw(trLine,position.x,position.y);
}
I wanted to erase some part of the texture using a Rectangle with x,y,width And height.And also its can be more than one time. How do I achieve this?
Added: I have found a article that use pixmap to load the texture and modifying it using mask. below is the code, but unfortunately , it draw nothing.
Pixmap mask = new Pixmap(trLine.getRegionWidth(), trLine.getRegionWidth(), Pixmap.Format.Alpha);
mask.setBlending(Pixmap.Blending.None);
mask.setColor(0,0,0,0);
mask.fillRectangle((int)rec.x,(int)rec.y,(int)rec.width,(int)rec.height);
Pixmap fg = new Pixmap(trLine.getRegionWidth(), trLine.getRegionWidth(), Pixmap.Format.RGBA8888);
for (int x = 0; x < trLine.getRegionWidth(); x++) {
for (int y = 0; y < trLine.getRegionHeight(); y++) {
int colorInt = fg.getPixel(trLine.getRegionX() + x, trLine.getRegionY() + y);
fg.drawPixel(colorInt,trLine.getRegionX() + x , trLine.getRegionY() + y);
}
}
fg.drawPixmap(mask, fg.getWidth(), fg.getHeight());
mask.setBlending(Pixmap.Blending.SourceOver);
trBlendedLine=new Texture(fg);
I am currently working on an OpenGL (JOGL) project in java.
The goal is to create a terrain with textures and shading.
I'm creating a random simplex noise, using these values as a heightmap.
The heights are mapped to a 1D texture to simulate coloring based on height.
A material (ambient/diffuse/specular/shininess) is then used to simulate shading.
However; after adding shading to the terrain, 'stripes' appear on each 'column' (Y direction) of the terrain.
The following material is then applied:
TERRAIN(
new float[]{0.5f, 0.5f, 0.5f, 1.0f},
new float[]{0.7f, 0.7f, 0.7f, 1.0f},
new float[]{0.2f, 0.2f, 0.2f, 1.0f},
new float[]{100f})
The material enum constructor:
Material(float[] ambient, float[] diffuse, float[] specular, float[] shininess) {
this.ambient = ambient;
this.diffuse = diffuse;
this.specular = specular;
this.shininess = shininess;
}
I apply the material using the following method:
public void use(GL2 gl) {
// set the material properties
gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GLLightingFunc.GL_AMBIENT, ambient, 0);
gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GLLightingFunc.GL_DIFFUSE, diffuse, 0);
gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GLLightingFunc.GL_SPECULAR, specular, 0);
gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GLLightingFunc.GL_SHININESS, shininess, 0);
}
After creating a 2D 'noisearray' consistent of 0-1 values, an 2D vectorarray is created, consiting of X*Y vectors, where each vector represents a point in the plane/terrain.
Here is the method that draws triangles in between those points, where you can see I draw the plane per column (Y direction):
public void draw(GL2 gl, GLU glu, GLUT glut, Drawer drawer) {
Material.TERRAIN.use(gl);
texture.bind(gl);
if (showGrid)
gl.glPolygonMode( gl.GL_FRONT_AND_BACK, gl.GL_LINE );
ArrayList<Vector[]> normals = new ArrayList<>();
for(int i=1;i<vectors.length;i++) {
gl.glBegin(gl.GL_TRIANGLE_STRIP);
for (int j = 0; j < vectors[i].length; j++) {
Vector normalTopRight, normalBottomLeft;
//Calculate normals top right
Vector v1, v2, triangleCenterTR;
if (j < vectors[i].length - 1)
{
v1 = vectors[i-1][j].subtract(vectors[i][j]);
v2 = vectors[i][j+1].subtract(vectors[i][j]);
normalTopRight = v2.cross(v1).normalized();
// Get center (a+b+c)*(1/3)
triangleCenterTR = (vectors[i][j].add(vectors[i - 1][j]).add(vectors[i][j + 1])).scale(1.0 / 3);
} else {
v1 = vectors[i-1][j].subtract(vectors[i][j]);
v2 = vectors[i][j-1].subtract(vectors[i][j]);
normalTopRight = v1.cross(v2).normalized();
// Get center (a+b+c)*(1/3)
triangleCenterTR = (vectors[i][j].add(vectors[i-1][j]).add(vectors[i][j-1])).scale(1.0/3);
}
normals.add(new Vector[] {triangleCenterTR, triangleCenterTR.add(normalTopRight)});
if (j != 0)
{
v1 = vectors[i][j].subtract(vectors[i-1][j]);
v2 = vectors[i-1][j-1].subtract(vectors[i-1][j]);
normalBottomLeft = v2.cross(v1).normalized();
// Get center (a+b+c)*(1/3)
Vector triangleCenterBL = (vectors[i - 1][j].add(vectors[i][j]).add(vectors[i - 1][j - 1])).scale(1.0 / 3);
normals.add(new Vector[]{triangleCenterBL, triangleCenterBL.add(normalBottomLeft)});
} else {
normalBottomLeft = null; // If j==0, there is no bottom left triangle above
}
/**
* We have everything to start drawing
*/
// Set some color
if (j == 0) {
// Initialization vector
gl.glTexCoord1d(mapTextureToHeight(vectors[i][j].z));
drawer.glVertexV(vectors[i][j]);
} else {
drawer.glNormalV(normalBottomLeft);
}
// Shift left
gl.glTexCoord1d(mapTextureToHeight(vectors[i - 1][j].z));
drawer.glVertexV(vectors[i - 1][j]);
// Right down diagonally
if (j < vectors[i].length - 1) { // Skip if we are reached the end
gl.glTexCoord1d(mapTextureToHeight(vectors[i][j + 1].z));
drawer.glNormalV(normalTopRight);
drawer.glVertexV(vectors[i][j + 1]);
}
}
gl.glEnd();
}
if (showGrid)
gl.glPolygonMode( gl.GL_FRONT_AND_BACK, gl.GL_FILL );
if (drawNormals) {
for (Vector[] arrow : normals) {
if (yellowNormals)
Material.YELLOW.use(gl);
else
gl.glTexCoord1d(mapTextureToHeight(arrow[0].z));
drawer.drawArrow(arrow[0], arrow[1], 0.05);
}
}
texture.unbind(gl);
}
The most obvious reason for the stripes is the fact I draw the triangles per column, causing OpenGL to not be able to smoothen the shading on the polygons (GL_SMOOTH). Is there any way to fix this?
[Edit1] Copied from your comment by Spektre
I just finished calculating the average normals, I indeed have a smooth terrain now, but the lighting looks kind of dull (no depth)
Here is the new code that draws the terrain:
public void draw() {
if (showGrid)
gl.glPolygonMode( gl.GL_FRONT_AND_BACK, gl.GL_LINE);
texture.bind(gl);
Material.TERRAIN.use(gl);
for(int i=1;i<vectors.length;i++) {
gl.glBegin(gl.GL_TRIANGLE_STRIP);
for (int j = 0; j < vectors[i].length; j++) {
// Initialization vector
gl.glTexCoord1d(mapTextureToHeight(vectors[i][j].z));
drawer.glNormalV(normals.get(vectors[i][j]));
drawer.glVertexV(vectors[i][j]);
// Shift left
gl.glTexCoord1d(mapTextureToHeight(vectors[i - 1][j].z));
drawer.glNormalV(normals.get(vectors[i - 1][j]));
drawer.glVertexV(vectors[i - 1][j]);
}
gl.glEnd();
}
if (showGrid)
gl.glPolygonMode( gl.GL_FRONT_AND_BACK, gl.GL_FILL );
if (drawNormals)
drawFaceNormals();
texture.unbind(gl);
}
I cleaned it up, I am sure the normals are pointing the correct way using the drawnormals function and made sure OpenGL is seeing the top of the terrain as FRONT using (gl.GL_FRONT -> draws only above terrain, not below).
Here is the complete class: PasteBin
Thanks to #Spektre for helping me out.
After properly calculating the average normal of all surrounding faces on a vertex and using this normal for glNormal, the shading was correct.
Maybe my title doesn't fit very well but I will try to clearly explain.
In fact, I'm currently working on a little project using Libgdx. At the moment, the goal of this project is to be able to randomly display several circles on my screen.
I correctly displayed these circles on the screen but they are blinking.
#Override
public void render(float delta) {
renderer.begin(ShapeType.Filled);
if(!mapIsCreated)
{
Random rand = new Random();
int x, y;
for(int i=0;i<200;i++)
{
x = rand.nextInt(Gdx.graphics.getWidth());
y = rand.nextInt(Gdx.graphics.getHeight());
renderer.setColor(Color.DARK_GRAY);
renderer.circle(x, y, 5);
renderer.setColor(Color.GRAY);
renderer.circle(x, y, 3);
}
mapIsCreated = true;
}
renderer.end();
}
Are there any solutions to definitively fix them on the background without blinking/reloading effects ?
If more details are needed, please let me know.
You never seem to clear your screen.
You should call the following lines at the start of your render method:
// This is black, you can choose any color, technically one call is enough
Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
// This line clears the screen (more precisely the color buffer, there are others but this one should be fine)
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Now, since it looks like you only want to generate them randomly once create them once in your initialization method (like the create method) and save them in an array/Collection:
// Global field
Array<Vector2> circlePositions = new Array<>();
// initialization method
renderer = new ShapeRenderer();
Random rand = new RandomXS128();
for (int i = 0; i < 200; i++)
{
circlePositions.add(
new Vector2(
rand.nextInt(Gdx.graphics.getWidth()),
rand.nextInt(Gdx.graphics.getHeight())));
circlePositions.add(
new Vector2(
rand.nextInt(Gdx.graphics.getWidth()),
rand.nextInt(Gdx.graphics.getHeight())));
}
Then in your render method you can draw your circles like this:
Gdx.gl.glClearColor(0f, 0f, 0f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderer.begin(ShapeType.Filled);
for (int i = 0; i < circlePositions.size; i++)
{
Vector2 pos = circlePositions.get(i);
if (i % 2 == 0)
{
renderer.setColor(Color.DARK_GRAY);
renderer.circle(pos.x, pos.y, 5);
} else
{
renderer.setColor(Color.GRAY);
renderer.circle(pos.x, pos.y, 3);
}
}
renderer.end();
If you don't want to redraw everything at e.g. 60 fps, then take a look at non continues rendering.
Can someone tell me why my camera class isn't working correctly? I set the position vector to (0,0,-10) and the look at vector to (0,0,0) but when I draw something on (0,0,0) it isn't there. I'm very new to vector math and matrix stuff, so I'm betting it's LookThrough() where the problem is.
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.vector.Matrix3f;
import org.lwjgl.util.vector.Vector3f;
public class Camera {
//3d vector to store the camera's position in
Vector3f position = null;
Vector3f lookAt = null;
//the rotation around the Y axis of the camera
float yaw = 0;
//the rotation around the X axis of the camera
float pitch = 0;
//the rotation around the Z axis of the camera
float roll = 0;
public Camera(float x, float y, float z)
{
//instantiate position Vector3f to the x y z params.
position = new Vector3f(x, y, z);
lookAt = new Vector3f();
}
public void lookThrough()
{
Matrix3f m = new Matrix3f();
Vector3f out = new Vector3f();
Vector3f.sub(position, lookAt, out);
out.normalise();
//set forward vector
m.m00 = out.x;
m.m01 = out.y;
m.m02 = out.z;
//set right vector
m.m10 = 1;
m.m11 = 0;
m.m12 = 0;
//set up vector
m.m20 = 0;
m.m21 = 1;
m.m22 = 0;
yaw = (float) -(Math.tan(m.m10/m.m00));
pitch = (float) -(Math.tan((-m.m20)/(Math.sqrt(Math.pow(m.m21, 2) + Math.pow(m.m22, 2)))));
roll = (float) -(Math.tan(m.m21/m.m22));
//roatate the pitch around the X axis
GL11.glRotatef(pitch, 1.0f, 0.0f, 0.0f);
//roatate the yaw around the Y axis
GL11.glRotatef(yaw, 0.0f, 1.0f, 0.0f);
//roatate the yaw around the Y axis
GL11.glRotatef(roll, 0.0f, 0.0f, 1.0f);
//translate to the position vector's location
GL11.glTranslatef(position.x, position.y, position.z);
}
}
There are a couple of things about your class that I would highlight:
1) You are fixing your 'right' and 'up' vectors, leaving only one degree of rotational freedom. As the camera re-orients in 3D space these will need to change. As it stands, your calculation for pitch always evaluates to 0, while your calculation to roll always evaluates to tan(1/0).
2) Though I'm not familiar with Java, you appear to be using the calculation (position - lookAt) to derive your forward vector. Ought it not be the reverse? The forward vector points away from the viewer's position.
3) Again - not familiar with java - but calling pow() to do a single multiplication is likely overkill.
1 & 2 could be the cause of your woes. Ultimately I would suggest taking a look at gluLookAt - assuming the GLU library is available in Java. If it is not, then look at the source code for gluLookAt (one variant is available here).