Orbit controls make scene disappear after a while - java

I am using JOGL to build a point cloud viewer and I have implemented my own orbit controls. It works very well for a while, but at some point (I think after dragging the mouse left and right very quickly) the scene completely disappears. Here is my code:
public void mouseDragged(MouseEvent e) {
if (oldX < 0.0005 && oldY < 0.0005) {
// when the mouse drag starts initially
oldX = e.getX();
oldY = e.getY();
} else {
float differenceX = e.getX() - oldX;
float differenceY = e.getY() - oldY;
oldX = e.getX();
oldY = e.getY();
float speedX = differenceX / 2;
float speedY = differenceY / 2;
Vector3f velocityX = new Vector3f();
Vector3f velocityY = new Vector3f();
Vector3f oldTarget = camera.getTarget();
Vector3f cameraRight = new Vector3f();
// getting right vector of the camera in the world space
camera.getDirection().cross(camera.getWorldUp(), cameraRight);
/* moving the camera first along its right vector
* then setting its target to what it was originally
* looking at */
cameraRight.mul(-speedX, velocityX);
camera.translate(velocityX);
camera.setTarget(oldTarget);
/* moving the camera second along its up vector
* then setting its target to what it was originally
* looking at */
camera.getUp().mul(-speedY, velocityY);
camera.translate(velocityY);
camera.setTarget(oldTarget);
}
}
I first thought that it would be because when the camera direction vector and the world up vector are identical, the camera right vector (cross product between the two) would be zero, but that would only mean for the controls to lose one dimension of movement; this should not cause the entire scene to go away.

The idea I originally came up with distanced the camera from its point of focus with each rotation (at some point beyod the far plane). The solution to this problem is to implement the orbit controls using the polar coordinate system. As such, in your mouseDragged() method:
if (oldX < 0.0005 && oldY < 0.0005) {
oldX = e.getX();
oldY = e.getY();
} else {
float differenceX = e.getX() - oldX;
float differenceY = e.getY() - oldY;
oldX = e.getX();
oldY = e.getY();
// getting the current position of the camera in the spherical coordinate system
Vector3f sphericalCoords = MathUtils.toSphericalCoords(camera.getPosition());
float speedY = (float)Math.toRadians(differenceY / 4.0f);
float speedX = (float)Math.toRadians(differenceX / 4.0f);
// adding speedY to the theta angle and speedX to the phi angle
sphericalCoords.add(new Vector3f(0, speedY, speedX));
// making sure the angles are not outside the [0, 2 * PI] interval
polarCoords.y = MathUtils.wrapTo2Pi(sphericalCoords.y);
polarCoords.z = MathUtils.wrapTo2Pi(sphericalCoords.z);
// updating the position of the camera
camera.setPosition(MathUtils.toCartesianCoords(sphericalCoords));
}

Related

Move a point toward the mouse

(I'm using processing for this but it is not necessarily relevant.)
I'm looking for an algorithm that would take the point A and the point B (B being the mouse cursor position) and use them so that every frame the point A moves a little bit towards B (from -1px to 1px left/right up/down)
I tried x1 += cos(atan((mouseY-y1)/(mouseX-x1))) and the same with sin for y1, but I doesn't seem to work.
If someone has an idea I would appreciate it.
I'm not looking for a built-in function that would do the job, I'd like to understand the math behind it.
Thank you for your time.
It is important that the point coordinates are floating point values:
float x = 0.0, y= 0.0;
For the computation of the movement of the point, I recommend to use PVector.
Setup 2 vectors, for the point and the mouse position:
PVector Pt = new PVector(x, y);
PVector Pm = new PVector(mouseX, mouseY);
Calculate the Unit vector from Pt to Pm:
PVector D = PVector.sub(Pm, Pt);
D.normalize();
Calculate the new point by newPt = Pt + D * min(speed, dist), but ensure that the point moves not further than the Euclidean distance to the mouse:
float speed = 3;
float movelen = min(PVector.dist(Pt, Pm), speed);
PVector newPt = PVector.add(Pt, D.mult(movelen));
The same can be achieved by arithmetic operations
float dx = mouseX - x;
float dy = mouseY - y;
float dist = sqrt(dx*dx + dy*dy);
if (dist > 0) {
float movelen = min(dist, speed);
x += dx/dist * movelen;
y += dy/dist * movelen;
}
(dx,dy) is the vector from the point to the mouse and dist ist the Euclidean distance between the 2 points. A Unit vector can be calculated by dividing a vector by its magnitude, so (dx/dist, dy/dist) is the unit direction vector.
Finally (dx/dist * movelen, dx/dist * movelen) is the same as D * movelen.
See the example:
(the code works for any speed, even below 1.0)
float x = 0.0, y= 0.0;
void setup() {
size(300, 300);
x = (float)random(width);
y = (float)random(height);
}
void draw() {
float speed = 3;
/*
//setup points
PVector Pt = new PVector(x, y);
PVector Pm = new PVector(mouseX, mouseY);
// calcualte normalized direction
PVector D = PVector.sub(Pm, Pt);
D.normalize();
// calcualte new point
float movelen = min(PVector.dist(Pt, Pm), speed);
PVector newPt = PVector.add(Pt, D.mult(movelen));
x = newPt.x;
y = newPt.y;
*/
float dx = mouseX - x;
float dy = mouseY - y;
float dist = sqrt(dx*dx + dy*dy);
if (dist > 0) {
float movelen = min(dist, speed);
x += dx/dist * movelen;
y += dy/dist * movelen;
}
background(196);
stroke(0);
fill(255, 0, 0);
ellipse((int)x, (int)y, 10, 10);
fill(0, 255, 0);
ellipse(mouseX, mouseY, 10, 10);
}

Libgdx Player rotation messing up

I'm trying to program a player that rotates towards the mouse and travels towards the mouse at a certain speed. I am using an orthographic camera, however as soon as I set the camera's position to equal the players position, the player rotation stops working and goes all over the place. I believe it might have something to do with the mouse coordinates using the screen and not the world x and y. I have tried unprojecting Gdx.inout.getY/X to no prevail. Any help is much appreciated.
I am using this code to follow player:
cam.position.x = player.getX();
cam.position.y = player.getY();
cam.update();
And this code for rotation:
float mouseX = Gdx.input.getX();
float mouseY = (480 - Gdx.input.getY());
float originX = getWidth() / 2 + position.x;
float originY = getHeight() / 2 + position.y;
double angle = Math.atan2(mouseY - originY, mouseX - originX) * (180/Math.PI) + 90;
if (angle < 0)
angle += 360;
rotation = (float) angle;
direction.x = mouseX - position.x;
direction.y = mouseY - position.y;
double hyp = Math.sqrt(direction.x * direction.x + direction.y * direction.y);
direction.x /= hyp;
direction.y /= hyp;
position.x += direction.x * 2;
position.y += direction.y * 2;
Have you tried projecting (or unprojecting) the points?
ViewPort viewPort = new ... // which ever ViewPort you're using
Vector2 worldPoint = new Vector2(x, y);
Vector2 projected = viewPort.project(worldPoint);
or
Vector2 screenPoint = new Vector2(x, y);
Vector2 unprojected = viewPort.unproject(screenPoint);

How to create the illusion of particles been left behind in libgdx

I am making an endless runner game were the camera is static and the environment is moving from top to bottom, the player is a rocket facing upwards that can only move left or right. When the player collides with an obstacle it spawns particles to show an explosion. What i want is to show the illusion of the particles been left behind as the camera is moving up. But since my camera is static i have to move them backwards myself to give an illusion of the camera going up how do i go about doing that?
Here is my code:
public Particle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
rotDirection = MathUtils.random.nextBoolean() ? -1 : 1;
dx = MathUtils.cos(MathUtils.random(MathUtils.PI2));
dy = MathUtils.sin(MathUtils.random(MathUtils.PI2));
xSpeed = MathUtils.random(MIN_SPEED, MAX_SPEED);
ySpeed = MathUtils.random(MIN_SPEED, MAX_SPEED);
rotation = MathUtils.random(360);
rotationSpeed = MathUtils.random(MIN_ROT_SPEED, MAX_ROT_SPEED);
}
public void update(float delta){
x += dx * xSpeed * delta;
y += dy * ySpeed * delta;
rotation += rotDirection * rotationSpeed * delta;
}
You are using randoms to set dy and ySpeed.
Then you change the y value using these 2 random values and deltaTime.
If you want to move the particle in a specific direction you cannot use random values to move it.
Try having a float yMoveSpeed and add it to y.
public void update(float delta){
x += dx * xSpeed * delta;
y += dy * ySpeed * delta;
rotation += rotDirection * rotationSpeed * delta;
y += yMoveSpeed * delta;
}
That should at least make it move in a direction.
Another solution could be to use the particle system and editor bundled with libgdx. (in gdx-tools)
Game From Scratch tutorial

Rendering 3-d lines in Java?

Ok, I have a little problem: I'm trying to code an engine capable of rendering 3d lines onto a 2d plane, but I'm having some trouble with it.
I have a point3d class, which takes x y and z coords, a line3d class, which takes two point3d endpoints, and I have a world object containing an arraylist of line3d's. I also have point2d and line2d, which are just like their 3d counterparts, except that they lack a z coordinate.
Here's the render method:
public void render(){
for(Line3d line : world.lines){ //for every 3d line in the world
panel.l3d(line, world.main); //render that line
}
panel.repaint(); //repaint the graphic
}
Which calls upon the l3d method:
public void l3d(Line3d line, Camera view){
Point2d start = p3Top2(line.start, view), end = p3Top2(line.end, view); //convert 3d points to 2d points
if(start==null || end==null)return; //if either is null, return
lineAbs(new Line2d(start, end)); //draw the line
}
Which calls upon p3Top2:
public Point2d p3Top2(Point3d point, Camera view){ //convert 3d point to 2d point on screen
int relativeZed = point.z - view.z; //difference in z values between camera and point
if(relativeZed <= 0)return null; //if it's behind the camera, return
int sx, sy, ex, ey, tx, ty; //begin declaring rectangle formed from extending camera angle to the z coord of the point(angle of 1 = 90 degrees)
sx = (int) (view.x - (width / 2) - relativeZed * (width * view.angle)); //starting x of rectangle
ex = (int) (view.x + (width / 2) + relativeZed * (width * view.angle)); //ending x
sy = (int) (view.y - (height / 2) - relativeZed * (height * view.angle)); //starting y
ey = (int) (view.y + (height / 2) + relativeZed * (height * view.angle)); //ending y
tx = point.x - sx; //difference between point's x and start of rectangle
ty = point.y - sy; //same for y
float px = (float)tx / (float)(ex - sx), py = (float)ty / (float)(ey - sy); //px and py are the ratios of the point's x/y coords compared to the x/y of the rectangle their in
return new Point2d((int)(px * width), (int)(py * height)); //multiply it by the width and height to get positions on screen
}
And also on lineAbs:
public void lineAbs(Line2d line){
Point2d start = line.start;
Point2d end = line.end;
if(start.x>end.x){
start = line.end;
end = line.start;
}
int y = start.y; //starting y point
int white = 0xffffff;
for(int x = start.x; x<end.x; x++){ //for each x in the line
if(x < 0 || y < 0 || x > canvas.getWidth() || y > canvas.getHeight())continue; //if the point is outside of the screen, continue
y += line.getSlope().slope; //increment y by the slope
canvas.setRGB(x, y, white); //draw the point to the canvas
}
}
'canvas' is a BufferedImage being drawn to the screen. With an arbitrary camera and angle of 1, as well as a few arbitrary lines thrown in, I do see each line, but they don't appear to be rendered properly. For example, when I have three point3d's as vertices, and three lines, each with a different combination of two of the points, the lines don't appear to meet at all, although each one is visible.
I suspect the issue is in my p3Top2, but I'm not sure where, can you tell?

Shoot to the mouse direction

The problem:
I've got this "Shot" class. In the code, the target variables are the mouseX and mouseY.
So when i click the mouse button, my player class will create a new shot object.
But the shooting is inaccurate.
How can i calculate the correct dx and dy?
If i add the dx and dy to the "bullet's" x and y, the bullet will move to the mouse's direction.This is what i want. The mouse position is stored in targetX and targetY, when the object is created. This is the point what the oval wants to reach.
Links:
The game (finished)
The code (from Shot.java):
public class Shot extends Entity {
private float targetX, targetY;
public Shot(World world, float x, float y, int width, int height, Color color, float targetX, float targetY) {
super(world, x, y, width, height, color);
this.targetX = targetX;
this.targetY = targetY;
}
#Override
public void render(GameContainer gc, Graphics g, Camera camera) {
g.setColor(color);
g.fillOval(x - camera.getX(), y - camera.getY(), width, height);
}
#Override
public void update(GameContainer gc, int delta) {
float dx = targetX - x;
float dy = targetY - y;
x += dx * delta * .001f;
y += dy * delta * .001f;
}
}
I tried this, but still not work:
#Override
public void update(GameContainer gc, int delta) {
float length = (float) Math.sqrt((targetX - x) * (targetX - x) + (targetY - y) * (targetY - y));
double dx = (targetX - x) / length * delta;
double dy = (targetY - y) / length * delta;
x += dx;
y += dy;
}
I did it! Here is my solution:
The problem was that, the target was the window's mouse position, and not the world's mouse position.
This is how i calculated the world's mouse positions:
float mouseWorldX = x + (mouseX - screen_width / 2); // x = player's x position
float mouseWorldY = y + (mouseY - screen_height / 2); // y = player's y position
This is code from my game at the moment is used to move a unit to the mouse when the right mouse button is pressed:
length = Math.sqrt((target_X - player_X)*(target_X - player_X) + (target_Y - player_Y)*(target_Y - player_Y)); //calculates the distance between the two points
speed_X = (target_X - player_X) /length * player_Speed;
speed_Y = (target_Y - player_Y) /length * player_Speed;
This will move an object to the target in a line at a set speed.
Edit: this is the actual code right from my game
if(input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON))
{
length = (float) Math.sqrt((player_waypoint_X - player_X)*(player_waypoint_X - player_X) + (player_waypoint_Y - player_Y)*(player_waypoint_Y - player_Y));
velocityX = (float) (player_waypoint_X - player_X) /length * (float) PlayerStats.player.db_player_Speed;
velocityY = (float) (player_waypoint_Y - player_Y) /length * (float) PlayerStats.player.db_player_Speed;
player_waypoint_X = input.getMouseX() - 2;
player_waypoint_Y = input.getMouseY() - 2;
}
For testing purposes the velocity's are defined in the init method along with length. Every time the right mouse is pressed the waypoints's X and Y are changed to the mouse location.
I learned this from this question
velocity calculation algorithm.
in order to make the bullets not all change direction every shot, create an array list so that each bullet fired has its own x and y velocity

Categories

Resources