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();


        }

}

Yes I did, no answer there. The problem is more math related than lwjgl. I some how should get my 2d screen coordinates to 3d world coordinate system. I have aiming cross center of the screen and I want to use that as targeting. Something like this.

package net.viped.vengine;

import static org.lwjgl.opengl.GL11.*;

public class Ammo {

    Vector3f origin;
    Vector3f direction;

    public Ammo(Vector3f origin, Vector3f direction) {
        this.origin = origin;
        this.direction = direction;
    }

    public void render() {
        glBegin(GL_LINES);
            glColor3f(1, 0, 0);
            glVertex3f(origin.x, origin.y, origin.z);
            glColor3f(0, 1, 0);
            glVertex3f(direction.x, direction.y, direction.z);
        glEnd();
    }
}




    public void renderAmmo() {
        Ammo ammo = new Ammo((new Vector3f(direction.x, direction.y, direction.z)),new Vector3f(cam.getX(), cam.getY(), cam.getZ()));
        ammos.add(ammo);
        for (int i = 0; i < ammos.size(); i++) {
            ammo.render();
        }
    }

Problem is that I can't manage to find right coordinates.

Edited 4 Years Ago by Viped

Anything from plain theory to ready code would be appreciated. Thanks!

Not ready code but have you tried looking at the source code of an existing 3D engine like Jmonkey? Also, you will have more luck with your question in a game engine oriented message board.

Edited 4 Years Ago by ~s.o.s~

Yes I tried that approach too but it didnt help me alot. This is really new to me. Both 3d and lwjgl. I posted this question also to gamedev.net and devmaster.net but still no answer.

Well, I can't help with this stuff but offer some advice. With a statement like:

Actually I don't even know where to start with that

I won't be surprised if you don't get replies even in Game oriented forums. As someone who has been on the "question answering" side of things for years now (newsgroups, forums etc.), the last thing a "helper" would want to see is a question in which the asker isn't clear about what he needs.

You say you are new with both 3D and LWJGL. I think the first logical step would be to get to know these things to a level at which you are comfortable enough to actually find out what's going wrong but don't know the solution to get around it. Since jMonkeyEngine is all Java, I would advise you to take out the source and "debug" through it when running the sample examples which come with it (either in Eclipse, Netbeans etc.).

The next problem is how to acquaint yourself with enough 3D knowledge to create your own engine. Search around google for queries like "starting 3d game development" etc. and you will definitely come across threads posted by others in the same situation as you. Also, are you aware of what kind of "features" a game engine provides? I would first recommend using a 'simple' engine, getting a feel of how the engine lets you program your own logic and then set out to write one. After all, you can't conquer something you don't know of!

Hope that gave you some direction; if it didn't, pardon the ramblings of an old man. :)

This article has been dead for over six months. Start a new discussion instead.