jeu-de-combat/src/engine/object/ObjectGl.java
2021-06-02 23:20:40 +02:00

277 lines
9.1 KiB
Java

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;
/**
* xPos and yPos will stop to be relevant if you use rotate function
*/
private float xPos;
private float yPos;
private float zPos;
private float xAngle;
private float yAngle;
private float zAngle;
private float width; // To be used in setTextureWrap
private float height;
private float scalingFactor;
public boolean useTime;
private Texture texture;
private float[] textureWrap;
/**
* 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.xPos = 0.0f;
this.yPos = 0.0f;
this.zPos = z;
this.height = h;
this.width = w;
this.textureWrap = Primitive.stdTexWrap;
this.vertexArray = new VertexArray(Primitive.createRectangle(this.zPos, this.width, this.height), Primitive.rectangle_indices, colorBuffer, Primitive.stdTexWrap);
this.scalingFactor = 1;
this.transform = Matrix4f.identity();
this.scale(new Vector3f(size, size,1.0f));
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;
this.xPos = 0.0f;
this.yPos = 0.0f;
this.zPos = 0.0f;
}
/**
* Move the object according to vec, direction can change if rotation method have been used
* @param vec Vector3f
*/
public void translate(Vector3f vec){
this.xPos += vec.x;
this.yPos += vec.y;
this.zPos += vec.z;
vec.divXY(this.scalingFactor);
this.transform = this.transform.multiply(Matrix4f.translate(vec));
}
/**
* 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);
}
/**
* Reverse the textureWrap left to right
*/
public void flipTextureWrapH(){
float[] textureWrapTemp = new float[] {
this.textureWrap[2], this.textureWrap[3],
this.textureWrap[0], this.textureWrap[1],
this.textureWrap[6], this.textureWrap[7],
this.textureWrap[4], this.textureWrap[5]
};
setTextureWrap(textureWrapTemp);
}
/**
* 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.textureWrap = texture;
this.vertexArray.swapTextureBufferObject(texture);
}
public float getXPos(){
return xPos;
}
public float getYPos(){
return yPos;
}
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();
}
}