Hi, I am trying to make my own 3d engine and got problem with picking / shooting. Actually I dont even know where to start with that. I have tried find tutos over internet but I did not find any thats useful. Maybe U guys can help me? Anything from plain theory to ready code would be appreciated. Thanks!
Core.java
package net.viped.vengine;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.*;
import java.awt.image.CropImageFilter;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Cursor;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
public class Core {
public static final int WIDTH = 800;
public static final int HEIGHT = 600;
private Camera cam;
World world = new World();
Cursor emptyCursor;
Gun gun = new Gun();
boolean shooting = false;
long shootTime;
public Core() {
try {
Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
Display.setTitle("vEngine 0.12");
Display.setVSyncEnabled(true);
Display.setResizable(false);
Display.create();
init();
world.createTestWorld();
long lastTime = System.nanoTime();
int frames = 0;
while (!Display.isCloseRequested()) {
tick();
render();
frames++;
if (System.nanoTime() - lastTime > 1000000000) {
System.out.println(frames + "FPS");
frames = 0;
lastTime = System.nanoTime();
}
Display.sync(60);
Display.update();
}
Display.destroy();
System.exit(0);
} catch (Exception e) {
e.printStackTrace();
Display.destroy();
System.exit(0);
}
}
public void init() {
Mouse.setGrabbed(true);
cam = new Camera(70, (float) (WIDTH / HEIGHT), 0.3f, 1000);
//Siirtää kameran alkupositiota
cam.move(0.0f, 1);
cam.setY(1.0f);
}
public void tick() {
input();
}
public void input() {
if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
cam.move(0.1f, 1);
}
if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
cam.move(-0.1f, 1);
}
if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
cam.move(0.1f, 0);
}
if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
cam.move(-0.1f, 0);
}
if (Keyboard.isKeyDown(Keyboard.KEY_SPACE) && collidingDown() && !cam.flymode) {
cam.jumping = true;
}
if (Keyboard.isKeyDown(Keyboard.KEY_SPACE) && cam.flymode) {
cam.fly(-0.1f);
}
if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && cam.flymode) {
cam.fly(0.1f);
}
if (Keyboard.isKeyDown(Keyboard.KEY_F)) {
cam.flymode = !cam.flymode;
}
if (cam.jumping) {
cam.jump();
}
if (Mouse.isButtonDown(0)) {
renderAmmo();// shootTime = System.currentTimeMillis();
} else {
// shooting = false;
}
cam.rotateY(Mouse.getDX());
cam.rotateX(-Mouse.getDY());
}
public boolean collidingDown() {
for (int i = 0; i < world.walls.size(); i++) {
if ((-cam.getZ() > world.walls.get(i).z && (-cam.getZ() < world.walls.get(i).z + world.walls.get(i).length)) && (-cam.getX() > world.walls.get(i).x && -cam.getX() < world.walls.get(i).x + world.walls.get(i).width) && (-cam.getY() > world.walls.get(i).y - 0.5f)) {// && -cam.getY() < world.walls.get(i).y +2.5f)) {
return true;
}
}
return false;
}
// public boolean collidingDown() {
// for (int i = 0; i < world.walls.size(); i++) {
// if ((-cam.getZ() > world.walls.get(i).z && (-cam.getZ() < world.walls.get(i).z + world.walls.get(i).length)) && (-cam.getX() > world.walls.get(i).x && -cam.getX() < world.walls.get(i).x + world.walls.get(i).width) && (cam.getY() < -world.walls.get(i).y + 0.5f)) {
// return true;
// }
// }
// return false;
// }
public void renderCursor() {
glLoadIdentity();
glPushMatrix();
glLineWidth(1);
glBegin(GL_LINES);
glColor3f(0, 1, 0);
glVertex2f(WIDTH / 2 - 15, HEIGHT / 2);
glVertex2f(WIDTH / 2 + 15, HEIGHT / 2);
glVertex2f(WIDTH / 2, HEIGHT / 2 - 15);
glVertex2f(WIDTH / 2, HEIGHT / 2 + 15);
glEnd();
glPopMatrix();
}
public void render() {
cam.initProjection();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
cam.useView();
glPushMatrix();
glTranslatef(0, -2, 0);
if (!collidingDown() && !cam.jumping && !cam.flymode) {
cam.implementGravity();
}
world.renderTestWorld();
// if (System.currentTimeMillis() - shootTime < 2000 && !shooting) {
// renderAmmo(cam.getRy(), cam.getY(), cam.getZ());
// }
glPopMatrix();
glPushMatrix();
glPopMatrix();
// glPushMatrix();
//
// System.out.println("x: " + cam.getX() + " , y: " + cam.getY() + " , z: " + cam.getZ());
//
// Vector3D from = new Vector3D(cam.getX(), -cam.getY(), -cam.getZ());
// glTranslatef(1, -10, -from.z);
// glColor3f(1f, 0.5f, 0.5f);
// glBegin(GL_QUADS);
// glVertex3f(from.x - 2, from.y, -from.z -2);
// glVertex3f(from.x + 2, from.y, -from.z -2);
// glVertex3f(from.x + 2, from.y, -from.z +2);
// glVertex3f(from.x - 2, from.y, -from.z +2);
// glEnd();
//
// glPopMatrix();
cam.init2D();
renderCursor();
gun.renderGun();
cam.initProjection();
}
public void renderAmmo(){//float x, float y, float z) {
}
public static void main(String[] args) {
new Core();
}
private class Vector3D {
float x, y, z;
public Vector3D(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
}
}
Camera.java
package net.viped.vengine;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.*;
public class Camera {
private float x, y, z;
private float rx, ry, rz;
private float fov;
private float aspect;
private float near;
private float far;
boolean flymode = false;
float speed = 0.05f;
float gravity = 0.5f;
float ogJumpGravity = 1.0f;
float jumpGravity = ogJumpGravity;
boolean jumping;
public Camera(float fov, float aspect, float near, float far) {
x = 0;
y = 0;
z = 0;
rx = 0;
ry = 0;
rz = 0;
this.fov = fov;
this.aspect = aspect;
this.near = near;
this.far = far;
initProjection();
}
public void initProjection() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fov, aspect, near, far);
// glOrtho(0, Core.WIDTH, Core.HEIGHT, 0, 1, -1000);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
}
public void init2D() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, Core.WIDTH, Core.HEIGHT, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
}
public void useView() {
// gluLookAt(rx, ry, rz, x, y, z, 0, 1, 0);
glRotatef(rx, 1, 0, 0);
glRotatef(ry, 0, 1, 0);
glRotatef(rz, 0, 0, 1);
glTranslatef(x, y, z);
}
public void move(float amount, int dir) {
z += amount * Math.sin(Math.toRadians(ry + 90 * dir));
x += amount* Math.cos(Math.toRadians(ry + 90 * dir));
}
public void fly(float amount) {
if (flymode) {
y += amount;
}
}
public void jump() {
if (jumping) {
y -= jumpGravity;
jumpGravity -= speed;
if (y > 0) {
y = 0;
jumpGravity = ogJumpGravity;
jumping = false;
}
}
}
public void implementGravity() {
y += gravity;
}
public void rotateY(float amount) {
ry += amount;
}
public void rotateX(float amount) {
if (rx + amount >= -90 && rx + amount <= 90 ) {
rx += amount;
}
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
public float getZ() {
return z;
}
public void setZ(float z) {
this.z = z;
}
public float getRx() {
return rx;
}
public void setRx(float rx) {
this.rx = rx;
}
public float getRy() {
return ry;
}
public void setRy(float ry) {
this.ry = ry;
}
public float getRz() {
return rz;
}
public void setRz(float rz) {
this.rz = rz;
}
public boolean isFlymode() {
return flymode;
}
public void setFlymode(boolean flymode) {
this.flymode = flymode;
}
public float getSpeed() {
return speed;
}
public void setSpeed(float speed) {
this.speed = speed;
}
}
World.java
package net.viped.vengine;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.gluPerspective;
import java.util.ArrayList;
import java.util.Random;
public class World {
public World() {
}
int stars = 10000;
Star[] starsA = new Star[stars];
int displayListHandle;
public ArrayList<pathToStars> walls = new ArrayList<World.pathToStars>();
public pathToStars path;
public pathToStars path2;
public pathToStars path3;
public void createTestWorld() {
for (int i = 0; i < stars; i++) {
Random rand = new Random();
starsA[i] = new Star((rand.nextFloat() - 0.5f) * 100f, (rand.nextFloat() - 0.5f) * 100f, rand.nextInt(200) - 100);
}
path = new pathToStars(-1.0f, -1.0f, -9.0f, 2.0f, 30f);
path2 = new pathToStars(3.0f, -1.0f, 1.0f, 2.0f, 30f);
path3 = new pathToStars(-4.0f, -1.0f, 1.0f, 2.0f, 30f);
walls.add(path);
walls.add(path2);
walls.add(path3);
for (int i = 0; i < walls.size(); i++) {
glBegin(GL_QUADS);
glVertex3f(walls.get(i).x, walls.get(i).y, walls.get(i).z);
glVertex3f(walls.get(i).x + walls.get(i).width, walls.get(i).y, walls.get(i).z);
glVertex3f(walls.get(i).x + walls.get(i).width, walls.get(i).y, walls.get(i).z + walls.get(i).length);
glVertex3f(walls.get(i).x, walls.get(i).y, walls.get(i).z + walls.get(i).length);
glEnd();
}
}
public void renderTestWorld() {
glColor3d(1, 1, 1);
for (Star s : starsA) {
Random rand = new Random();
glBegin(GL_POINTS);
{
glVertex3f(s.x, s.y, s.z);
}
glEnd();
}
for (int i = 0; i < walls.size(); i++) {
glBegin(GL_QUADS);
glVertex3f(walls.get(i).x, walls.get(i).y, walls.get(i).z);
glVertex3f(walls.get(i).x + walls.get(i).width, walls.get(i).y, walls.get(i).z);
glVertex3f(walls.get(i).x + walls.get(i).width, walls.get(i).y, walls.get(i).z + walls.get(i).length);
glVertex3f(walls.get(i).x, walls.get(i).y, walls.get(i).z + walls.get(i).length);
glEnd();
}
}
private class Star {
float x, y, z;
public Star(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
}
class pathToStars {
float x, y, z;
float width, length;
public pathToStars(float x, float y, float z, float width, float length) {
super();
this.x = x;
this.y = y;
this.z = z;
this.width = width;
this.length = length;
}
}
}
Gun.java
package net.viped.vengine;
import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.Sys;
public class Gun {
public void renderGun() {
glPushMatrix();
glLineWidth(40);
glColor3f(1, 0, 0);
glBegin(GL_LINES);
glVertex2f(Core.WIDTH-80, Core.HEIGHT+20);
glVertex2f(Core.WIDTH-Core.WIDTH/4-50, Core.HEIGHT-Core.HEIGHT/4);
glEnd();
glPopMatrix();
}
}