Right now, whenever my player turns, the camera turns with it. This was intentional, but I changed my mind on that feature when I inputted other camera controls, and right now, I can't seem to disable that functionality without breaking the whole camera system. I'm working with OpenGL and LWJGL, but I don't think knowledge in those will be too necessary for this. I basically want the camera not to turn as the player does. Thank you for your time, and have a
Here is the camera class:
package entities;
import org.lwjgl.input.Keyboard;
import org.lwjgl.util.vector.Vector3f;
public class Camera {
private float distanceFromPlayer = 50;
private float angleAroundPlayer = 0;
private Vector3f position = new Vector3f(10,20,10);
private float pitch = 45;
private float yaw;
private float roll;
private Player player;
public Camera(Player player){
this.player = player;
}
public void move(){
if(Keyboard.isKeyDown(Keyboard.KEY_LEFT)){
angleAroundPlayer -= 1;
}
if(Keyboard.isKeyDown(Keyboard.KEY_RIGHT)){
angleAroundPlayer += 1;
}
if(Keyboard.isKeyDown(Keyboard.KEY_UP)){
pitch += 1;
}
if(Keyboard.isKeyDown(Keyboard.KEY_DOWN)){
pitch -= 1;
}
float horizontalDistance = calculateHorizontalDistance();
float verticalDistance = calculateVerticalDistance();
calculateCameraPosition(horizontalDistance,verticalDistance);
this.yaw = 180 - (player.getRotY() + angleAroundPlayer);
}
public Vector3f getPosition() {
return position;
}
public float getPitch() {
return pitch;
}
public float getYaw() {
return yaw;
}
public float getRoll() {
return roll;
}
private float calculateHorizontalDistance(){
return (float)(distanceFromPlayer * Math.cos(Math.toRadians(pitch)));
}
private float calculateVerticalDistance(){
return (float)(distanceFromPlayer * Math.sin(Math.toRadians(pitch)));
}
private void calculateCameraPosition(float horizontalDistance, float verticalDistance){
float theta = player.getRotY() + angleAroundPlayer;
float offsetX = (float)(horizontalDistance * Math.sin(Math.toRadians(theta)));
float offsetZ = (float)(horizontalDistance * Math.cos(Math.toRadians(theta)));
position.x = player.getPosition().x - offsetX;
position.z = player.getPosition().z - offsetZ;
position.y = player.getPosition().y + verticalDistance;
}
}
And here is the player class:
package entities;
import models.TexturedModel;
import org.lwjgl.input.Keyboard;
import org.lwjgl.util.vector.Vector3f;
import renderEngine.DisplayManager;
public class Player extends Entity{
private static final float RUN_SPEED = 20;
private static final float TURN_SPEED = 180;
private static final float GRAVITY = -50;
private static final float JUMP_POWER = 40;
private static final float TERRAIN_HEIGHT = 0.5f;
private float currentSpeed = 0;
private float currentTurnSpeed = 0;
private float upwardsSpeed = 0;
private boolean isInAir = false;
public Player(TexturedModel model, Vector3f position, float rotX, float rotY, float rotZ, float scale) {
super(model, position, rotX, rotY, rotZ, scale);
}
public void move(){
checkInputs();super.increaseRotation(0,currentTurnSpeed * DisplayManager.getFrameTimeSeconds(),0);
float distance = currentSpeed * DisplayManager.getFrameTimeSeconds();
float dx = (float) (distance * Math.sin(Math.toRadians(super.getRotY())));
float dz = (float) (distance * Math.cos(Math.toRadians(super.getRotY())));
super.increasePosition(dx,0,dz);
upwardsSpeed += GRAVITY * DisplayManager.getFrameTimeSeconds();
super.increasePosition(0,upwardsSpeed * DisplayManager.getFrameTimeSeconds(),0);
if(super.getPosition().y < TERRAIN_HEIGHT){
upwardsSpeed =0;
isInAir = false;
super.getPosition().y = TERRAIN_HEIGHT;
}
}
private void jump(){
if(!isInAir){
this.upwardsSpeed = JUMP_POWER;
isInAir = true;
}
}
private void checkInputs(){
if(Keyboard.isKeyDown(Keyboard.KEY_W)){
this.currentSpeed = RUN_SPEED;
}
else if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
this.currentSpeed = -RUN_SPEED;
}
else{
this.currentSpeed = 0;
}
if(Keyboard.isKeyDown(Keyboard.KEY_D)){
this.currentTurnSpeed = -TURN_SPEED;
}
else if(Keyboard.isKeyDown(Keyboard.KEY_A)){
this.currentTurnSpeed = TURN_SPEED;
}
else{
this.currentTurnSpeed = 0;
}
if(Keyboard.isKeyDown(Keyboard.KEY_SPACE)){
jump();
}
}
}
And if needed, here is the Entity Class:
package entities;
import models.TexturedModel;
import org.lwjgl.util.vector.Vector3f;
public class Entity {
private TexturedModel model;
private Vector3f position;
private float rotX,rotY,rotZ;
private float scale;
public Entity(TexturedModel model, Vector3f position, float rotX, float rotY, float rotZ,float scale){
this.model = model;
this.position = position;
this.rotX = rotX;
this.rotY = rotY;
this.rotZ = rotZ;
this.scale = scale;
}
public void increasePosition(float dx, float dy, float dz){
this.position.x += dx;
this.position.y += dy;
this.position.z += dz;
}
public void increaseRotation(float dx, float dy, float dz){
this.rotX += dx;
this.rotY += dy;
this.rotZ += dz;
}
public TexturedModel getModel() {
return model;
}
public Vector3f getPosition() {
return position;
}
public float getRotX() {
return rotX;
}
public float getRotY() {
return rotY;
}
public float getRotZ() {
return rotZ;
}
public float getScale() {
return scale;
}
public void setModel(TexturedModel model) {
this.model = model;
}
public void setPosition(Vector3f position) {
this.position = position;
}
public void setRotX(float rotX) {
this.rotX = rotX;
}
public void setRotY(float rotY) {
this.rotY = rotY;
}
public void setRotZ(float rotZ) {
this.rotZ = rotZ;
}
public void setScale(float scale) {
this.scale = scale;
}
}
Related
How can I utilize my lerp function inside the vector3f class? Currently the lerp function reads like so:
public Vector3f lerp(Vector3f other, float alpha) {
return this.scale(1f - alpha).add(other.scale(alpha));
}
I have position and velocity vectors which use the add function as it updates. Now I want some smooth movement, but, I'm unsure how you would correctly use lerp. I've watched and read a few tutorials but none of them seem to address this kind of functionality. Any help would be much appreciated.
UPDATE:
So I've been watching this video here he has a series of videos on lerp with a very good diagram demonstration, which gave me a clue as to how linear interpolation works, so I decided to give it another shot. I wrote a new Vector2f method like so.
public Vector2f lerpT(Vector2f currentPos, Vector2f newPos, float alpha)
{
return currentPos.scale(1f - alpha).add(newPos.scale(alpha));
//return Vector3f point1 + alpha * (point2 - point1);
}
And my main class is like so:
public class Main {
public static void main(String[] args) throws IOException {
init();
}
public static void init() {
Vector2f currentPosition = new Vector2f(0.3f,0.7f);
Vector2f newPosition = new Vector2f(1.3f,0.8f);
Vector2f lerpPos = new Vector2f().lerpT(currentPosition, newPosition, 0f);
System.out.println("Testing LERP: " + "5/01/2018" + "\n");
System.out.println(lerpPos.x);
System.out.println(lerpPos.y);
}
This is what gets printed out into the console.
X: 0.79999995
Y: 0.75
I found some graph paper and decided to map it which was useful. I calculated the formula with a calculator and I get the same values in the x and y's lerpPos vector that is calculated in the code. I also changed it to Vector2f to make it simpler. And instead of LWJGL I decided to make a simple console program in java. While I understand it a bit more, I'm unsure how I'm supposed to use a velocity vector with the lerp function so I can give something some acceleration(?). I see how the alpha in the formula is important, but I'm unsure how to utilize it. If anything, I'd like to tryout some easing in and easing out, but the witchcraft needed seems a little bit over my head just at this moment. Oh well, I'll keep trying.
I'm going to post my completed code to my github, I'll post a link here when I get it up and running .Again, any help would be much appreciated
UPDATE:
public class Player {
private TexturedModel model;
public Vector3f position;
public Vector3f velocity;
public Vector3f acceleration;
public static Vector3f direction;
public static float maxVelocity = 0.5f;
private float rotX, rotY, rotZ;
private float scaleX, scaleY, scaleZ;
private float maxHolder;
public Player(TexturedModel model, Vector3f position, float rotX, float rotY, float rotZ,
float scaleX, float scaleY, float scaleZ) {
this.model = model;
this.rotX = rotX;
this.rotY = rotY;
this.rotZ = rotZ;
this.scaleX = scaleX;
this.scaleY = scaleY;
this.scaleZ = scaleZ;
this.position = position;
Random random = new Random();
position = new Vector3f();
velocity = new Vector3f();
acceleration = new Vector3f();
direction = new Vector3f();
}
public void update() {
velocity = velocity.add(acceleration);
position = position.add(velocity);
maxHolder = maxVelocity;
//position.length()
//Limit
if (velocity.length() > maxVelocity) {
velocity = velocity.normalize().scale(maxVelocity);
}
else if (velocity.dot(direction) < 0.0) {
velocity = new Vector3f(0,0,0);
}
}
public void movePlayer() {
if (KeyboardInput.isKeyDown(GLFW_KEY_D)) {
this.acceleration.x = 0.001f;
}
if (KeyboardInput.isKeyDown(GLFW_KEY_A)) {
this.acceleration.x = -0.001f;
}
if (KeyboardInput.isKeyDown(GLFW_KEY_W)) {
this.acceleration.y = 0.001f;
}
if (KeyboardInput.isKeyDown(GLFW_KEY_S)) {
this.acceleration.y = -0.001f;
}
if (!KeyboardInput.isKeyDown(GLFW_KEY_W) && !KeyboardInput.isKeyDown(GLFW_KEY_S) && !KeyboardInput.isKeyDown(GLFW_KEY_D) && !KeyboardInput.isKeyDown(GLFW_KEY_A)){
this.velocity.x = 0;
this.velocity.y = 0;
this.velocity.z = 0;
this.acceleration.x = 0f;
this.acceleration.y = 0;
this.acceleration.z = 0;
}
}
public void applyForce(Vector3f force) {
acceleration = force;
}
public void increasePosition(float dx, float dy, float dz) {
this.velocity.x += dx;
this.velocity.y += dy;
this.velocity.z += dz;
}
public void increaseRotation(float dx, float dy, float dz) {
this.rotX += dx;
this.rotY += dy;
this.rotZ += dz;
}
public TexturedModel getModel() {
return model;
}
public void setModel(TexturedModel model) {
this.model = model;
}
public void setVelocity(Vector3f velocity) {
this.velocity = velocity;
}
public Vector3f getPosition() {
return position;
}
public void setPosition(Vector3f position) {
this.position = position;
}
public float getRotX() {
return rotX;
}
public void setRotX(float rotX) {
this.rotX = rotX;
}
public float getRotY() {
return rotY;
}
public void setRotY(float rotY) {
this.rotY = rotY;
}
public float getRotZ() {
return rotZ;
}
public void setRotZ(float rotZ) {
this.rotZ = rotZ;
}
public float getScaleX() {
return scaleX;
}
public void setScaleX(float scaleX) {
this.scaleX = scaleX;
}
public float getScaleY() {
return scaleY;
}
public void setScaleY(float scaleY) {
this.scaleY = scaleY;
}
public float getScaleZ() {
return scaleZ;
}
public void setScaleZ(float scaleZ) {
this.scaleZ = scaleZ;
}
}
Heres the current code: It accelerates but velocity snaps back to 0 as I let go of the key. I want it to decelerate. Conceptually it should be easy.
I am trying to make a game. I want the projectiles (balls) that I shoot to each have their own individual collisions with objects and the margins of the game screen, but right now when one ball collides with the game screen margins, every balls' velocity.x or velocity.y is multiplied by -1 to simulate collision rather than just the individual ball that hit's velocity being modified. (When one ball hits, all balls' velocities are affected). The projectiles are stored in an ArrayList in the GameWorld class and are all given an identical velocity when they are shot. You pick a direction to shoot in, then balls are shot every 0.3s in that direction until all balls are shot.
Here is the code from my Projectiles class:
package com.trimble.gameobjects;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Vector2;
import com.trimble.gameworld.GameWorld;
public class Projectile {
private Vector2 velocity, acceleration;
private Vector2 position;
private final float RADIUS = 3f;
private boolean active, shot;
private GameWorld world;
private float theta;
public Projectile(float x, GameWorld world) {
this.world = world;
this.position = new Vector2();
this.position.x = x;
this.position.y = world.getGameRect().y - 3;
// hitbox = new Circle(position, 3f);
this.velocity = new Vector2();
this.acceleration = new Vector2(0, 0.5f);
this.active = false;
this.shot = false;
}
public void update(float delta) {
if (active) {
position.add(velocity.cpy().scl(delta));
velocity.add(acceleration.cpy().scl(delta));
// left
if (this.position.x <= 3) {
Gdx.app.log("hit", " left");
this.position.x = 3;
this.velocity.x *= -1;
}
// right
else if (this.position.x >= world.getGameRect().width - 3) {
Gdx.app.log("hit", " right");
this.position.x = world.getGameRect().width - 3;
this.velocity.x *= -1;
}
// top
if (this.position.y < world.getGameRect().y + world.getGameRect().height + 3) {
Gdx.app.log("hit", " top");
this.position.y = world.getGameRect().y + world.getGameRect().height + 3;
this.velocity.y *= -1;
}
// bottom
else if (this.position.y > world.getGameRect().y - 3 && velocity.y > 0) {
Gdx.app.log("hit", " bottom");
if (!this.world.hasTouched()) {
this.world.getBaseCircle().setPositionX(position.x);
this.world.setTouched(true);
}
zeroVelocity();
this.active = false;
this.position = world.getBaseCirclePos();
this.world.addInactive();
}
}
}
public Vector2 getVelocity() {
return velocity;
}
public float getVelocityX() {
return velocity.x;
}
public float getVelocityY() {
return velocity.y;
}
public void setVelocity(Vector2 velocity) {
this.velocity = velocity;
}
public void setVelocityX(float x) {
this.velocity.x = x;
}
public void setVelocityY(float y) {
this.velocity.y = y;
}
public float getTheta() {
return theta;
}
public void setTheta(float theta) {
this.theta = theta;
}
public void zeroVelocity() {
this.velocity.x = 0;
this.velocity.y = 0;
}
public Vector2 getPosition() {
return position;
}
public void setPositionY(float y) {
this.position.y = y;
}
public void setPositionX(float x) {
this.position.x = x;
}
public void setPosition(Vector2 position) {
this.position = position;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public float getR() {
return RADIUS;
}
public boolean wasShot() {
return shot;
}
public void setShot(boolean shot) {
this.shot = shot;
}
}
Here is the code in GameWorld which is called when the player shoots:
public void transitionHasShot() {
if (currentState == GameState.READY) {
currentState = GameState.HASSHOT;
velocity.y = (float) (-165 * Math.sin(theta));
velocity.x = (float) (165 * Math.cos(theta));
baseCircle.setActive(false);
for (Projectile p : projectiles) {
p.setVelocity(velocity);
}
projectiles.get(0).setActive(true);
}
}
Let me know if you need any more info.
I solved the problem by changing the code in transitionHasShot():
change
for (Projectile p : projectiles) {
p.setVelocity(velocity);
}
to:
for (Projectile p : projectiles) {
p.setVelocity(velocity.cpy());
}
I am a new Android game developer. I want to force my game object which moves to projectile trajectory like in Angry birds.
Related example here and my example You can see image.
I use jbox2d little bit code, but I don't know how to make it work.
private static class ProjectileEquation {
public float gravity;
public Vector2 startVelocity = new Vector2();
public Vector2 startPoint = new Vector2();
public float yogx(float t) {
return startPoint.x + t * startVelocity.x;
}
public float yogy(float t) {
float u = (float) -4.97741939970554;
float v = (float) 30.88079;
float tt = 1/6f;
float n = (u+v)/2*tt;
return startPoint.y + n * t *startVelocity.y + 0.5f *(n*n+n)
* t * t * gravity;
}
}
private static class Controller {
public float power = -66f;
public float angle = 585f;
}
}
public float P2M(float xPixels) {
return xPixels * metersPerPixel;
}
public float M2P(float xMetres) {
return xMetres * pixelsPerMeter;
}
public float MaxHeight(){
if (projectileEquation.startVelocity.y > 0){
return projectileEquation.startPoint.y;
}
return projectileEquation.startPoint.y;
}
public void Update() {
projectileEquation.startVelocity.set(controller.power,controller.power);
projectileEquation.startVelocity.rotate(controller.angle);
// bd = bodies;
}
#Override
protected void onDraw(Canvas c) {
super.onDraw(c);
MaxHeight();
Update();
float t = 0f;
x = c.getWidth()/2;
y = c.getHeight()-20;
float timeSeparation = this.timeSeparation;
for (int i = 0; i < trajectoryPointCount; i++) {
float x = this.x + projectileEquation.yogx(t);
float y = this.y + -projectileEquation.yogy(t);
t += timeSeparation;
if(A) {
c.drawBitmap(bmp, x, y, null);
}else if(B) {
float bX = M2P(body.getPosition().x);
float by = c.getHeight() - M2P(body.getPosition().y);
body.setActive(true);
c.drawCircle(bX, by, M2P(body.m_fixtureList.m_shape.m_radius), circlePaint);
}
}
}
public class jbox2d {
public float targetFps = 30.0f;
public float timeStep = (1.0f / targetFps);
private int interations = 2;
public Body body;
private World world;
private BodyDef bodydef;
public void Create(){
Vec2 gravity = new Vec2(0,-10f);
boolean doSleep = true;
world = new World(gravity, doSleep);
}
public void addboll() {
bodydef = new BodyDef();
bodydef.type = BodyType.DYNAMIC;
bodydef.allowSleep = true;
bodydef.position.set(8.24f,10f);
body = world.createBody(bodydef);
body.setActive(false);
float tt = 0f;
Vec2 stx = new Vec2();
Vec2 sty =new Vec2();
for (int it = 0; it < 20; it++) {
stx = M2P(projectileEquation.startVelocity.x);
sty = M2P(projectileEquation.startVelocity.y);
stx = M2P(projectileEquation.yogx(tt));
sty = -M2P(projectileEquation.yogy(tt));
body.setLinearVelocity(new Vec2(stx,sty));
body.applyLinearImpulse(body.getLinearVelocity(), body.getWorldCenter());
tt += timeSeparation;
}
CircleShape circle = new CircleShape();
circle.m_radius = (float).42;
FixtureDef fixturedef = new FixtureDef();
fixturedef.density = 1.0f;
fixturedef.restitution = 0.9f;
fixturedef.friction = 0.2f;
fixturedef.shape = circle;
body.createFixture(fixturedef);
}
public void update(){
world.step(timeStep, interations, interations);
}
}
Im coding a Game with lwjgl3. I initially used lwjgl 2. but of major chanllenges, i switched to lwjgl3.
I walked through a couple tutorials and put together a gameloop with a window class and tried to implement the code i already had.
I had to change multiple things, had challenges like the slick util textureloader, but now im stuck:
Basically what i see is the Window, but nothing is displayed on it.
My Engine is fairly big by now, but i will try to implement the important methods. When you need more, i can post more.
I will post the Shaderfiles for entity and skybox (what im trying to display currently) too
And all i see is a Window with nothing displayed
MAIN CLASS
package main;
import static org.lwjgl.glfw.GLFW.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.opengl.GL;
import entities.Camera;
import entities.Light;
import entities.Player;
import graphics.Window;
import graphics.models.RawModel;
import graphics.models.TexturedModel;
import graphics.renderEngine.Loader;
import graphics.renderEngine.MasterRenderer;
import graphics.renderEngine.OBJLoader;
import graphics.textures.ModelTexture;
import toolbox.Vector3f;
public class Main
{
private GLFWErrorCallback errorCallback = GLFWErrorCallback.createPrint(System.err);
private Window window;
private MasterRenderer renderer;
private Loader loader;
private int Width;
private int Height;
private boolean running = false;
private double delta;
List<Light> lights = new ArrayList<Light>();
Camera camera = null;
private Player player;
public Main()
{
init();
}
private void input()
{
glfwPollEvents();
if(window.shouldClose()) stop();
}
private void update()
{
renderer.setHeight(Height);
renderer.setWidth(Width);
renderer.setDelta(delta);
}
private void render()
{
renderer.processEntity(player);
renderer.render(lights, camera);
window.render();
}
private void run()
{
long lastTime = System.nanoTime();
long currentTime = lastTime;
long diff = 0;
long timer = System.currentTimeMillis();
double ns = 1000000000 / 60.0;
delta = 0.0;
double dfps = 1000000000 / 60.0;
double d = 0.0;
int fps = 0;
int ups = 0;
while(running)
{
currentTime = System.nanoTime();
diff = currentTime - lastTime;
delta += (diff)/ ns;
d += diff/dfps;
lastTime = currentTime;
while(delta >= 1.0)
{
input();
update();
ups++;
delta--;
}
if(d >- 1.0)
{
render();
fps++;
d = 0.0;
}
if(System.currentTimeMillis() > timer + 1000)
{
window.setTitle("Junker.5 | ups: "+ups+"| fps: "+fps+"");
ups = 0;
fps = 0;
timer += 1000;
}
}
cleanUp();
}
public void start()
{
if(running) return;
running = true;
run();
}
public void stop()
{
if(!running) return;
running = false;
}
private void init()
{
Width = 1280;
Height = 720;
glfwSetErrorCallback(errorCallback);
glfwInit();
window = new Window(Width, Height, "Junker.5");
GL.createCapabilities();
loader = new Loader();
renderer = new MasterRenderer(loader);
renderer.setHeight(Height);
renderer.setWidth(Width);
renderer.setDelta(delta);
RawModel playerShip = OBJLoader.loadObjModel("Puddle Jumper", loader);
TexturedModel playership = new TexturedModel(playerShip, ModelTexture.loadTexture("white"));
player = new Player(playership, new Vector3f(0, 0, -50),0,0,0,1);
lights.add(new Light(new Vector3f(0,1000,-5000), new Vector3f(0f,0.4f,5f)));
lights.add(new Light(new Vector3f(0,0,-10), new Vector3f(1,0,1), new Vector3f(1, 0.01f, 0.002f)));
try
{
camera = new Camera(player);
}
catch (IOException e)
{
e.printStackTrace();
}
}
private void cleanUp()
{
window.hide();
//guiRenderer.cleanUp();
renderer.cleanUp();
loader.cleanUp();
window.dispose();
}
public static void main(String[] args)
{
Main main = new Main();
main.start();
}
public int getWidth()
{
return window.getWidth();
}
public int getheight()
{
return window.getHeight();
}
public double getDelta()
{
return delta;
}
}
MASTER RENDERER CLASS
package graphics.renderEngine;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.lwjgl.opengl.GL11;
import entities.Camera;
import entities.Entity;
import entities.Light;
import entities.Player;
import graphics.models.RawModel;
import graphics.models.TexturedModel;
import graphics.shaders.StaticShader;
import graphics.shaders.TerrainShader;
import graphics.skybox.SkyboxRenderer;
import graphics.terrains.Terrain;
import graphics.textures.ModelTexture;
import toolbox.Matrix4f;
import toolbox.Vector3f;
public class MasterRenderer
{
private static final float FOV = 70;
private static final float NEAR_PLANE = 0.01f;
private static final float FAR_PLANE = 1000;
public int Width;
public double delta;
public int Height;
private Matrix4f projectionMatrix;
private StaticShader shader = new StaticShader();
private TerrainRenderer terrainRenderer;
private TerrainShader terrainShader = new TerrainShader();
private EntityRenderer renderer;
private Map<TexturedModel, List<Entity>> entities = new HashMap<TexturedModel, List<Entity>>();
private List<Terrain> terrains = new ArrayList<Terrain>();
private SkyboxRenderer skyboxRenderer ;
public MasterRenderer(Loader loader)
{
enableCulling();
createProjectionMatrix();
renderer = new EntityRenderer(shader, projectionMatrix);
terrainRenderer = new TerrainRenderer(terrainShader, projectionMatrix);
skyboxRenderer = new SkyboxRenderer(loader, projectionMatrix);
}
public static void enableCulling()
{
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glCullFace(GL11.GL_BACK);
}
public static void disableCullig()
{
GL11.glDisable(GL11.GL_CULL_FACE);
}
public void render(List<Light> lights, Camera camera)
{
prepare();
shader.start();
shader.loadLights(lights);
shader.loadViewMatrix(camera);
renderer.render(entities);
shader.stop();
terrainShader.start();
terrainShader.loadLights(lights);
terrainShader.loadViewMatrix(camera);
terrainRenderer.render(terrains);
terrainShader.stop();
skyboxRenderer.render(camera);
terrains.clear();
entities.clear();
}
public void processTerrain(Terrain terrain)
{
terrains.add(terrain);
}
public void processEntity(Entity entity)
{
TexturedModel entityModel = entity.getModel();
List<Entity> batch = entities.get(entityModel);
if(batch != null)
{
batch.add(entity);
}
else
{
List<Entity> newBatch = new ArrayList<Entity>();
newBatch.add(entity);
entities.put(entityModel, newBatch);
}
}
private void createProjectionMatrix()
{
float aspectRatio = (float) Width / (float) Height;
float y_scale = (float) ((1f / Math.tan(Math.toRadians(FOV / 2f))) * aspectRatio);
float x_scale = y_scale / aspectRatio;
float frustum_length = FAR_PLANE - NEAR_PLANE;
projectionMatrix = new Matrix4f();
projectionMatrix.m00 = x_scale;
projectionMatrix.m11 = y_scale;
projectionMatrix.m22 = -((FAR_PLANE + NEAR_PLANE) / frustum_length);
projectionMatrix.m23 = -1;
projectionMatrix.m32 = -((2 * FAR_PLANE + NEAR_PLANE) / frustum_length);
projectionMatrix.m33 = 0;
}
public void prepare()
{
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT|GL11.GL_DEPTH_BUFFER_BIT);
GL11.glClearColor(0.03f, 0f, 0.0f, 1);
}
public void cleanUp()
{
shader.cleanUp();
terrainShader.cleanUp();
}
public void setWidth(int width)
{
Width = width;
}
public void setHeight(int height)
{
Height = height;
}
public void setDelta(double delta)
{
this.delta = delta;
}
}
STATIC SHADER CLASS
package graphics.shaders;
import java.util.List;
import entities.Camera;
import entities.Light;
import toolbox.Maths;
import toolbox.Matrix4f;
import toolbox.Vector3f;
public class StaticShader extends ShaderProgram
{
public static final String VERTEX_FILE = "./Ressources/Shaders/VertexShader.shd";
public static final String FRAGMENT_FILE = "./Ressources/Shaders/FragmentShader.shd";
public static final int MAX_LIGHTS = 4;
private int location_transformationMatrix;
private int location_projectionMatrix;
private int location_viewMatrix;
private int location_lightPosition[];
private int location_lightColour[];
private int location_attenuation[];
private int location_shineDamper;
private int location_reflectivity;
private int location_useFakeLighting;
public StaticShader()
{
super(VERTEX_FILE, FRAGMENT_FILE);
}
#Override
protected void bindAttributes()
{
super.bindAttribute(0, "position");
super.bindAttribute(1, "textureCoords");
super.bindAttribute(2, "normal");
}
protected void getAllUniformLocations()
{
location_transformationMatrix = super.getUniformLocation("transformationMatrix");
location_projectionMatrix = super.getUniformLocation("projectionMatrix");
location_viewMatrix = super.getUniformLocation("viewMatrix");
location_shineDamper = super.getUniformLocation("shineDamper");
location_reflectivity = super.getUniformLocation("reflectivity");
location_useFakeLighting = super.getUniformLocation("useFakeLighting");
location_lightPosition = new int[MAX_LIGHTS];
location_attenuation = new int[MAX_LIGHTS];
location_lightColour = new int[MAX_LIGHTS];
for(int i = 0;i<MAX_LIGHTS;i++)
{
location_lightPosition[i] = super.getUniformLocation("lightPosition["+i+"]");
location_lightColour[i] = super.getUniformLocation("lightColour["+i+"]");
location_attenuation[i] = super.getUniformLocation("attenuation["+i+"]");
}
}
public void loadFakeLightingVariable(boolean useFake)
{
super.loadBoolean(location_useFakeLighting, useFake);
}
public void loadShineVariables(float damper, float reflectivity)
{
super.LoadFloat(location_shineDamper, damper);
super.LoadFloat(location_reflectivity, reflectivity);
}
public void loadTreansformationMatrix(Matrix4f matrix)
{
super.loadMatrix(location_transformationMatrix, matrix);
}
public void loadLights(List<Light> lights)
{
for(int i = 0;i<MAX_LIGHTS;i++)
{
if(i<lights.size())
{
super.LoadVector(location_lightPosition[i], lights.get(i).getPosition());
super.LoadVector(location_lightColour[i], lights.get(i).getColour());
super.LoadVector(location_attenuation[i], lights.get(i).getAttenuation());
}
else
{
super.LoadVector(location_lightPosition[i], new Vector3f(0,0,0));
super.LoadVector(location_lightColour[i], new Vector3f(0,0,0));
super.LoadVector(location_attenuation[i], new Vector3f(1,0,0));
}
}
}
public void loadViewMatrix(Camera camera)
{
Matrix4f viewMatrix = Maths.createViewMatrix(camera);
super.loadMatrix(location_viewMatrix, viewMatrix);
}
public void loadProjectionMatrix(Matrix4f projection)
{
super.loadMatrix(location_projectionMatrix, projection);
}
}
SHADERFILES:
FRAGMENT SHADER
#version 400 core
in vec2 pass_textureCoords;
in vec3 surfaceNormal;
in vec3 toLightVector[4];
in vec3 toCameraVector;
out vec4 out_Color;
uniform sampler2D textureSampler;
uniform vec3 lightColour[4];
uniform float shineDamper;
uniform float reflectivity;
uniform vec3 attenuation[4];
void main(void)
{
vec3 unitNormal = normalize(surfaceNormal);
vec3 unitVectorToCamera = normalize(toCameraVector);
vec3 totalDiffuse = vec3(0.0);
vec3 totalSpecular = vec3(0.0);
for(int i=0;i<4;i++)
{
float distance = length(toLightVector[i]);
float attFactor = attenuation[i].x + (attenuation[i].y * distance) + (attenuation[i].z * distance * distance);
vec3 unitLightVector = normalize(toLightVector[i]);
float nDot1 = dot(unitNormal, unitLightVector);
float brightness = max(nDot1,0.0);
vec3 lightDirection = -unitLightVector;
vec3 reflectedLightDirection = reflect(lightDirection,unitNormal);
float specularFactor = dot(reflectedLightDirection, unitVectorToCamera);
specularFactor = max(specularFactor,0.0);
float dampedFactor = pow(specularFactor,shineDamper);
totalSpecular = totalSpecular + (dampedFactor * reflectivity * lightColour[i])/attFactor;
totalDiffuse = totalDiffuse + (brightness * lightColour[i])/attFactor;
}
totalDiffuse = max(totalDiffuse, 0.2);
vec4 textureColour = texture(textureSampler, pass_textureCoords);
if(textureColour.a<0.5)
{
discard;
}
out_Color = vec4(totalDiffuse,1.0) * texture(textureSampler, pass_textureCoords) + vec4(totalSpecular,1.0);
}
VERTEX SHADER
#version 400 core
in vec3 position;
in vec2 textureCoords;
in vec3 normal;
out vec2 pass_textureCoords;
out vec3 surfaceNormal;
out vec3 toLightVector[4];
out vec3 toCameraVector;
uniform mat4 transformationMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform vec3 lightPosition[4];
uniform float useFakeLighting;
void main(void)
{
vec4 worldPosition = transformationMatrix * vec4(position,1.0);
gl_Position = projectionMatrix * viewMatrix * worldPosition;
pass_textureCoords = textureCoords;
vec3 actualNormal = normal;
if(useFakeLighting > 0.5)
{
actualNormal = vec3(0.0,1.0,0.0);
}
surfaceNormal = (transformationMatrix * vec4(actualNormal,0.0)).xyz;
for(int i=0;i<4;i++)
{
toLightVector[i] = lightPosition[i] - worldPosition.xyz;
}
toCameraVector = (inverse(viewMatrix) * vec4(0.0,0.0,0.0,1.0)).xyz - worldPosition.xyz;
}
I have absolutely no idea what im doing wrong. If anyone wants to really help me more personal on this problem, feel free to contact me too.
Thank you soo much!
EDIT:
Yes, the Clearcolor works, thats part of why i am confused.
And before i worked ofer my lwjgl2 code to my new lwjgl3 code, the lwjgl3 window DID display simple graphics such as a 3d cube
Here is my window class
WINDOW
package graphics;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.system.MemoryUtil.*;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.system.MemoryUtil;
public class Window
{
private long window;
private int Width;
private int Height;
public Window(int width, int height, String title)
{
this.Width = width;
this.Height = height;
glfwDefaultWindowHints();
glfwWindowHint(GLFW_RESIZABLE, GL11.GL_FALSE);
glfwWindowHint(GLFW_VISIBLE, GL11.GL_TRUE);
//DECORATION
glfwWindowHint(GLFW_DECORATED, GL11.GL_TRUE);
glfwWindowHint(GLFW_FOCUSED, GL11.GL_TRUE);
window = glfwCreateWindow(Width,Height,"Junker.5",NULL,NULL);
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(
window,
(vidmode.width() - width) / 2,
(vidmode.height() - height) / 2
);
glfwMakeContextCurrent(window);
}
public void dispose()
{
glfwDestroyWindow(window);
}
public void hide()
{
glfwHideWindow(window);
}
public void render()
{
glfwSwapBuffers(window);
}
public void show()
{
glfwShowWindow(window);
}
public void setTitle(String title)
{
glfwSetWindowTitle(window, title);
}
public boolean shouldClose()
{
if(!glfwWindowShouldClose(window))
{
return false;
}
else
{
return true;
}
}
public int getWidth()
{
return Width;
}
public void setWidth(int width)
{
Width = width;
}
public int getHeight()
{
return Height;
}
public void setHeight(int height)
{
Height = height;
}
public void changecursor()
{
// Create the cursor object
//long cursor = GLFW.glfwCreateCursor(imageBuffer, 0, 0);
/*if (cursor == MemoryUtil.NULL)
throw new RuntimeException("Error creating cursor");
// Set the cursor on a window
GLFW.glfwSetCursor(window, cursor);*/
}
}
I did manage to fix the problem myself, atleast its displaying stuff now :)
I just hardcoded the Width and height right now. The method of doing a setHeight() in the Main class must have angried the gods of my createProjectionMatrix() function. However, id would be awesome to know how to do this dynamic for future purposes
I've researched this quite a bit but I can't seem to find why I'm getting this error. I've ruled out the origin of the error coming from anywhere but "Transform .java:38", so I don't think I need to include that code. Line 38 is followed by 4 asterisks(*).
Error:
Exception in thread "main" java.lang.NullPointerException
at com.base.engine.Transform.getProjectedTransformation(Transform.java:38)
at com.base.engine.Game.render(Game.java:67)
at com.base.engine.MainComponent.render(MainComponent.java:111)
at com.base.engine.MainComponent.run(MainComponent.java:102)
at com.base.engine.MainComponent.start(MainComponent.java:28)
at com.base.engine.MainComponent.main(MainComponent.java:126)
Code:
package com.base.engine;
public class Transform
{
private static Camera camera;
private static float zNear;
private static float zFar;
private static float width;
private static float height;
private static float fov;
private Vector3f translation;
private Vector3f rotation;
private Vector3f scale;
public Transform()
{
translation = new Vector3f(0,0,0);
rotation = new Vector3f(0,0,0);
scale = new Vector3f(1,1,1);
}
public Matrix4f getTransformation()
{
Matrix4f translationMatrix = new Matrix4f().initTranslation(translation.getX(), translation.getY(), translation.getZ());
Matrix4f rotationMatrix = new Matrix4f().initRotation(rotation.getX(), rotation.getY(), rotation.getZ());
Matrix4f scaleMatrix = new Matrix4f().initScale(scale.getX(), scale.getY(), scale.getZ());
return translationMatrix.mul(rotationMatrix.mul(scaleMatrix));
}
public Matrix4f getProjectedTransformation()
{
Matrix4f transformationMatrix = getTransformation();
Matrix4f projectionMatrix = new Matrix4f().initProjection(fov, width, height, zNear, zFar);
Matrix4f cameraRotation = new Matrix4f().initCamera(camera.getForward(), camera.getUp());
****Matrix4f cameraTranslation = new Matrix4f().initTranslation(-camera.getPos().getX(), -camera.getPos().getY(), -camera.getPos().getZ());
return projectionMatrix.mul(cameraRotation.mul(cameraTranslation.mul(transformationMatrix)));
}
public Vector3f getTranslation()
{
return translation;
}
public static void setProjection(float fov, float width, float height, float zNear, float zFar)
{
Transform.fov = fov;
Transform.width = width;
Transform.height = height;
Transform.zNear = zNear;
Transform.zFar = zFar;
}
public void setTranslation(Vector3f translation)
{
this.translation = translation;
}
public void setTranslation(float x, float y, float z)
{
this.translation = new Vector3f(x, y, z);
}
public Vector3f getRotation()
{
return rotation;
}
public void setRotation(Vector3f rotation)
{
this.rotation = rotation;
}
public void setRotation(float x, float y, float z)
{
this.rotation = new Vector3f(x, y, z);
}
public Vector3f getScale()
{
return scale;
}
public void setScale(Vector3f scale)
{
this.scale = scale;
}
public void setScale(float x, float y, float z)
{
this.scale = new Vector3f(x, y, z);
}
public static Camera getCamera()
{
return camera;
}
public static void setCamera(Camera camera)
{
Transform.camera = camera;
}
}
More Code:
package com.base.engine;
public class Camera
{
public static final Vector3f yAxis = new Vector3f(0,1,0);
private Vector3f pos;
private Vector3f forward;
private Vector3f up;
public Camera()
{
this(new Vector3f(0,0,0), new Vector3f(0,0,1), new Vector3f(0,1,0));
}
public Camera(Vector3f ps, Vector3f forward, Vector3f up)
{
this.pos = pos;
this.forward = forward;
this.up = up;
up.normalize();
forward.normalize();
}
public void move(Vector3f dir, float amt)
{
pos = pos.add(dir.mul(amt));
}
public void rotateY(float angle)
{
Vector3f Haxis = yAxis.cross(forward);
Haxis.normalize();
forward.rotate(angle, yAxis);
forward.normalize();
up = forward.cross(Haxis);
up.normalize();
}
public void rotateX(float angle)
{
Vector3f Haxis = yAxis.cross(forward);
Haxis.normalize();
forward.rotate(angle, Haxis);
forward.normalize();
up = forward.cross(Haxis);
up.normalize();
}
public Vector3f getLeft()
{
Vector3f left = up.cross(forward);
left.normalize();
return left;
}
public Vector3f getRight()
{
Vector3f right = forward.cross(up);
right.normalize();
return right;
}
public Vector3f getPos() {
return pos;
}
public void setPos(Vector3f pos) {
this.pos = pos;
}
public Vector3f getForward() {
return forward;
}
public void setForward(Vector3f forward) {
this.forward = forward;
}
public Vector3f getUp() {
return up;
}
public void setUp(Vector3f up) {
this.up = up;
}
}
here's the answer: you don't need to research anything. you get a NullPointerException when you dereference a null reference. run your code in a debugger and figure out why the reference in question is null when you don't think it should be null. you need to learn how to debug these things yourself.
There is a typo in the constructor:
Wrong:
public Camera(Vector3f ps, Vector3f forward, Vector3f up)
{
this.pos = pos;
this.forward = forward;
this.up = up;
up.normalize();
forward.normalize();
}
Correct:
public Camera(Vector3f pos, Vector3f forward, Vector3f up)
{
this.pos = pos;
this.forward = forward;
this.up = up;
up.normalize();
forward.normalize();
}
There should have been a warning about the variable ps.