Merge branch 'engineWIP' into 'master'

EngineWIP -> master (2)

See merge request fautin/jeu-de-combat!5
This commit is contained in:
François Autin 2021-05-27 11:27:41 +00:00
commit 04c28b9e0f
32 changed files with 1307 additions and 10 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
/.idea/
/.gitignore
/jeu-de-combat.iml
/target/
/bin/

9
.idea/jeu-de-combat.iml generated Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/jeu-de-combat.iml" filepath="$PROJECT_DIR$/jeu-de-combat.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

Binary file not shown.

View File

@ -0,0 +1,10 @@
#version 330 core
out vec4 FragColor;
uniform float time;
void main()
{
FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
}

View File

@ -0,0 +1,12 @@
#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 transform;
void main()
{
gl_Position = projection * view * transform * vec4(aPos, 1.0);
}

View File

@ -0,0 +1,12 @@
#version 330 core
in vec3 color;
out vec4 FragColor;
uniform float time;
void main()
{
FragColor = vec4(color, 1.0f);
}

View File

@ -0,0 +1,16 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
out vec3 color;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 transform;
void main()
{
gl_Position = projection * view * transform * vec4(aPos, 1.0);
color = aColor;
}

View File

@ -0,0 +1,13 @@
#version 410 core
out vec4 FragColor;
in vec2 texCoord;
uniform sampler2D texture1;
uniform float time;
void main()
{
FragColor = texture(texture1, texCoord);
}

View File

@ -0,0 +1,16 @@
#version 410 core
layout (location = 0) in vec3 aPos;
layout (location = 2) in vec2 aTexCoord;
out vec2 texCoord;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 transform;
void main()
{
gl_Position = projection * view * transform * vec4(aPos, 1.0);
texCoord = aTexCoord;
}

View File

@ -0,0 +1,19 @@
#version 410 core
out vec4 FragColor;
in vec4 color;
in vec2 texCoord;
uniform sampler2D texture1;
uniform float time;
void main()
{
vec4 tex = texture(texture1, texCoord);
if (tex.a == 0.0){
FragColor = tex;
} else{
FragColor = mix(tex, color, 0.5);
}
}

View File

@ -0,0 +1,19 @@
#version 410 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec2 texCoord;
out vec4 color;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 transform;
void main()
{
gl_Position = projection * view * transform * vec4(aPos, 1.0);
color = vec4(aColor, 1.0f);
texCoord = aTexCoord;
}

View File

@ -0,0 +1,21 @@
#version 410 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec2 fragCoord;
out vec2 texCoord;
out vec4 color;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 transform;
void main()
{
gl_Position = projection * view * transform * vec4(aPos, 1.0);
color = vec4(aColor, 1.0f);
texCoord = aTexCoord;
fragCoord = aPos.xy;
}

View File

@ -0,0 +1,21 @@
#version 410
out vec4 FragColor;
in vec4 color;
in vec2 fragCoord;
in vec2 texCoord;
uniform sampler2D texture1;
uniform float time;
void main()
{ // Pas fini c'est moche
vec4 colorPoweredUp = abs(vec4(color.xyz * sin(fragCoord.y + time*20), 1.0));
vec4 tex = texture(texture1, texCoord);
if (tex.a == 0.0){
FragColor = tex;
} else{
FragColor = mix(tex, colorPoweredUp, 0.5);
}
}

View File

@ -7,8 +7,8 @@
* *
*/ */
import launcher.Launcher;
import engine.Engine; import engine.Engine;
import launcher.Launcher;
import javafx.application.Application; import javafx.application.Application;
public class Main { public class Main {

View File

@ -1,14 +1,305 @@
/**
* CLASS ENGINE
*
* Classe principale du moteur de jeu
*
* @author François Autin
*
*/
package engine; package engine;
import engine.math.*;
import engine.object.*;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWFramebufferSizeCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.NULL;
public class Engine { public class Engine {
private static long window;
private final List<ObjectGl> objectsGl;
private static boolean present = glfwJoystickPresent(GLFW_JOYSTICK_1);
private boolean running;
/**
* Create the engine and initial attributes use .init() to start the engine
*/
public Engine() {
this.running = false;
this.objectsGl = new ArrayList<>();
float width = 1280.0f;
ObjectGl.projection = Matrix4f.orthographic(-width, width, -width * 9.0f / 16.0f, width * 9.0f / 16.0f, 0.1f, 100.0f);
ObjectGl.view = Matrix4f.translate(new Vector3f(0.0f,0.0f,1.0f));
}
/**
* Start the engine
* Create the window
* Set the color of the background
*/
public void init() {
glfwInit();
this.running = true;
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); //On utilise la version 3.3 d'openGL
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //Compatible MAC
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //Le core profile est l'interface 'avancé' d'openGL
int width = 1280;
int height = 720;
this.setWindow(glfwCreateWindow(width, height, "Boulevard Combattant", NULL, NULL));
assert getWindow() != NULL;
System.out.println(present);
// On ©cupère les informations du moniteur principal
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
assert vidmode != null;
// On met la fenêtre au centre de l'écran principale
glfwSetWindowPos(getWindow(), (vidmode.width() - width)/2, (vidmode.height() - height)/2);
glfwSetKeyCallback(getWindow(), new Input());
glfwSetInputMode(getWindow(), GLFW_STICKY_KEYS, GLFW_TRUE);
// Contexte = zone cible des rendus
glfwMakeContextCurrent(getWindow());
glfwShowWindow(getWindow());
GL.createCapabilities();
glfwSetFramebufferSizeCallback(getWindow(), resizeWindow);
glEnable(GL_DEPTH_TEST); // Z-Buffer plus z est grand plus l'objet est proche de la camera limite à 100.0f au dela l'objet disparait
glEnable(GL_BLEND); // Transparence
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
System.out.println("OpenGL: " + glGetString(GL_VERSION));
}
/**
*
*/
public void update(){
glfwPollEvents();
}
/**
*
*/
public void render(){
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
objectsGl.sort(new SortZ());
for (ObjectGl objectGl : objectsGl) {
objectGl.render();
}
int error = glGetError();
if (error != GL_NO_ERROR) System.out.println(error);
glfwSwapBuffers(getWindow()); //Envoie le buffer vers le moniteur
}
/**
* Add obj to the render queue
* @param obj
*/
public void add_objectGl(ObjectGl obj){
objectsGl.add(obj);
}
public void remove_objectGl(ObjectGl obj){
objectsGl.remove(obj);
}
public boolean isRunning(){
return running;
}
public void setRunning(boolean b){
running = b;
}
public boolean shouldClose(){
return glfwWindowShouldClose(getWindow());
}
public static long getWindow() {
return window;
}
public void setWindow(long window) {
Engine.window = window;
}
/**
* Est appelé àa chaque modification de la taille de la fenêtre, et modifie la taille de la zone de rendu
* pour quelle corresponde à la taille de la fenêtre
*/
private static final GLFWFramebufferSizeCallback resizeWindow = new GLFWFramebufferSizeCallback(){
@Override
public void invoke(long window, int width, int height){
glViewport(0,0,width,height);
}
};
public static void main(String[] args) {
Engine engine = new Engine();
int speed = 10 ; //vitesse déplacement Object
engine.init();
// Add objects to render
String path = "textures/zangief_sprite.png";
String path2 = "textures/awesomeface.png";
ObjectGl zangief = new ObjectGl(0f,60f,80f,10f, path, null);
zangief.setTextureWrap(58,0,62,84, ObjectGl.STICK_TOP);
engine.add_objectGl(zangief);
zangief.translate(new Vector3f(-5000.0f,500.0f,10.0f));
zangief.setColor(new Vector3f(0.0f, 0.0f, 1.0f));
zangief.useTime = true;
zangief.setShader("shaders/StylishShaders/BasicVert.glsl","shaders/StylishShaders/EnergyWave.glsl");
// ObjectGl smiley2 = new ObjectGl(0.0f,500.0f,500.0f, 1f, path2, null);
// engine.add_objectGl(smiley2);
// smiley2.translate(new Vector3f(0.0f,0.0f,5.0f));
long timer = System.currentTimeMillis();
long lastFrame;
int frame = 0;
boolean nextFrame = false;
while(engine.isRunning()){
lastFrame = System.currentTimeMillis();
// Game logic should fit here
if (present) {
gamepadInput(zangief, speed);
}
input(zangief, speed);
// input(smiley2, speed);
/*
********************
* essential part v *
********************
*/
engine.update();
engine.render();
frame++;
if (System.currentTimeMillis() - timer > 1000) {
timer += 1000;
System.out.println("FPS: " + frame);
frame = 0;
}
while(!nextFrame){
nextFrame = System.currentTimeMillis() - lastFrame >= 16.66f;
}
nextFrame = false;
if(engine.shouldClose()) engine.setRunning(false);
}
}
private static void gamepadInput(ObjectGl token, int speed) {
ByteBuffer gamepadButton = glfwGetJoystickButtons(GLFW_JOYSTICK_1);
FloatBuffer gamepadAxes = glfwGetJoystickAxes(GLFW_JOYSTICK_1);
assert gamepadAxes != null;
assert gamepadButton != null;
String name = GLFW.glfwGetJoystickName(GLFW_JOYSTICK_1);
System.out.println("GamePad Name :" + name);
// for (int i =0 ; i < gamepadAxes.capacity(); i++) {
// System.out.println(i + " :" + gamepadAxes.get(i));
// }
if (gamepadButton.get(0) ==1 ) { // appuie sur croix(PlayStation) A (Xbox)
token.translate(new Vector3f ( 0.0f, speed * 5.0f, 0.0f));
}
if ( (gamepadAxes.get(2) < -0.1 || gamepadAxes.get(2) > 0.1) ) { // de droite à gauche //joystick gauche
token.translate(new Vector3f (5*speed * gamepadAxes.get(2), 0.0f, 0.0f));
if ( gamepadAxes.get(2) < -0.1 ){
token.setTextureWrap(121,0,57,80, ObjectGl.DEFAULT);
}else if (gamepadAxes.get(2) > 0.1) {
token.setTextureWrap(178,0,62,82, ObjectGl.DEFAULT);
}
}
if ( (gamepadAxes.get(3) < -0.1 || gamepadAxes.get(3) > 0.1) ) { // de haut en bas //joystick gauche
token.translate(new Vector3f (0.0f, -5* speed * gamepadAxes.get(3), 0.0f));
}
/* Buttons
0 : Croix / A
1: rond /B
2: carré / X
3: triangle / Y
4: L1 / LB
5: R1 / RB
6:select
7:start
8:L3
9:R3
10: haut
11: droite
12: bas
13: gauche
*/
/* Axes
0 : left X axe ( right : 1 left -1)
1: left Y axe ( down : 1 , Up -1)
2: right X axe ( right : 1 left -1)
3: right Y axe ( down : 1 , Up -1)
4:L2 / LT : 1 active, -1 unactive
5: R2 /RT : 1 active, -1 unactive
*/
}
public static void input(ObjectGl token, int speed) {
boolean keyPressed = false;
if (Input.isKeyDown(GLFW.GLFW_KEY_S)) {
token.setTextureWrap(161,260,56,59, ObjectGl.STICK_BOTTOM);
keyPressed = true;
} else if (Input.isKeyDown(GLFW.GLFW_KEY_W)) {
// token.translate(new Vector3f (0.0f, speed * 5.0f, 0.0f));
keyPressed = true;
}
if (Input.isKeyDown(GLFW.GLFW_KEY_A)) {
token.translate(new Vector3f (speed *-5.0f, 0.0f, 0.0f));
// token.setTextureWrap(121,0,57,80, ObjectGl.STICK_TOP);
token.setTextureWrap(121,0,57,82, ObjectGl.STICK_TOP);
keyPressed = true;
}
else if (Input.isKeyDown(GLFW.GLFW_KEY_D)) {
token.translate(new Vector3f (speed * 5.0f, 0.0f, 0.0f));
// token.setTextureWrap(178,0,62,82, ObjectGl.STICK_TOP);
token.setTextureWrap(178,0,62,82, ObjectGl.STICK_TOP);
keyPressed = true;
}
// if (!keyPressed) token.setTextureWrap(58,0,62,84, ObjectGl.STICK_TOP);
if (!keyPressed) token.setTextureWrap(58,0,62,82, ObjectGl.STICK_TOP);
}
} }

26
src/engine/Input.java Normal file
View File

@ -0,0 +1,26 @@
package engine;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWKeyCallback;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
public class Input extends GLFWKeyCallback {
public static boolean[] keys = new boolean[65536];
@Override
public void invoke(long window, int key, int scancode, int action, int mods) {
keys[key] = action != GLFW.GLFW_RELEASE;
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
else if(key == GLFW_KEY_SPACE && action == GLFW_PRESS) //Switch to wireframe
if (glGetInteger(GL_POLYGON_MODE) == GL_FILL) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
public static boolean isKeyDown(int keyCode) {
return glfwGetKey(Engine.getWindow(), keyCode) == 1;
}
}

View File

@ -0,0 +1,75 @@
package engine.graphics;
import engine.math.Matrix4f;
import engine.utils.ShaderUtils;
import engine.math.Vector3f;
import java.util.HashMap;
import java.util.Map;
import static org.lwjgl.opengl.GL20.*;
public class Shader {
private boolean enabled = false;
//Identifiant du programme resultat de la compilation des shaders
private final int ID;
private Map<String, Integer> locationCache = new HashMap<String, Integer>();
/*
Crée le fragment et le vertex shader les lie dans un programme dont il renvoie l'identifiant.
*/
public Shader(String vertex, String fragment) {
ID = ShaderUtils.load(vertex, fragment);
}
public int getUniform(String name){
if (locationCache.containsKey(name)) return locationCache.get(name);
int result = glGetUniformLocation(ID, name);
if (result == -1) System.err.println("Could not find uniform variable " + name);
else locationCache.put(name, result);
return result;
}
public void setUniform1i(String name, int value) {
if (!enabled) enable();
glUniform1i(getUniform(name), value);
}
public void setUniform1f(String name, float value) {
if (!enabled) enable();
glUniform1f(getUniform(name), value);
}
public void setUniform2f(String name, float x, float y) {
if (!enabled) enable();
glUniform2f(getUniform(name), x, y);
}
public void setUniform3f(String name, Vector3f vector) {
if (!enabled) enable();
glUniform3f(getUniform(name), vector.x, vector.y, vector.z);
}
public void setUniform4f(String name, float x, float y, float z, float w) {
if (!enabled) enable();
glUniform4f(getUniform(name), x, y, z, w);
}
public void setUniformMat4f(String name, Matrix4f matrix){
if (!enabled) enable();
glUniformMatrix4fv(getUniform(name), false, matrix.toFloatBuffer());
}
public void enable() {
glUseProgram(ID);
enabled = true;
}
public void disable() {
glUseProgram(0);
enabled = false;
}
}

View File

@ -0,0 +1,75 @@
package engine.graphics;
import engine.utils.BufferUtils;
import org.lwjgl.opengl.GL11;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL30.*;
public class Texture {
private int width, height;
private int texture;
private int index;
public Texture(String path, int index) {
this.index = index;
texture = load(path);
}
private int load(String path) {
int[] pixels = null;
try {
BufferedImage image = ImageIO.read(new FileInputStream(path));
width = image.getWidth();
height = image.getHeight();
pixels = new int[width * height];
image.getRGB(0, 0, width, height, pixels, 0, width);
} catch (IOException e) {
e.printStackTrace();
}
int[] data = new int[width * height];
for (int i = 0; i < width * height; i++) {
int a = (pixels[i] & 0xff000000) >> 24;
int r = (pixels[i] & 0xff0000) >> 16;
int g = (pixels[i] & 0xff00) >> 8;
int b = (pixels[i] & 0xff);
data[i] = a << 24 | b << 16 | g << 8 | r;
}
int result = glGenTextures();
glBindTexture(GL_TEXTURE_2D, result);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GL11.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, BufferUtils.createIntBuffer(data));
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
return result;
}
public void bind() {
glActiveTexture(GL_TEXTURE0 + this.index);
glBindTexture(GL_TEXTURE_2D, texture);
}
public void unbind() {
glBindTexture(GL_TEXTURE_2D, 0);
}
public int getWidth(){
return width;
}
public int getHeight(){
return height;
}
}

View File

@ -0,0 +1,89 @@
package engine.graphics;
import engine.utils.BufferUtils;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL30.*;
public class VertexArray {
private int VAO ,VBO, EBO, CBO, TBO;
private int count;
public VertexArray(float[] vertices, byte[] indices, float[] color, float[] texture) {
count = indices.length;
// VERTEX ARRAY OBJECT
VAO = glGenVertexArrays();
glBindVertexArray(VAO);
glEnableVertexAttribArray(0);
// VERTEX BUFFER OBJECT
createVertexBufferObject(vertices);
// COLOR BUFFER OBJECT
if (color != null) createColorBufferObject(color);
// TEXTURE BUFFER OBJECT
if (texture != null) createTextureBufferObject(texture);
EBO = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, BufferUtils.createByteBuffer(indices), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
private void createVertexBufferObject(float[] vertices){
VBO = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(vertices), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(0);
}
private void createColorBufferObject(float[] color){
CBO = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, CBO);
glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(color), GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(1);
}
private void createTextureBufferObject(float[] texture){
TBO = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, TBO);
glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(texture), GL_STATIC_DRAW);
glVertexAttribPointer(2, 2, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(2);
}
public void swapVertexBufferObject(float[] vertices){
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(vertices), GL_STATIC_DRAW);
}
public void swapTextureBufferObject(float [] texture){
glBindBuffer(GL_ARRAY_BUFFER, TBO);
glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(texture), GL_STATIC_DRAW);
}
public void bind(){
glBindVertexArray(this.VAO);
}
public void unbind(){
glBindVertexArray(0);
}
public void draw(){
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_BYTE, 0);
}
public void render(){
bind();
draw();
unbind();
}
}

View File

@ -0,0 +1,123 @@
package engine.math;
import engine.utils.BufferUtils;
import java.nio.FloatBuffer;
public class Matrix4f {
public static final int SIZE = 4 * 4;
public float[] elements = new float[4 * 4];
public Matrix4f(){
}
public static Matrix4f identity(){
Matrix4f result = new Matrix4f();
for (int i = 0; i < SIZE; i++){
result.elements[i] = 0.0f;
}
result.elements[0 + 0 * 4] = 1.0f;
result.elements[1 + 1 * 4] = 1.0f;
result.elements[2 + 2 * 4] = 1.0f;
result.elements[3 + 3 * 4] = 1.0f;
return result;
}
public static Matrix4f orthographic(float left, float right, float bottom, float top, float near, float far){
Matrix4f result = identity();
result.elements[0 + 0 * 4] = 2.0f / (right - left);
result.elements[1 + 1 * 4] = 2.0f / (top - bottom);
result.elements[2 + 2 * 4] = 2.0f / (near - far);
result.elements[0 + 3 * 4] = (left + right) / (left - right);
result.elements[1 + 3 * 4] = (bottom + top) / (bottom - top);
result.elements[2 + 3 * 4] = (far + near) / (far - near);
return result;
}
public static Matrix4f translate(Vector3f vector){
Matrix4f result= identity();
result.elements[0 + 3*4] = vector.x;
result.elements[1 + 3*4] = vector.y;
result.elements[2 + 3*4] = vector.z;
return result;
}
public static Matrix4f scale(Vector3f vector){
Matrix4f result= identity();
result.elements[0 + 0*4] = vector.x;
result.elements[1 + 1*4] = vector.y;
result.elements[2 + 2*4] = vector.z;
return result;
}
public static Matrix4f rotateX(float angle){
Matrix4f result = identity();
float r = (float) Math.toRadians(angle);
float cos = (float) Math.cos(r);
float sin = (float) Math.sin(r);
result.elements[1 + 1 * 4] = cos;
result.elements[2 + 1 * 4] = -sin;
result.elements[1 + 2 * 4] = sin;
result.elements[2 + 2 * 4] = cos;
return result;
}
public static Matrix4f rotateY(float angle){
Matrix4f result = identity();
float r = (float) Math.toRadians(angle);
float cos = (float) Math.cos(r);
float sin = (float) Math.sin(r);
result.elements[0 + 0 * 4] = cos;
result.elements[2 + 0 * 4] = sin;
result.elements[0 + 2 * 4] = -sin;
result.elements[2 + 2 * 4] = cos;
return result;
}
public static Matrix4f rotateZ(float angle){
Matrix4f result = identity();
float r = (float) Math.toRadians(angle);
float cos = (float) Math.cos(r);
float sin = (float) Math.sin(r);
result.elements[0 + 0 * 4] = cos;
result.elements[1 + 0 * 4] = -sin;
result.elements[0 + 1 * 4] = sin;
result.elements[1 + 1 * 4] = cos;
return result;
}
public Matrix4f multiply(Matrix4f matrix){
Matrix4f result = new Matrix4f();
for (int y = 0; y< 4; y++){
for (int x = 0; x< 4; x++){
float sum = 0.0f;
for (int e = 0; e< 4; e++){
sum += this.elements[x + e * 4] * matrix.elements[e + y * 4];
}
result.elements[x + y * 4] = sum;
}
}
return result;
}
public FloatBuffer toFloatBuffer() {
return BufferUtils.createFloatBuffer(elements);
}
}

View File

@ -0,0 +1,38 @@
package engine.math;
import engine.math.Vector3f;
public class Primitive {
public static float[] createRectangle(float z, float w, float h){
return new float[] {
0 , 0 , z, // Haut gauche
0 + w, 0 , z, // Haut droit
0 + w, 0 - h, z, // Bas droit
0 , 0 - h, z // Bas gauche
};
}
/**
* Chaque point correspond à un vertex de la primite le reste est interpolé
*/
public static float[] stdTexWrap = new float[] {
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f
};
public static float[] upperHalfTexWrap = new float[] {
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 0.5f,
0.0f, 0.5f
};
public static byte[] rectangle_indices = new byte[] {
0, 1, 3,
1, 2, 3
};
}

View File

@ -0,0 +1,24 @@
package engine.math;
public class Vector3f {
public float x, y, z;
public Vector3f(){
x = 0.0f;
y = 0.0f;
z = 0.0f;
}
public Vector3f(float x, float y, float z){
this.x = x;
this.y = y;
this.z = z;
}
public void divXY(float div){
this.x /= div;
this.y /= div;
}
}

View File

@ -0,0 +1,237 @@
package engine.object;
import engine.graphics.*;
import engine.math.*;
import static org.lwjgl.glfw.GLFW.glfwGetTime;
/**
*
*/
public class ObjectGl {
/**
* STATE CONST DECLARATION
*/
public static final int DEFAULT = 0, STICK_BOTTOM = 1, STICK_TOP = 2;
private int stick_state;
protected VertexArray vertexArray;
protected Shader shader;
protected Matrix4f transform;
/**
* Projection and view matrix are set by the engine do not modify
*/
public static Matrix4f projection;
public static Matrix4f view;
private float zPos;
private float width; // To be used in setTextureWrap
private float height;
private float scalingFactor;
public boolean useTime;
private Texture texture;
/**
* Create a rectangle shape, use setTextureWrap to correctly align the texture with the model
* @param z depth of your model the larger it is the more it will be "close" to the camera
* @param w height of the rectangle
* @param h width of the rectangle
* @param size scaling factor of the rectangle, the model could not show up because this value is too small or too large, a good compromise is between 2 and 15
* @param tex set to null if you don't want a tex on your model
* @param color set to null if you don't want a Color on your model
*/
public ObjectGl(float z, float w, float h, float size, String tex, Vector3f color){
float[] colorBuffer = null;
// Check des options
if (color != null){
colorBuffer = new float[] {
color.x, color.y, color.z,
color.x, color.y, color.z,
color.x, color.y, color.z,
color.x, color.y, color.z
};
}
if (tex != null){
this.texture = new Texture(tex, 0);
}
this.zPos = z;
this.height = h;
this.width = w;
this.vertexArray = new VertexArray(Primitive.createRectangle(this.zPos, this.width, this.height), Primitive.rectangle_indices, colorBuffer, Primitive.stdTexWrap);
this.scalingFactor = size;
this.transform = Matrix4f.identity();
this.scale(new Vector3f(size, size,1f));
this.stick_state = DEFAULT;
this.useTime = false;
// use different shader for each set of option
if (tex == null && color == null){
this.shader = new Shader("shaders/ObjectGl/vert.glsl","shaders/ObjectGl/frag.glsl");
} else if (tex == null){
this.shader = new Shader("shaders/ObjectGlColor/vert.glsl","shaders/ObjectGlColor/frag.glsl");
} else if (color == null){
this.shader = new Shader("shaders/ObjectGlTex/vert.glsl","shaders/ObjectGlTex/frag.glsl");
} else {
this.shader = new Shader("shaders/ObjectGlTexColor/vert.glsl","shaders/ObjectGlTexColor/frag.glsl");
}
}
/**
* Reset the transform matrix, the model will appear at the 0.0.0 coordinate, his scaleFactor will be set to zero
* Because the model is at position 0 on the z axis he will not show up on screen
*/
public void resetTransform(){
this.transform = Matrix4f.identity();
this.scalingFactor = 1;
}
/**
* Move the object according to vec, direction can change if rotation method have been used
* @param vec Vector3f
*/
public void translate(Vector3f vec){
vec.divXY(this.scalingFactor);
this.transform = this.transform.multiply(Matrix4f.translate(vec));
this.zPos += vec.z;
}
/**
* Scale the model with the vec vector, the x component is used to mitigate size modification in the behavior of other transformation method
* @param vec Vector3f
*/
public void scale(Vector3f vec){
this.scalingFactor *= vec.x;
this.transform = this.transform.multiply(Matrix4f.scale(vec));
}
/**
* rotate the model by angle degree on the local x axis, beware this will change the behavior of the translate method
* @param angle in degree
*/
public void rotateX(float angle){
this.transform = this.transform.multiply(Matrix4f.rotateX(angle));
}
/**
* rotate the model by angle degree on the local y axis, beware this will change the behavior of the translate method
* @param angle in degree
*/
public void rotateY(float angle){
this.transform = this.transform.multiply(Matrix4f.rotateY(angle));
}
/**
* rotate the model by angle degree on the local z axis, beware this will change the behavior of the translate method
* @param angle in degree
*/
public void rotateZ(float angle){
this.transform = this.transform.multiply(Matrix4f.rotateZ(angle));
}
/**
* Set a new texture to be used on the model. You may need to use setTextureWrap tp get the correct wrap
* @param texPath path to the new texture
*/
public void setTexture(String texPath){
this.texture = new Texture(texPath, 0);
}
/**
* Change the wrapping coordinate
* @param x starting wrapping on the horizontal axis
* @param y starting wrapping on the vertical axis
* @param w the length of the wrapping on the horizontal axis
* @param h the length of the wrapping on the vertical axis
*/
public void setTextureWrap(float x, float y, float w, float h, int sticky){
// TODO set sticky property + precision issue
if (this.stick_state != sticky){ // Check if we're using a new dimension
if (sticky == STICK_BOTTOM){
this.stick_state = STICK_BOTTOM;
this.translate(new Vector3f(0.0f, (h - this.height)*this.scalingFactor, 0.0f));
} else if (sticky == STICK_TOP){
this.stick_state = STICK_TOP;
this.translate(new Vector3f(0.0f, (h - this.height)*this.scalingFactor, 0.0f));
} else {
this.stick_state = DEFAULT;
}
}
this.height = h;
this.width = w;
this.vertexArray.swapVertexBufferObject(Primitive.createRectangle(this.zPos, w, h));
int texWidth = this.texture.getWidth();
int texHeight = this.texture.getHeight();
x /= texWidth;
w /= texWidth;
y /= texHeight;
h /= texHeight;
float[] result = {
x , y ,
x + w , y ,
x + w , y + h ,
x , y + h ,
};
this.setTextureWrap(result);
}
/**
* Set a new shader to be used by this object
* @param vert path to glsl Vertex Shader
* @param frag path to glsl Fragment Shader
*/
public void setShader(String vert, String frag){
this.shader = new Shader(vert, frag);
}
/**
* Set a new Color for the object if the shader do not use the color attrib this will make no change.
* @param color Vector3f r,g,b format
*/
public void setColor(Vector3f color){
float[] colorBuffer = new float[] {
color.x, color.y, color.z,
color.x, color.y, color.z,
color.x, color.y, color.z,
color.x, color.y, color.z
};
this.vertexArray = new VertexArray(Primitive.createRectangle(this.zPos, this.width, this.height), Primitive.rectangle_indices, colorBuffer, Primitive.stdTexWrap);
}
private void setTextureWrap(float[] texture){
this.vertexArray.swapTextureBufferObject(texture);
}
public float getZPos(){
return zPos;
}
/**
* Do shader binding, texture binding and vertexArray drawing
*/
public void render(){
this.shader.enable();
if (this.texture != null) this.texture.bind();
if (this.useTime) this.shader.setUniform1f("time", (float) glfwGetTime());
this.shader.setUniformMat4f("projection", projection);
this.shader.setUniformMat4f("view", view);
this.shader.setUniformMat4f("transform", this.transform);
this.vertexArray.render();
if (this.texture != null) this.texture.unbind();
this.shader.disable();
}
}

View File

@ -0,0 +1,11 @@
package engine.object;
import java.util.Comparator;
public class SortZ implements Comparator<ObjectGl>
{
public int compare(ObjectGl a, ObjectGl b)
{
return (int) (a.getZPos() - b.getZPos());
}
}

View File

@ -0,0 +1,32 @@
package engine.utils;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
public class BufferUtils {
private BufferUtils() {
}
public static ByteBuffer createByteBuffer(byte[] array){
ByteBuffer result = ByteBuffer.allocateDirect(array.length).order(ByteOrder.nativeOrder());
result.put(array).flip();
return result;
}
public static FloatBuffer createFloatBuffer(float[] array){
FloatBuffer result = ByteBuffer.allocateDirect(array.length << 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
result.put(array).flip();
return result;
}
public static IntBuffer createIntBuffer(int[] array){
IntBuffer result = ByteBuffer.allocateDirect(array.length << 2).order(ByteOrder.nativeOrder()).asIntBuffer();
result.put(array).flip();
return result;
}
}

View File

@ -0,0 +1,29 @@
package engine.utils;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class FileUtils {
private FileUtils() {
}
public static String loadAsString(String file){
StringBuilder result = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(new FileReader(file));
String buffer = "";
while ((buffer = reader.readLine()) != null) {
result.append(buffer +"\n");
}
reader.close();
} catch (IOException e){
e.printStackTrace();
}
return result.toString();
}
}

View File

@ -0,0 +1,60 @@
package engine.utils;
import engine.utils.FileUtils;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;
public class ShaderUtils {
private ShaderUtils(){
}
public static int load(String vertPath, String fragPath){
String vert = FileUtils.loadAsString(vertPath);
String frag = FileUtils.loadAsString(fragPath);
return create(vert, frag);
}
public static int create(String vert, String frag){
// On crée et compile le vertex et le fragment shader
int vertID = glCreateShader(GL_VERTEX_SHADER);
int fragID = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vertID, vert);
glShaderSource(fragID, frag);
glCompileShader(vertID);
if (glGetShaderi(vertID, GL_COMPILE_STATUS) == GL_FALSE){
System.err.println("Failed to compile vertex shader");
System.err.println(glGetShaderInfoLog(vertID));
return -1;
}
glCompileShader(fragID);
if (glGetShaderi(fragID, GL_COMPILE_STATUS) == GL_FALSE){
System.err.println("Failed to compile fragment shader");
System.err.println(glGetShaderInfoLog(fragID));
return -1;
}
//on lie les shaders au programme
int program = glCreateProgram();
glAttachShader(program, vertID);
glAttachShader(program, fragID);
glLinkProgram(program);
if(glGetProgrami(program, GL_LINK_STATUS) == GL_FALSE) {
System.err.println("Failed to link vertex and fragment shader");
System.err.println(glGetShaderInfoLog(program));
return -1;
}
glValidateProgram(program);
glDeleteShader(vertID);
glDeleteShader(fragID);
return program;
}
}

BIN
textures/awesomeface.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
textures/container.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

BIN
textures/zangief_sprite.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB