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

de.javagl.jgltf.viewer.GltfRenderData Maven / Gradle / Ivy

/*
 * www.javagl.de - JglTF
 *
 * Copyright 2015-2016 Marco Hutter - http://www.javagl.de
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */
package de.javagl.jgltf.viewer;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.logging.Logger;

import de.javagl.jgltf.model.BufferViewModel;
import de.javagl.jgltf.model.GltfConstants;
import de.javagl.jgltf.model.ImageModel;
import de.javagl.jgltf.model.Optionals;
import de.javagl.jgltf.model.TextureModel;
import de.javagl.jgltf.model.gl.ProgramModel;
import de.javagl.jgltf.model.gl.ShaderModel;
import de.javagl.jgltf.model.image.PixelData;
import de.javagl.jgltf.model.image.PixelDatas;

/**
 * A class maintaining the data for rendering a glTF with OpenGL.
*
* The class offers methods to obtain the GL representations of * {@link ProgramModel}, {@link TextureModel} and {@link BufferViewModel} * objects. These GL representations are the integer values of the * corresponding GL objects, as generated with glCreateProgram, * glGenTextures and glGenBuffers.
*
* The actual creation of these objects will be done lazily when * the objects are requested for the first time. Since the objects * are created using a {@link GlContext}, the methods of this class * may only be called from the OpenGL thread (when the GL context * is current). */ class GltfRenderData { /** * The logger used in this class */ private static final Logger logger = Logger.getLogger(GltfRenderData.class.getName()); /** * The GL vertex array objects */ private final List glVertexArrays; /** * The mapping from glTF {@link ProgramModel} keys to GL programs */ private final Map programModelToGlProgram; /** * The mapping from glTF {@link TextureModel} keys to GL textures */ private final Map textureModelToGlTexture; /** * The mapping from glTF {@link BufferViewModel} keys to GL buffers */ private final Map bufferViewModelToGlBufferView; /** * The {@link GlContext} that will create the GL objects */ private final GlContext glContext; /** * Create the render data that operates on the given {@link GlContext} * * @param glContext The {@link GlContext} */ GltfRenderData(GlContext glContext) { this.glContext = Objects.requireNonNull(glContext, "The glContext may not be null"); this.glVertexArrays = new ArrayList(); this.programModelToGlProgram = new LinkedHashMap(); this.textureModelToGlTexture = new LinkedHashMap(); this.bufferViewModelToGlBufferView = new LinkedHashMap(); } /** * Add the given GL vertex array * * @param glVertexArray The GL vertex array */ void addGlVertexArray(int glVertexArray) { glVertexArrays.add(glVertexArray); } /** * Obtain the OpenGL program for the given glTF {@link ProgramModel}.
*
* If the OpenGL program for the specified program has already been * requested, then the previously created GL program will be returned. * Otherwise, the GL program will be created, stored for later * retrieval, and returned.
*
* If the GL program can not be created (due to missing data, or * due to compile- or link errors), then a warning will be printed * and null will be returned. * * @param programModel The {@link ProgramModel} * @return The GL program */ Integer obtainGlProgram(ProgramModel programModel) { Integer glProgram = programModelToGlProgram.get(programModel); if (glProgram == null) { if (!programModelToGlProgram.containsKey(programModel)) { glProgram = createGlProgram(programModel); programModelToGlProgram.put( programModel, glProgram); } } return glProgram; } /** * Internal method to create the GL program for the given * {@link ProgramModel}. If the GL program can not be created for any * reason, then a warning will be printed and null will * be returned. * * @param programModel The {@link ProgramModel} * @return The GL program */ private Integer createGlProgram(ProgramModel programModel) { logger.fine("Creating GL program for " + programModel); ShaderModel vertexShaderModel = programModel.getVertexShaderModel(); ShaderModel fragmentShaderModel = programModel.getFragmentShaderModel(); Integer glProgram = glContext.createGlProgram( vertexShaderModel.getShaderSource(), fragmentShaderModel.getShaderSource()); if (glProgram != null) { logger.fine("Creating GL program for " + programModel + " DONE"); } else { logger.warning("Creating GL program for " + programModel + " FAILED"); } return glProgram; } /** * Obtain the OpenGL texture for the given glTF {@link TextureModel}.
*
* If the OpenGL texture for the specified texture has already been * requested, then the previously created GL texture will be returned. * Otherwise, the GL texture will be created, stored for later * retrieval, and returned.
*
* If the GL texture can not be created (e.g. due to missing or invalid * image data), then a warning will be printed and an unspecified * placeholder texture will be returned. * * @param textureModel The {@link TextureModel} * @return The GL texture */ Integer obtainGlTexture(TextureModel textureModel) { Integer glTexture = textureModelToGlTexture.get(textureModel); if (glTexture == null) { if (!textureModelToGlTexture.containsKey(textureModel)) { glTexture = createGlTexture(textureModel); textureModelToGlTexture.put( textureModel, glTexture); } } return glTexture; } /** * Internal method to create the GL texture for the given * {@link TextureModel}. If the image data for the texture cannot * be read, then a warning will be printed, and an unspecified * placeholder texture will be returned. * * @param textureModel The {@link TextureModel} key * @return The GL texture */ private Integer createGlTexture(TextureModel textureModel) { logger.fine("Creating GL texture for texture " + textureModel); int internalFormat = GltfConstants.GL_RGBA; int format = GltfConstants.GL_RGBA; int type = GltfConstants.GL_UNSIGNED_BYTE; ImageModel imageModel = textureModel.getImageModel(); ByteBuffer imageData = imageModel.getImageData(); PixelData pixelData = PixelDatas.create(imageData); if (pixelData == null) { logger.warning("Could not extract pixel data from image"); pixelData = PixelDatas.createErrorPixelData(); } int width = pixelData.getWidth(); int height = pixelData.getHeight(); ByteBuffer pixelsRGBA = pixelData.getPixelsRGBA(); int glTexture = glContext.createGlTexture( pixelsRGBA, internalFormat, width, height, format, type); int minFilter = Optionals.of( textureModel.getMinFilter(), GltfConstants.GL_NEAREST_MIPMAP_LINEAR); int magFilter = Optionals.of( textureModel.getMagFilter(), GltfConstants.GL_LINEAR); int wrapS = Optionals.of( textureModel.getWrapS(), GltfConstants.GL_REPEAT); int wrapT = Optionals.of( textureModel.getWrapT(), GltfConstants.GL_REPEAT); glContext.setGlTextureParameters( glTexture, minFilter, magFilter, wrapS, wrapT); logger.fine( "Creating GL texture for texture " + textureModel + " DONE"); return glTexture; } /** * Obtain the OpenGL buffer for the given glTF {@link BufferViewModel}.
*
* If the OpenGL buffer for the specified bufferView has already been * requested, then the previously created GL buffer will be returned. * Otherwise, the GL buffer will be created, stored for later * retrieval, and returned.
*
* If the GL buffer can not be created (e.g. due to missing data), then * a warning will be printed and null will be returned. * * @param bufferViewModel The {@link BufferViewModel} * @return The GL buffer */ Integer obtainGlBufferView(BufferViewModel bufferViewModel) { Objects.requireNonNull(bufferViewModel, "The bufferViewModel may not be null"); Integer glBufferView = bufferViewModelToGlBufferView.get(bufferViewModel); if (glBufferView == null) { if (!bufferViewModelToGlBufferView.containsKey(bufferViewModel)) { glBufferView = createGlBufferView(bufferViewModel); bufferViewModelToGlBufferView.put( bufferViewModel, glBufferView); } } return glBufferView; } /** * Internal method to create the GL buffer for the given * {@link BufferViewModel}. If the GL buffer can not be created for * any reason, then a warning will be printed and null * will be returned. * * @param bufferViewModel The {@link BufferViewModel} * @return The GL buffer */ private Integer createGlBufferView(BufferViewModel bufferViewModel) { logger.fine("Creating GL bufferView for bufferView " + bufferViewModel); Integer byteLength = bufferViewModel.getByteLength(); ByteBuffer bufferViewData = bufferViewModel.getBufferViewData(); int target = Optionals.of( bufferViewModel.getTarget(), GltfConstants.GL_ARRAY_BUFFER); int glBufferView = glContext.createGlBufferView( target, byteLength, bufferViewData.slice()); logger.fine("Creating GL bufferView for bufferView " + bufferViewModel + " DONE"); return glBufferView; } /** * Delete all GL resources that have been created internally. */ void delete() { Collection glTextures = textureModelToGlTexture.values(); for (int glTexture : glTextures) { glContext.deleteGlTexture(glTexture); } Collection glBufferViews = bufferViewModelToGlBufferView.values(); for (int glBufferView : glBufferViews) { glContext.deleteGlBufferView(glBufferView); } Collection glPrograms = programModelToGlProgram.values(); for (int glProgram : glPrograms) { glContext.deleteGlProgram(glProgram); } for (int glVertexArray : glVertexArrays) { glContext.deleteGlVertexArray(glVertexArray); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy