All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.dabasan.joglf.gl.model.ModelMgr Maven / Gradle / Ivy

There is a newer version: 11.7.0
Show newest version
package com.github.dabasan.joglf.gl.model;

import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.dabasan.basis.matrix.Matrix;
import com.github.dabasan.basis.matrix.MatrixFunctions;
import com.github.dabasan.basis.vector.Vector;
import com.github.dabasan.basis.vector.VectorFunctions;
import com.github.dabasan.joglf.gl.model.buffer.BufferedVertices;
import com.github.dabasan.joglf.gl.shader.ShaderProgram;
import com.github.dabasan.joglf.gl.shape.Triangle;
import com.github.dabasan.joglf.gl.texture.TextureMgr;
import com.github.dabasan.joglf.gl.wrapper.GLWrapper;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.GL;

/**
 * Model manager
 * 
 * @author Daba
 *
 */
public class ModelMgr {
	private final Logger logger = LoggerFactory.getLogger(ModelMgr.class);

	private List buffered_vertices_list;

	private boolean property_updated_flag;

	private IntBuffer indices_vbo;
	private IntBuffer pos_vbo;
	private IntBuffer uv_vbo;
	private IntBuffer norm_vbo;
	private IntBuffer vao;

	private final List programs;

	public ModelMgr(List buffered_vertices_list, FlipVOption option) {
		this.buffered_vertices_list = buffered_vertices_list;

		property_updated_flag = false;

		programs = new ArrayList<>();
		final ShaderProgram program = new ShaderProgram("texture");
		programs.add(program);

		this.GenerateBuffers(option);
	}
	public ModelMgr(List buffered_vertices_list) {
		this(buffered_vertices_list, FlipVOption.MUST_FLIP_VERTICALLY);
	}

	public void AddProgram(ShaderProgram program) {
		programs.add(program);
	}
	public void RemoveAllPrograms() {
		programs.clear();
	}

	public void Interpolate(ModelMgr frame1, ModelMgr frame2, float blend_ratio) {
		final List interpolated_bv_list = new ArrayList<>();
		final List frame1_bv_list = frame1.buffered_vertices_list;
		final List frame2_bv_list = frame2.buffered_vertices_list;

		final int element_num = frame1_bv_list.size();
		for (int i = 0; i < element_num; i++) {
			final BufferedVertices frame1_bv = frame1_bv_list.get(i);
			final BufferedVertices frame2_bv = frame2_bv_list.get(i);

			final BufferedVertices interpolated_bv = BufferedVertices.Interpolate(frame1_bv,
					frame2_bv, blend_ratio);
			interpolated_bv_list.add(interpolated_bv);
		}

		this.buffered_vertices_list = interpolated_bv_list;
	}

	public ModelMgr Copy() {
		final List copied_buffered_vertices_list = new ArrayList<>();

		for (final BufferedVertices buffered_vertices : buffered_vertices_list) {
			final BufferedVertices copied_buffered_vertices = buffered_vertices.Copy();
			copied_buffered_vertices_list.add(copied_buffered_vertices);
		}

		final ModelMgr copied_model = new ModelMgr(copied_buffered_vertices_list);

		return copied_model;
	}

	private void GenerateBuffers(FlipVOption option) {
		final int element_num = buffered_vertices_list.size();
		if (element_num == 0) {
			logger.warn("This model does not contain any elements.");
			return;
		}

		indices_vbo = Buffers.newDirectIntBuffer(element_num);
		pos_vbo = Buffers.newDirectIntBuffer(element_num);
		uv_vbo = Buffers.newDirectIntBuffer(element_num);
		norm_vbo = Buffers.newDirectIntBuffer(element_num);
		vao = Buffers.newDirectIntBuffer(element_num);

		GLWrapper.glGenBuffers(element_num, indices_vbo);
		GLWrapper.glGenBuffers(element_num, pos_vbo);
		GLWrapper.glGenBuffers(element_num, uv_vbo);
		GLWrapper.glGenBuffers(element_num, norm_vbo);
		GLWrapper.glGenVertexArrays(element_num, vao);

		for (int i = 0; i < element_num; i++) {
			final BufferedVertices buffered_vertices = buffered_vertices_list.get(i);

			final FloatBuffer pos_buffer = buffered_vertices.GetPosBuffer();
			final FloatBuffer uv_buffer = buffered_vertices.GetUVBuffer();
			final FloatBuffer norm_buffer = buffered_vertices.GetNormBuffer();

			if (option == FlipVOption.MUST_FLIP_VERTICALLY) {
				final int texture_handle = buffered_vertices.GetTextureHandle();
				final boolean texture_exists = TextureMgr.TextureExists(texture_handle);
				if (texture_exists == true) {
					final boolean must_flip_vertically = TextureMgr
							.GetMustFlipVertically(texture_handle);
					if (must_flip_vertically == true) {
						final int cap = uv_buffer.capacity();

						for (int j = 0; j < cap; j += 2) {
							float v = uv_buffer.get(j + 1);
							v *= (-1.0f);
							uv_buffer.put(j + 1, v);
						}
					}
				}
			} else if (option == FlipVOption.ALL) {
				final int cap = uv_buffer.capacity();

				for (int j = 0; j < cap; j += 2) {
					float v = uv_buffer.get(j + 1);
					v *= (-1.0f);
					uv_buffer.put(j + 1, v);
				}
			}

			GLWrapper.glBindBuffer(GL.GL_ARRAY_BUFFER, pos_vbo.get(i));
			GLWrapper.glBufferData(GL.GL_ARRAY_BUFFER, Buffers.SIZEOF_FLOAT * pos_buffer.capacity(),
					pos_buffer, GL.GL_DYNAMIC_DRAW);
			GLWrapper.glBindBuffer(GL.GL_ARRAY_BUFFER, uv_vbo.get(i));
			GLWrapper.glBufferData(GL.GL_ARRAY_BUFFER, Buffers.SIZEOF_FLOAT * uv_buffer.capacity(),
					uv_buffer, GL.GL_STATIC_DRAW);
			GLWrapper.glBindBuffer(GL.GL_ARRAY_BUFFER, norm_vbo.get(i));
			GLWrapper.glBufferData(GL.GL_ARRAY_BUFFER,
					Buffers.SIZEOF_FLOAT * norm_buffer.capacity(), norm_buffer, GL.GL_DYNAMIC_DRAW);
			GLWrapper.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
		}
		for (int i = 0; i < element_num; i++) {
			final BufferedVertices buffered_vertices = buffered_vertices_list.get(i);
			final IntBuffer indices_buffer = buffered_vertices.GetIndicesBuffer();

			GLWrapper.glBindVertexArray(vao.get(i));

			GLWrapper.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, indices_vbo.get(i));
			GLWrapper.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER,
					Buffers.SIZEOF_INT * indices_buffer.capacity(), indices_buffer,
					GL.GL_STATIC_DRAW);

			GLWrapper.glBindBuffer(GL.GL_ARRAY_BUFFER, pos_vbo.get(i));
			GLWrapper.glEnableVertexAttribArray(0);
			GLWrapper.glVertexAttribPointer(0, 3, GL.GL_FLOAT, false, Buffers.SIZEOF_FLOAT * 3, 0);

			GLWrapper.glBindBuffer(GL.GL_ARRAY_BUFFER, uv_vbo.get(i));
			GLWrapper.glEnableVertexAttribArray(1);
			GLWrapper.glVertexAttribPointer(1, 2, GL.GL_FLOAT, false, Buffers.SIZEOF_FLOAT * 2, 0);

			GLWrapper.glBindBuffer(GL.GL_ARRAY_BUFFER, norm_vbo.get(i));
			GLWrapper.glEnableVertexAttribArray(2);
			GLWrapper.glVertexAttribPointer(2, 3, GL.GL_FLOAT, false, Buffers.SIZEOF_FLOAT * 3, 0);

			GLWrapper.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
			GLWrapper.glBindVertexArray(0);
		}
	}
	private void UpdateBuffers() {
		final int element_num = buffered_vertices_list.size();

		for (int i = 0; i < element_num; i++) {
			final BufferedVertices buffered_vertices = buffered_vertices_list.get(i);

			final FloatBuffer pos_buffer = buffered_vertices.GetPosBuffer();
			final FloatBuffer norm_buffer = buffered_vertices.GetNormBuffer();

			GLWrapper.glBindVertexArray(vao.get(i));

			GLWrapper.glBindBuffer(GL.GL_ARRAY_BUFFER, pos_vbo.get(i));
			GLWrapper.glBufferData(GL.GL_ARRAY_BUFFER, Buffers.SIZEOF_FLOAT * pos_buffer.capacity(),
					pos_buffer, GL.GL_DYNAMIC_DRAW);
			GLWrapper.glBindBuffer(GL.GL_ARRAY_BUFFER, norm_vbo.get(i));
			GLWrapper.glBufferData(GL.GL_ARRAY_BUFFER,
					Buffers.SIZEOF_FLOAT * norm_buffer.capacity(), norm_buffer, GL.GL_DYNAMIC_DRAW);

			GLWrapper.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
			GLWrapper.glBindVertexArray(0);
		}

		property_updated_flag = false;
	}

	public void DeleteBuffers() {
		final int element_num = buffered_vertices_list.size();

		GLWrapper.glDeleteBuffers(element_num, indices_vbo);
		GLWrapper.glDeleteBuffers(element_num, pos_vbo);
		GLWrapper.glDeleteBuffers(element_num, uv_vbo);
		GLWrapper.glDeleteBuffers(element_num, norm_vbo);
		GLWrapper.glDeleteVertexArrays(element_num, vao);

		for (final BufferedVertices buffered_vertices : buffered_vertices_list) {
			final int texture_handle = buffered_vertices.GetTextureHandle();
			TextureMgr.DeleteTexture(texture_handle);
		}
	}

	public void DrawWithProgram(ShaderProgram program, String sampler_name, int texture_unit) {
		if (property_updated_flag == true) {
			this.UpdateBuffers();
		}

		final int element_num = buffered_vertices_list.size();

		program.Enable();

		for (int i = 0; i < element_num; i++) {
			final BufferedVertices buffered_vertices = buffered_vertices_list.get(i);
			final int texture_handle = buffered_vertices.GetTextureHandle();
			final int indices_count = buffered_vertices.GetIndicesCount();

			GLWrapper.glBindVertexArray(vao.get(i));

			program.SetTexture(sampler_name, texture_unit, texture_handle);

			GLWrapper.glEnable(GL.GL_BLEND);
			GLWrapper.glDrawElements(GL.GL_TRIANGLES, indices_count, GL.GL_UNSIGNED_INT, 0);
			GLWrapper.glDisable(GL.GL_BLEND);

			GLWrapper.glBindVertexArray(0);
		}

		program.Disable();
	}
	public void Draw(String sampler_name, int texture_unit) {
		for (final ShaderProgram program : programs) {
			this.DrawWithProgram(program, sampler_name, texture_unit);
		}
	}
	public void Draw() {
		this.Draw("texture_sampler", 0);
	}

	public void Transfer() {
		if (property_updated_flag == true) {
			this.UpdateBuffers();
		}

		final int element_num = buffered_vertices_list.size();

		for (int i = 0; i < element_num; i++) {
			final BufferedVertices buffered_vertices = buffered_vertices_list.get(i);
			final int indices_count = buffered_vertices.GetIndicesCount();

			GLWrapper.glBindVertexArray(vao.get(i));

			GLWrapper.glEnable(GL.GL_BLEND);
			GLWrapper.glDrawElements(GL.GL_TRIANGLES, indices_count, GL.GL_UNSIGNED_INT, 0);
			GLWrapper.glDisable(GL.GL_BLEND);

			GLWrapper.glBindVertexArray(0);
		}
	}

	public int DrawElement(int index, String sampler_name, int texture_unit) {
		if (property_updated_flag == true) {
			this.UpdateBuffers();
		}

		final int element_num = buffered_vertices_list.size();
		if (!(0 <= index && index < element_num)) {
			logger.trace("Index out of bounds. index={}", index);
			return -1;
		}

		for (final ShaderProgram program : programs) {
			program.Enable();

			final BufferedVertices buffered_vertices = buffered_vertices_list.get(index);
			final int texture_handle = buffered_vertices.GetTextureHandle();
			final int indices_count = buffered_vertices.GetIndicesCount();

			GLWrapper.glBindVertexArray(vao.get(index));

			program.SetTexture(sampler_name, texture_unit, texture_handle);

			GLWrapper.glEnable(GL.GL_BLEND);
			GLWrapper.glDrawElements(GL.GL_TRIANGLES, indices_count, GL.GL_UNSIGNED_INT, 0);
			GLWrapper.glDisable(GL.GL_BLEND);

			GLWrapper.glBindVertexArray(0);

			program.Disable();
		}

		return 0;
	}
	public int DrawElement(int index) {
		return this.DrawElement(index, "texture_sampler", 0);
	}

	@Deprecated
	public void DrawElements(String sampler_name, int texture_unit, int bound) {
		if (property_updated_flag == true) {
			this.UpdateBuffers();
		}

		final int element_num = buffered_vertices_list.size();

		int clamped_bound;
		if (bound < 0) {
			clamped_bound = 0;
		} else if (bound < element_num) {
			clamped_bound = bound;
		} else {
			clamped_bound = element_num;
		}

		for (final ShaderProgram program : programs) {
			program.Enable();

			for (int i = 0; i < clamped_bound; i++) {
				final BufferedVertices buffered_vertices = buffered_vertices_list.get(i);
				final int texture_handle = buffered_vertices.GetTextureHandle();
				final int indices_count = buffered_vertices.GetIndicesCount();

				GLWrapper.glBindVertexArray(vao.get(i));

				program.SetTexture(sampler_name, texture_unit, texture_handle);

				GLWrapper.glEnable(GL.GL_BLEND);
				GLWrapper.glDrawElements(GL.GL_TRIANGLES, indices_count, GL.GL_UNSIGNED_INT, 0);
				GLWrapper.glDisable(GL.GL_BLEND);

				GLWrapper.glBindVertexArray(0);
			}

			program.Disable();
		}
	}
	@Deprecated
	public void DrawElements(int bound) {
		this.DrawElements("texture_sampler", 0, bound);
	}

	public int GetElementNum() {
		return buffered_vertices_list.size();
	}

	public void SetMatrix(Matrix m) {
		for (final BufferedVertices buffered_vertices : buffered_vertices_list) {
			final FloatBuffer pos_buffer = buffered_vertices.GetPosBuffer();
			final FloatBuffer norm_buffer = buffered_vertices.GetNormBuffer();

			final int capacity = pos_buffer.capacity();
			for (int i = 0; i < capacity; i += 3) {
				// pos_buffer
				Vector pos = new Vector();
				pos.SetX(pos_buffer.get(i));
				pos.SetY(pos_buffer.get(i + 1));
				pos.SetZ(pos_buffer.get(i + 2));

				pos = MatrixFunctions.VTransform(pos, m);

				pos_buffer.put(i, pos.GetX());
				pos_buffer.put(i + 1, pos.GetY());
				pos_buffer.put(i + 2, pos.GetZ());

				// norm_buffer
				Vector norm = new Vector();
				norm.SetX(norm_buffer.get(i));
				norm.SetY(norm_buffer.get(i + 1));
				norm.SetZ(norm_buffer.get(i + 2));

				norm = MatrixFunctions.VTransformSR(norm, m);
				norm = VectorFunctions.VNorm(norm);

				norm_buffer.put(i, norm.GetX());
				norm_buffer.put(i + 1, norm.GetY());
				norm_buffer.put(i + 2, norm.GetZ());
			}

			buffered_vertices.SetPosBuffer(pos_buffer);
			buffered_vertices.SetNormBuffer(norm_buffer);
		}

		property_updated_flag = true;
	}

	public int ChangeTexture(int material_index, int new_texture_handle) {
		if (!(0 <= material_index && material_index < buffered_vertices_list.size())) {
			logger.warn("Index out of bounds. material_index={}", material_index);
			return -1;
		}

		final BufferedVertices buffered_vertices = buffered_vertices_list.get(material_index);
		buffered_vertices.SetTextureHandle(new_texture_handle);

		return 0;
	}

	public int[] GetTextureHandles() {
		final int element_num = buffered_vertices_list.size();
		final int[] texture_handles = new int[element_num];

		for (int i = 0; i < element_num; i++) {
			texture_handles[i] = buffered_vertices_list.get(i).GetTextureHandle();
		}

		return texture_handles;
	}

	public List GetFaces() {
		final List ret = new ArrayList<>();

		for (final BufferedVertices buffered_vertices : buffered_vertices_list) {
			final IntBuffer indices_buffer = buffered_vertices.GetIndicesBuffer();
			final FloatBuffer pos_buffer = buffered_vertices.GetPosBuffer();
			final FloatBuffer norm_buffer = buffered_vertices.GetNormBuffer();
			final FloatBuffer uv_buffer = buffered_vertices.GetUVBuffer();

			final int indices_count = indices_buffer.capacity();
			final int triangle_num = indices_count / 3;

			for (int i = 0; i < triangle_num; i++) {
				final Triangle triangle = new Triangle();

				for (int j = 0; j < 3; j++) {
					final int index = indices_buffer.get(i * 3 + j);

					final int vec_base_index = index * 3;
					final int uv_base_index = index * 2;

					// pos_buffer
					final Vector pos = new Vector();
					pos.SetX(pos_buffer.get(vec_base_index));
					pos.SetY(pos_buffer.get(vec_base_index + 1));
					pos.SetZ(pos_buffer.get(vec_base_index + 2));

					// norm_buffer
					final Vector norm = new Vector();
					norm.SetX(norm_buffer.get(vec_base_index));
					norm.SetY(norm_buffer.get(vec_base_index + 1));
					norm.SetZ(norm_buffer.get(vec_base_index + 2));

					// uv buffer
					final float u = uv_buffer.get(uv_base_index);
					final float v = uv_buffer.get(uv_base_index + 1);

					triangle.GetVertex(j).SetPos(pos);
					triangle.GetVertex(j).SetNorm(norm);
					triangle.GetVertex(j).SetU(u);
					triangle.GetVertex(j).SetV(v);
				}

				ret.add(triangle);
			}
		}

		return ret;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy