From f5f9178e8ff2e642ddc2daf9e95b1f9d77c81462 Mon Sep 17 00:00:00 2001 From: Riccardo Balbo Date: Tue, 17 Oct 2023 14:49:06 +0200 Subject: [PATCH 1/4] Squashed commit of the following: commit 81fe1e080a1bba8afccc91438122afe3c217a721 Author: riccardobl Date: Sun Apr 3 09:15:45 2022 +0200 fix access to constructor commit ac1d23c191c0b33677d4a60522f9121ececa4be8 Author: riccardobl Date: Sun Apr 3 09:15:18 2022 +0200 Fix shader buffer block managment commit cce6f805348adf8f55ced32b2e75fd86ac9e842d Author: riccardobl Date: Sun Apr 3 09:14:56 2022 +0200 Replace deprecated newInstance, pass exception to runtime exception commit e917c4e5174b2137121aeb6986675a3f79da353a Author: riccardobl Date: Sun Apr 3 09:14:47 2022 +0200 fix sub struct padding commit 2f4e006a78d9b3e4b98eef5089e5885c4d543146 Author: riccardobl Date: Sun Apr 3 09:14:23 2022 +0200 Fix UBO/SSBO rebinding commit 58a371c66967acee7de5325355a8bba53fe5dc71 Author: riccardobl Date: Sun Apr 3 09:14:04 2022 +0200 Ensure fields are final only when exported commit ef7982de9217dab3f95bc6fdcbbe0f846b896f77 Author: riccardobl Date: Tue Mar 8 21:10:07 2022 +0100 Struct based BufferObjects and Std140 layout commit 4797356ae251aa1ac7a281d65bcdf3a12abb168b Author: riccardobl Date: Tue Mar 8 20:49:01 2022 +0100 Improved UBO/SSBO support implemented over generic BufferObjects with glBufferSubData support commit 7f93b64626323d0bf6bee145f39a2e7df664c1ca Author: Riccardo Balbo Date: Thu Apr 2 14:40:41 2020 +0200 Generic BufferObject and memory regions --- .../main/java/com/jme3/material/Material.java | 146 +-- .../java/com/jme3/material/Technique.java | 5 +- .../logic/DefaultTechniqueDefLogic.java | 3 +- .../logic/MultiPassLightingLogic.java | 3 +- .../SinglePassAndImageBasedLightingLogic.java | 7 +- .../logic/SinglePassLightingLogic.java | 3 +- .../logic/StaticPassLightingLogic.java | 3 +- .../material/logic/TechniqueDefLogic.java | 3 +- .../src/main/java/com/jme3/math/FastMath.java | 9 + .../java/com/jme3/renderer/RenderContext.java | 15 + .../main/java/com/jme3/renderer/Renderer.java | 14 +- .../java/com/jme3/renderer/opengl/GL.java | 4 + .../com/jme3/renderer/opengl/GLRenderer.java | 181 +++- .../java/com/jme3/shader/BufferObject.java | 834 ------------------ .../com/jme3/shader/BufferObjectField.java | 77 -- .../com/jme3/shader/ShaderBufferBlock.java | 36 +- .../main/java/com/jme3/shader/Uniform.java | 4 +- .../main/java/com/jme3/shader/VarType.java | 6 +- .../shader/bufferobject/BufferObject.java | 345 ++++++++ .../shader/bufferobject/BufferRegion.java | 149 ++++ .../bufferobject/DirtyRegionsIterator.java | 86 ++ .../bufferobject/layout/BufferLayout.java | 116 +++ .../shader/bufferobject/layout/RawLayout.java | 511 +++++++++++ .../bufferobject/layout/Std140Layout.java | 583 ++++++++++++ .../java/com/jme3/system/NullRenderer.java | 24 +- .../java/com/jme3/util/struct/Struct.java | 12 + .../com/jme3/util/struct/StructField.java | 104 +++ .../util/struct/StructStd140BufferObject.java | 106 +++ .../com/jme3/util/struct/StructUtils.java | 186 ++++ .../util/struct/fields/BooleanArrayField.java | 32 + .../jme3/util/struct/fields/BooleanField.java | 20 + .../struct/fields/ColorRGBAArrayField.java | 33 + .../util/struct/fields/ColorRGBAField.java | 21 + .../util/struct/fields/FloatArrayField.java | 32 + .../jme3/util/struct/fields/FloatField.java | 20 + .../util/struct/fields/IntArrayField.java | 32 + .../com/jme3/util/struct/fields/IntField.java | 20 + .../struct/fields/Matrix3fArrayField.java | 33 + .../util/struct/fields/Matrix3fField.java | 21 + .../struct/fields/Matrix4fArrayField.java | 33 + .../util/struct/fields/Matrix4fField.java | 21 + .../struct/fields/QuaternionArrayField.java | 33 + .../util/struct/fields/QuaternionField.java | 21 + .../struct/fields/SubStructArrayField.java | 33 + .../util/struct/fields/SubStructField.java | 13 + .../struct/fields/Vector2fArrayField.java | 33 + .../util/struct/fields/Vector2fField.java | 21 + .../struct/fields/Vector3fArrayField.java | 33 + .../util/struct/fields/Vector3fField.java | 21 + .../struct/fields/Vector4fArrayField.java | 33 + .../util/struct/fields/Vector4fField.java | 21 + .../test/java/com/jme3/util/StructTest.java | 218 +++++ .../main/java/jme3test/material/TestUBO.java | 149 ++++ .../main/resources/jme3test/ubo/TestUBO.frag | 107 +++ .../main/resources/jme3test/ubo/TestUBO.j3md | 16 + .../main/resources/jme3test/ubo/TestUBO.vert | 7 + 56 files changed, 3603 insertions(+), 1049 deletions(-) delete mode 100644 jme3-core/src/main/java/com/jme3/shader/BufferObject.java delete mode 100644 jme3-core/src/main/java/com/jme3/shader/BufferObjectField.java create mode 100644 jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferObject.java create mode 100644 jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferRegion.java create mode 100644 jme3-core/src/main/java/com/jme3/shader/bufferobject/DirtyRegionsIterator.java create mode 100644 jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/BufferLayout.java create mode 100644 jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/RawLayout.java create mode 100644 jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/Std140Layout.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/Struct.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/StructField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/StructStd140BufferObject.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/StructUtils.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/BooleanArrayField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/BooleanField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/ColorRGBAArrayField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/ColorRGBAField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/FloatArrayField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/FloatField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/IntArrayField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/IntField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix3fArrayField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix3fField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix4fArrayField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix4fField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/QuaternionArrayField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/QuaternionField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/SubStructArrayField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/SubStructField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/Vector2fArrayField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/Vector2fField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/Vector3fArrayField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/Vector3fField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/Vector4fArrayField.java create mode 100644 jme3-core/src/main/java/com/jme3/util/struct/fields/Vector4fField.java create mode 100644 jme3-core/src/test/java/com/jme3/util/StructTest.java create mode 100644 jme3-examples/src/main/java/jme3test/material/TestUBO.java create mode 100644 jme3-examples/src/main/resources/jme3test/ubo/TestUBO.frag create mode 100644 jme3-examples/src/main/resources/jme3test/ubo/TestUBO.j3md create mode 100644 jme3-examples/src/main/resources/jme3test/ubo/TestUBO.vert diff --git a/jme3-core/src/main/java/com/jme3/material/Material.java b/jme3-core/src/main/java/com/jme3/material/Material.java index 1e1d40df36..7940642b6c 100644 --- a/jme3-core/src/main/java/com/jme3/material/Material.java +++ b/jme3-core/src/main/java/com/jme3/material/Material.java @@ -47,6 +47,7 @@ import com.jme3.renderer.queue.RenderQueue.Bucket; import com.jme3.scene.Geometry; import com.jme3.shader.*; +import com.jme3.shader.bufferobject.BufferObject; import com.jme3.texture.Image; import com.jme3.texture.Texture; import com.jme3.texture.image.ColorSpace; @@ -87,6 +88,16 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { private boolean receivesShadows = false; private int sortingId = -1; + /** + * Track bind ids for textures and buffers + * Used internally + */ + public static class BindUnits { + public int textureUnit = 0; + public int bufferUnit = 0; + } + private BindUnits bindUnits = new BindUnits(); + public Material(MaterialDef def) { if (def == null) { throw new IllegalArgumentException("Material definition cannot be null"); @@ -506,6 +517,18 @@ public void setParam(String name, VarType type, Object value) { } } + /** + * Pass a parameter to the material shader. + * + * @param name the name of the parameter defined in the material definition (j3md) + * @param value the value of the parameter + */ + public void setParam(String name, Object value) { + MatParam p = getMaterialDef().getMaterialParam(name); + setParam(name, p.getVarType(), value); + } + + /** * Clear a parameter from this material. The parameter must exist * @param name the name of the parameter to clear @@ -685,8 +708,7 @@ public void setColor(String name, ColorRGBA value) { * @param value the buffer object. */ public void setUniformBufferObject(final String name, final BufferObject value) { - value.setBufferType(BufferObject.BufferType.UniformBufferObject); - setParam(name, VarType.BufferObject, value); + setParam(name, VarType.UniformBufferObject, value); } /** @@ -696,8 +718,7 @@ public void setUniformBufferObject(final String name, final BufferObject value) * @param value the buffer object. */ public void setShaderStorageBufferObject(final String name, final BufferObject value) { - value.setBufferType(BufferObject.BufferType.ShaderStorageBufferObject); - setParam(name, VarType.BufferObject, value); + setParam(name, VarType.ShaderStorageBufferObject, value); } /** @@ -797,7 +818,7 @@ public void selectTechnique(String name, final RenderManager renderManager) { sortingId = -1; } - private int applyOverrides(Renderer renderer, Shader shader, SafeArrayList overrides, int unit) { + private void applyOverrides(Renderer renderer, Shader shader, SafeArrayList overrides, BindUnits bindUnits) { for (MatParamOverride override : overrides.getArray()) { VarType type = override.getVarType(); @@ -810,36 +831,64 @@ private int applyOverrides(Renderer renderer, Shader shader, SafeArrayList worldOverrides, SafeArrayList forcedOverrides) { - int unit = 0; + private void updateShaderMaterialParameter(Renderer renderer, VarType type, Shader shader, MatParam param, BindUnits unit, boolean override) { + if (type == VarType.UniformBufferObject || type == VarType.ShaderStorageBufferObject) { + ShaderBufferBlock bufferBlock = shader.getBufferBlock(param.getPrefixedName()); + BufferObject bufferObject = (BufferObject) param.getValue(); + + ShaderBufferBlock.BufferType btype; + if (type == VarType.ShaderStorageBufferObject) { + btype = ShaderBufferBlock.BufferType.ShaderStorageBufferObject; + bufferBlock.setBufferObject(btype, bufferObject); + renderer.setShaderStorageBufferObject(unit.bufferUnit, bufferObject); // TODO: probably not needed + } else { + btype = ShaderBufferBlock.BufferType.UniformBufferObject; + bufferBlock.setBufferObject(btype, bufferObject); + renderer.setUniformBufferObject(unit.bufferUnit, bufferObject); // TODO: probably not needed + } + unit.bufferUnit++; + } else { + Uniform uniform = shader.getUniform(param.getPrefixedName()); + if (!override && uniform.isSetByCurrentMaterial()) return; + + if (type.isTextureType()) { + try { + renderer.setTexture(unit.textureUnit, (Texture) param.getValue()); + } catch (TextureUnitException exception) { + int numTexParams = unit.textureUnit + 1; + String message = "Too many texture parameters (" + numTexParams + ") assigned\n to " + toString(); + throw new IllegalStateException(message); + } + uniform.setValue(VarType.Int, unit.textureUnit); + unit.textureUnit++; + } else { + uniform.setValue(type, param.getValue()); + } + } + } + + + + + private BindUnits updateShaderMaterialParameters(Renderer renderer, Shader shader, SafeArrayList worldOverrides, + SafeArrayList forcedOverrides) { + + bindUnits.textureUnit = 0; + bindUnits.bufferUnit = 0; + if (worldOverrides != null) { - unit = applyOverrides(renderer, shader, worldOverrides, unit); + applyOverrides(renderer, shader, worldOverrides, bindUnits); } if (forcedOverrides != null) { - unit = applyOverrides(renderer, shader, forcedOverrides, unit); + applyOverrides(renderer, shader, forcedOverrides, bindUnits); } for (int i = 0; i < paramValues.size(); i++) { @@ -847,48 +896,15 @@ private int updateShaderMaterialParameters(Renderer renderer, Shader shader, MatParam param = paramValues.getValue(i); VarType type = param.getVarType(); - if (isBO(type)) { - - final ShaderBufferBlock bufferBlock = shader.getBufferBlock(param.getPrefixedName()); - bufferBlock.setBufferObject((BufferObject) param.getValue()); - - } else { - - Uniform uniform = shader.getUniform(param.getPrefixedName()); - if (uniform.isSetByCurrentMaterial()) { - continue; - } - - if (type.isTextureType()) { - try { - renderer.setTexture(unit, (Texture) param.getValue()); - } catch (TextureUnitException exception) { - int numTexParams = unit + 1; - String message = "Too many texture parameters (" - + numTexParams + ") assigned\n to " + toString(); - throw new IllegalStateException(message); - } - uniform.setValue(VarType.Int, unit); - unit++; - } else { - uniform.setValue(type, param.getValue()); - } - } + updateShaderMaterialParameter(renderer, type, shader, param, bindUnits, false); } - //TODO HACKY HACK remove this when texture unit is handled by the uniform. - return unit; + // TODO HACKY HACK remove this when texture unit is handled by the + // uniform. + return bindUnits; } - /** - * Returns true if the type is Buffer Object's type. - * - * @param type the material parameter type. - * @return true if the type is Buffer Object's type. - */ - private boolean isBO(final VarType type) { - return type == VarType.BufferObject; - } + private void updateRenderState(Geometry geometry, RenderManager renderManager, Renderer renderer, TechniqueDef techniqueDef) { if (renderManager.getForcedRenderState() != null) { @@ -1064,13 +1080,13 @@ public void render(Geometry geometry, LightList lights, RenderManager renderMana renderManager.updateUniformBindings(shader); // Set material parameters - int unit = updateShaderMaterialParameters(renderer, shader, overrides, renderManager.getForcedMatParams()); + BindUnits units = updateShaderMaterialParameters(renderer, shader, overrides, renderManager.getForcedMatParams()); // Clear any uniforms not changed by material. resetUniformsNotSetByCurrent(shader); // Delegate rendering to the technique - technique.render(renderManager, shader, geometry, lights, unit); + technique.render(renderManager, shader, geometry, lights, units); } /** diff --git a/jme3-core/src/main/java/com/jme3/material/Technique.java b/jme3-core/src/main/java/com/jme3/material/Technique.java index 667594f09c..58e8cd6896 100644 --- a/jme3-core/src/main/java/com/jme3/material/Technique.java +++ b/jme3-core/src/main/java/com/jme3/material/Technique.java @@ -33,6 +33,7 @@ import com.jme3.asset.AssetManager; import com.jme3.light.LightList; +import com.jme3.material.Material.BindUnits; import com.jme3.material.TechniqueDef.LightMode; import com.jme3.material.logic.TechniqueDefLogic; import com.jme3.renderer.Caps; @@ -162,9 +163,9 @@ Shader makeCurrent(RenderManager renderManager, SafeArrayList * @param lights Lights which influence the geometry. * @param lastTexUnit the index of the most recently used texture unit */ - void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) { + void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, BindUnits lastBindUnits) { TechniqueDefLogic logic = def.getLogic(); - logic.render(renderManager, shader, geometry, lights, lastTexUnit); + logic.render(renderManager, shader, geometry, lights, lastBindUnits); } /** diff --git a/jme3-core/src/main/java/com/jme3/material/logic/DefaultTechniqueDefLogic.java b/jme3-core/src/main/java/com/jme3/material/logic/DefaultTechniqueDefLogic.java index 9bb317219f..9c5636c2ac 100644 --- a/jme3-core/src/main/java/com/jme3/material/logic/DefaultTechniqueDefLogic.java +++ b/jme3-core/src/main/java/com/jme3/material/logic/DefaultTechniqueDefLogic.java @@ -34,6 +34,7 @@ import com.jme3.asset.AssetManager; import com.jme3.light.*; import com.jme3.material.TechniqueDef; +import com.jme3.material.Material.BindUnits; import com.jme3.math.ColorRGBA; import com.jme3.renderer.Caps; import com.jme3.renderer.RenderManager; @@ -91,7 +92,7 @@ protected static ColorRGBA getAmbientColor(LightList lightList, boolean removeLi @Override - public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) { + public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, BindUnits lastBindUnits) { Renderer renderer = renderManager.getRenderer(); renderer.setShader(shader); renderMeshFromGeometry(renderer, geometry); diff --git a/jme3-core/src/main/java/com/jme3/material/logic/MultiPassLightingLogic.java b/jme3-core/src/main/java/com/jme3/material/logic/MultiPassLightingLogic.java index d5c48b1df9..10774c0ef0 100644 --- a/jme3-core/src/main/java/com/jme3/material/logic/MultiPassLightingLogic.java +++ b/jme3-core/src/main/java/com/jme3/material/logic/MultiPassLightingLogic.java @@ -38,6 +38,7 @@ import com.jme3.light.SpotLight; import com.jme3.material.RenderState; import com.jme3.material.TechniqueDef; +import com.jme3.material.Material.BindUnits; import com.jme3.math.ColorRGBA; import com.jme3.math.Quaternion; import com.jme3.math.Vector3f; @@ -67,7 +68,7 @@ public MultiPassLightingLogic(TechniqueDef techniqueDef) { } @Override - public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) { + public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, BindUnits lastBindUnits) { Renderer r = renderManager.getRenderer(); Uniform lightDir = shader.getUniform("g_LightDirection"); Uniform lightColor = shader.getUniform("g_LightColor"); diff --git a/jme3-core/src/main/java/com/jme3/material/logic/SinglePassAndImageBasedLightingLogic.java b/jme3-core/src/main/java/com/jme3/material/logic/SinglePassAndImageBasedLightingLogic.java index 801d5b7837..d9921298d6 100644 --- a/jme3-core/src/main/java/com/jme3/material/logic/SinglePassAndImageBasedLightingLogic.java +++ b/jme3-core/src/main/java/com/jme3/material/logic/SinglePassAndImageBasedLightingLogic.java @@ -34,6 +34,7 @@ import com.jme3.asset.AssetManager; import com.jme3.light.*; import com.jme3.material.*; +import com.jme3.material.Material.BindUnits; import com.jme3.material.RenderState.BlendMode; import com.jme3.math.*; import com.jme3.renderer.*; @@ -262,17 +263,17 @@ private int setProbeData(RenderManager rm, int lastTexUnit, Uniform lightProbeDa } @Override - public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) { + public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, BindUnits lastBindUnits) { int nbRenderedLights = 0; Renderer renderer = renderManager.getRenderer(); int batchSize = renderManager.getSinglePassLightBatchSize(); if (lights.size() == 0) { - updateLightListUniforms(shader, geometry, lights,batchSize, renderManager, 0, lastTexUnit); + updateLightListUniforms(shader, geometry, lights, batchSize, renderManager, 0, lastBindUnits.textureUnit); renderer.setShader(shader); renderMeshFromGeometry(renderer, geometry); } else { while (nbRenderedLights < lights.size()) { - nbRenderedLights = updateLightListUniforms(shader, geometry, lights, batchSize, renderManager, nbRenderedLights, lastTexUnit); + nbRenderedLights = updateLightListUniforms(shader, geometry, lights, batchSize, renderManager, nbRenderedLights, lastBindUnits.textureUnit); renderer.setShader(shader); renderMeshFromGeometry(renderer, geometry); } diff --git a/jme3-core/src/main/java/com/jme3/material/logic/SinglePassLightingLogic.java b/jme3-core/src/main/java/com/jme3/material/logic/SinglePassLightingLogic.java index a9b51783c2..dd6cd9c385 100644 --- a/jme3-core/src/main/java/com/jme3/material/logic/SinglePassLightingLogic.java +++ b/jme3-core/src/main/java/com/jme3/material/logic/SinglePassLightingLogic.java @@ -40,6 +40,7 @@ import com.jme3.material.RenderState; import com.jme3.material.RenderState.BlendMode; import com.jme3.material.TechniqueDef; +import com.jme3.material.Material.BindUnits; import com.jme3.math.ColorRGBA; import com.jme3.math.Vector3f; import com.jme3.math.Vector4f; @@ -206,7 +207,7 @@ protected int updateLightListUniforms(Shader shader, Geometry g, LightList light } @Override - public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) { + public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, BindUnits lastBindUnits) { int nbRenderedLights = 0; Renderer renderer = renderManager.getRenderer(); int batchSize = renderManager.getSinglePassLightBatchSize(); diff --git a/jme3-core/src/main/java/com/jme3/material/logic/StaticPassLightingLogic.java b/jme3-core/src/main/java/com/jme3/material/logic/StaticPassLightingLogic.java index 5afee8f4b0..516ee202bd 100644 --- a/jme3-core/src/main/java/com/jme3/material/logic/StaticPassLightingLogic.java +++ b/jme3-core/src/main/java/com/jme3/material/logic/StaticPassLightingLogic.java @@ -38,6 +38,7 @@ import com.jme3.light.PointLight; import com.jme3.light.SpotLight; import com.jme3.material.TechniqueDef; +import com.jme3.material.Material.BindUnits; import com.jme3.math.ColorRGBA; import com.jme3.math.Matrix4f; import com.jme3.math.Vector3f; @@ -171,7 +172,7 @@ private void updateLightListUniforms(Matrix4f viewMatrix, Shader shader, LightLi } @Override - public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) { + public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, BindUnits lastBindUnits) { Renderer renderer = renderManager.getRenderer(); Matrix4f viewMatrix = renderManager.getCurrentCamera().getViewMatrix(); updateLightListUniforms(viewMatrix, shader, lights); diff --git a/jme3-core/src/main/java/com/jme3/material/logic/TechniqueDefLogic.java b/jme3-core/src/main/java/com/jme3/material/logic/TechniqueDefLogic.java index d021d28d0f..de43c22b6e 100644 --- a/jme3-core/src/main/java/com/jme3/material/logic/TechniqueDefLogic.java +++ b/jme3-core/src/main/java/com/jme3/material/logic/TechniqueDefLogic.java @@ -33,6 +33,7 @@ import com.jme3.asset.AssetManager; import com.jme3.light.LightList; +import com.jme3.material.Material.BindUnits; import com.jme3.renderer.Caps; import com.jme3.renderer.RenderManager; import com.jme3.scene.Geometry; @@ -92,5 +93,5 @@ public Shader makeCurrent(AssetManager assetManager, RenderManager renderManager * @param lights Lights which influence the geometry. * @param lastTexUnit the index of the most recently used texture unit */ - public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit); + public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, BindUnits lastBindUnits); } diff --git a/jme3-core/src/main/java/com/jme3/math/FastMath.java b/jme3-core/src/main/java/com/jme3/math/FastMath.java index 712e322e30..c32f31174c 100644 --- a/jme3-core/src/main/java/com/jme3/math/FastMath.java +++ b/jme3-core/src/main/java/com/jme3/math/FastMath.java @@ -1135,4 +1135,13 @@ public static short convertFloatToHalf(float flt) { public static float unInterpolateLinear(float value, float min, float max) { return (value - min) / (max - min); } + + /** + * Round n to a multiple of p + */ + public static int toMultipleOf(int n, int p) { + return ((n - 1) | (p - 1)) + 1; + } + + } diff --git a/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java b/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java index 7fb60e7322..4d8b9c4e1a 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java +++ b/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java @@ -38,6 +38,7 @@ import com.jme3.texture.FrameBuffer; import com.jme3.texture.Image; import java.lang.ref.WeakReference; +import com.jme3.shader.bufferobject.BufferObject; /** * Represents the current state of the graphics library. This class is used @@ -49,6 +50,11 @@ public class RenderContext { */ public static final int maxTextureUnits = 16; + /** + * Number of buffer object units that JME supports. + */ + public static final int maxBufferObjectUnits = 8; + /** * Criteria for culling faces. * @@ -256,6 +262,15 @@ public class RenderContext { public final WeakReference boundTextures[] = new WeakReference[maxTextureUnits]; + + /** + * Current bound buffer object IDs for each buffer object unit. + * + * @see Renderer#setUniformBufferObject(int, com.jme3.shader.BufferObject) + * @see Renderer#setShaderStorageBufferObject(int, com.jme3.shader.BufferObject) + */ + public final WeakReference[] boundBO = new WeakReference[maxBufferObjectUnits]; + /** * IDList for texture units. * diff --git a/jme3-core/src/main/java/com/jme3/renderer/Renderer.java b/jme3-core/src/main/java/com/jme3/renderer/Renderer.java index 63e49f030b..9dcb038f2a 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/Renderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/Renderer.java @@ -35,7 +35,7 @@ import com.jme3.math.ColorRGBA; import com.jme3.scene.Mesh; import com.jme3.scene.VertexBuffer; -import com.jme3.shader.BufferObject; +import com.jme3.shader.bufferobject.BufferObject; import com.jme3.shader.Shader; import com.jme3.shader.Shader.ShaderSource; import com.jme3.system.AppSettings; @@ -306,8 +306,15 @@ public void setTexture(int unit, Texture tex) * * @param bo the buffer object to upload. */ - public void updateBufferData(BufferObject bo); + public void updateShaderStorageBufferObjectData(BufferObject bo); + /** + * Uploads data of the buffer object on the GPU. + * + * @param bo the buffer object to upload. + */ + public void updateUniformBufferObjectData(BufferObject bo); + /** * Deletes a vertex buffer from the GPU. * @@ -533,4 +540,7 @@ public default void pushDebugGroup(String name) { */ public FrameBuffer getCurrentFrameBuffer(); + public void setShaderStorageBufferObject(int bindingPoint, BufferObject bufferObject) ; + public void setUniformBufferObject(int bindingPoint, BufferObject bufferObject) ; + } diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java index ff23e8a02d..797f8a27ba 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java @@ -68,6 +68,7 @@ public interface GL { public static final int GL_DST_COLOR = 0x306; public static final int GL_DYNAMIC_DRAW = 0x88E8; public static final int GL_DYNAMIC_COPY = 0x88EA; + public static final int GL_DYNAMIC_READ = 0x88E9; public static final int GL_ELEMENT_ARRAY_BUFFER = 0x8893; public static final int GL_EQUAL = 0x202; public static final int GL_EXTENSIONS = 0x1F03; @@ -148,10 +149,13 @@ public interface GL { public static final int GL_SRC_ALPHA_SATURATE = 0x0308; public static final int GL_SRC_COLOR = 0x300; public static final int GL_STATIC_DRAW = 0x88E4; + public static final int GL_STATIC_READ = 0x88E5; + public static final int GL_STATIC_COPY = 0x88E6; public static final int GL_STENCIL_BUFFER_BIT = 0x400; public static final int GL_STENCIL_TEST = 0xB90; public static final int GL_STREAM_DRAW = 0x88E0; public static final int GL_STREAM_READ = 0x88E1; + public static final int GL_STREAM_COPY = 0x88E2; public static final int GL_TEXTURE = 0x1702; public static final int GL_TEXTURE0 = 0x84C0; public static final int GL_TEXTURE1 = 0x84C1; diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index c3dbc1e118..f9aa2203bd 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -50,6 +50,10 @@ import com.jme3.shader.Shader.ShaderType; import com.jme3.system.JmeSystem; import com.jme3.system.Platform; +import com.jme3.shader.ShaderBufferBlock.BufferType; +import com.jme3.shader.bufferobject.BufferObject; +import com.jme3.shader.bufferobject.BufferRegion; +import com.jme3.shader.bufferobject.DirtyRegionsIterator; import com.jme3.texture.FrameBuffer; import com.jme3.texture.FrameBuffer.RenderBuffer; import com.jme3.texture.Image; @@ -61,7 +65,9 @@ import com.jme3.util.BufferUtils; import com.jme3.util.ListMap; import com.jme3.util.MipMapGenerator; +import com.jme3.util.NativeObject; import com.jme3.util.NativeObjectManager; + import jme3tools.shader.ShaderDebug; import java.lang.ref.WeakReference; @@ -1445,44 +1451,55 @@ protected void updateShaderBufferBlock(final Shader shader, final ShaderBufferBl assert shader.getId() > 0; final BufferObject bufferObject = bufferBlock.getBufferObject(); - if (bufferObject.getUniqueId() == -1 || bufferObject.isUpdateNeeded()) { - updateBufferData(bufferObject); - } + final BufferType bufferType = bufferBlock.getType(); + - if (!bufferBlock.isUpdateNeeded()) { - return; + if (bufferObject.isUpdateNeeded()) { + if (bufferType == BufferType.ShaderStorageBufferObject) { + updateShaderStorageBufferObjectData(bufferObject); + } else { + updateUniformBufferObjectData(bufferObject); + } } + int usage = resolveUsageHint(bufferObject.getAccessHint(), bufferObject.getNatureHint()); + if (usage == -1) return; // cpu only + bindProgram(shader); final int shaderId = shader.getId(); - final BufferObject.BufferType bufferType = bufferObject.getBufferType(); - bindBuffer(bufferBlock, bufferObject, shaderId, bufferType); - - bufferBlock.clearUpdateNeeded(); - } - - private void bindBuffer(final ShaderBufferBlock bufferBlock, final BufferObject bufferObject, final int shaderId, - final BufferObject.BufferType bufferType) { + int bindingPoint = bufferObject.getBinding(); switch (bufferType) { case UniformBufferObject: { - final int blockIndex = gl3.glGetUniformBlockIndex(shaderId, bufferBlock.getName()); - gl3.glBindBufferBase(GL3.GL_UNIFORM_BUFFER, bufferObject.getBinding(), bufferObject.getId()); - gl3.glUniformBlockBinding(GL3.GL_UNIFORM_BUFFER, blockIndex, bufferObject.getBinding()); + setUniformBufferObject(bindingPoint, bufferObject); // rebind buffer if needed + if (bufferBlock.isUpdateNeeded()) { + int blockIndex = gl3.glGetUniformBlockIndex(shaderId, bufferBlock.getName()); + bufferBlock.setLocation(blockIndex); + if (bufferBlock.getLocation() != NativeObject.INVALID_ID) { + gl3.glUniformBlockBinding(shaderId, bufferBlock.getLocation(), bindingPoint); + } + } break; } case ShaderStorageBufferObject: { - final int blockIndex = gl4.glGetProgramResourceIndex(shaderId, GL4.GL_SHADER_STORAGE_BLOCK, bufferBlock.getName()); - gl4.glShaderStorageBlockBinding(shaderId, blockIndex, bufferObject.getBinding()); - gl4.glBindBufferBase(GL4.GL_SHADER_STORAGE_BUFFER, bufferObject.getBinding(), bufferObject.getId()); + setShaderStorageBufferObject(bindingPoint, bufferObject); // rebind buffer if needed + if (bufferBlock.isUpdateNeeded() ) { + int blockIndex = gl4.glGetProgramResourceIndex(shaderId, GL4.GL_SHADER_STORAGE_BLOCK, bufferBlock.getName()); + bufferBlock.setLocation(blockIndex); + if (bufferBlock.getLocation() != NativeObject.INVALID_ID) { + gl4.glShaderStorageBlockBinding(shaderId, bufferBlock.getLocation(), bindingPoint); + } + } break; } default: { throw new IllegalArgumentException("Doesn't support binding of " + bufferType); } } + + bufferBlock.clearUpdateNeeded(); } protected void updateShaderUniforms(Shader shader) { @@ -2730,6 +2747,34 @@ public void setTexture(int unit, Texture tex) throws TextureUnitException { } } + @Override + public void setUniformBufferObject(int bindingPoint, BufferObject bufferObject) { + if (bufferObject.isUpdateNeeded()) { + updateUniformBufferObjectData(bufferObject); + } + + if (context.boundBO[bindingPoint] == null || context.boundBO[bindingPoint].get() != bufferObject) { + gl3.glBindBufferBase(GL3.GL_UNIFORM_BUFFER, bindingPoint, bufferObject.getId()); + bufferObject.setBinding(bindingPoint); + context.boundBO[bindingPoint] = bufferObject.getWeakRef(); + } + + bufferObject.setBinding(bindingPoint); + + } + + @Override + public void setShaderStorageBufferObject(int bindingPoint, BufferObject bufferObject) { + if (bufferObject.isUpdateNeeded()) { + updateShaderStorageBufferObjectData(bufferObject); + } + if (context.boundBO[bindingPoint] == null || context.boundBO[bindingPoint].get() != bufferObject) { + gl4.glBindBufferBase(GL4.GL_SHADER_STORAGE_BUFFER, bindingPoint, bufferObject.getId()); + bufferObject.setBinding(bindingPoint); + context.boundBO[bindingPoint] = bufferObject.getWeakRef(); + } + bufferObject.setBinding(bindingPoint); + } /** * @deprecated Use modifyTexture(Texture2D dest, Image src, int destX, int destY, int srcX, int srcY, int areaW, int areaH) @@ -2897,23 +2942,63 @@ public void updateBufferData(VertexBuffer vb) { vb.clearUpdateNeeded(); } - @Override - public void updateBufferData(final BufferObject bo) { - - int maxSize = Integer.MAX_VALUE; + private int resolveUsageHint(BufferObject.AccessHint ah, BufferObject.NatureHint nh) { + switch (ah) { + case Dynamic: { + switch (nh) { + case Draw: + return GL.GL_DYNAMIC_DRAW; + case Read: + return GL4.GL_DYNAMIC_READ; + case Copy: + return GL.GL_DYNAMIC_COPY; + } + } + case Stream: { + switch (nh) { + case Draw: + return GL.GL_STREAM_DRAW; + case Read: + return GL.GL_STREAM_READ; + case Copy: + return GL.GL_STREAM_COPY; + } + } + case Static: { + switch (nh) { + case Draw: + return GL.GL_STATIC_DRAW; + case Read: + return GL.GL_STATIC_READ; + case Copy: + return GL.GL_STATIC_COPY; + } + } + default: + } + return -1; + } - final BufferObject.BufferType bufferType = bo.getBufferType(); + @Override + public void updateShaderStorageBufferObjectData(BufferObject bo) { + if (!caps.contains(Caps.ShaderStorageBufferObject)) throw new IllegalArgumentException("The current video hardware doesn't support shader storage buffer objects "); + updateBufferData(GL4.GL_SHADER_STORAGE_BUFFER, bo); + } - if (!caps.contains(bufferType.getRequiredCaps())) { - throw new IllegalArgumentException("The current video hardware doesn't support " + bufferType); - } + @Override + public void updateUniformBufferObjectData(BufferObject bo) { + if (!caps.contains(Caps.UniformBufferObject)) throw new IllegalArgumentException("The current video hardware doesn't support uniform buffer objects"); + updateBufferData(GL4.GL_UNIFORM_BUFFER, bo); + } - final ByteBuffer data = bo.computeData(maxSize); - if (data == null) { - throw new IllegalArgumentException("Can't upload BO without data."); + private void updateBufferData(int type, BufferObject bo) { + int bufferId = bo.getId(); + int usage = resolveUsageHint(bo.getAccessHint(), bo.getNatureHint()); + if (usage == -1) { + deleteBuffer(bo); + return; // CpuOnly } - int bufferId = bo.getId(); if (bufferId == -1) { // create buffer @@ -2926,26 +3011,28 @@ public void updateBufferData(final BufferObject bo) { objManager.registerObject(bo); } - data.rewind(); + DirtyRegionsIterator it = bo.getDirtyRegions(); + BufferRegion reg; - switch (bufferType) { - case UniformBufferObject: { - gl3.glBindBuffer(GL3.GL_UNIFORM_BUFFER, bufferId); - gl3.glBufferData(GL4.GL_UNIFORM_BUFFER, data, GL3.GL_DYNAMIC_DRAW); - gl3.glBindBuffer(GL4.GL_UNIFORM_BUFFER, 0); - break; - } - case ShaderStorageBufferObject: { - gl4.glBindBuffer(GL4.GL_SHADER_STORAGE_BUFFER, bufferId); - gl4.glBufferData(GL4.GL_SHADER_STORAGE_BUFFER, data, GL4.GL_DYNAMIC_COPY); - gl4.glBindBuffer(GL4.GL_SHADER_STORAGE_BUFFER, 0); + while ((reg = it.getNext()) != null) { + gl3.glBindBuffer(type, bufferId); + if (reg.isFullBufferRegion()) { + ByteBuffer bbf = bo.getData(); + if (logger.isLoggable(java.util.logging.Level.FINER)) { + logger.log(java.util.logging.Level.FINER, "Update full buffer {0} with {1} bytes", new Object[] { bo, bbf.remaining() }); + } + gl.glBufferData(type, bbf, usage); + gl3.glBindBuffer(type, 0); break; + } else { + if (logger.isLoggable(java.util.logging.Level.FINER)) { + logger.log(java.util.logging.Level.FINER, "Update region {0} of {1}", new Object[] { reg, bo }); + } + gl.glBufferSubData(type, reg.getStart(), reg.getData()); + gl3.glBindBuffer(type, 0); } - default: { - throw new IllegalArgumentException("Doesn't support binding of " + bufferType); - } + reg.clearDirty(); } - bo.clearUpdateNeeded(); } diff --git a/jme3-core/src/main/java/com/jme3/shader/BufferObject.java b/jme3-core/src/main/java/com/jme3/shader/BufferObject.java deleted file mode 100644 index b893576a87..0000000000 --- a/jme3-core/src/main/java/com/jme3/shader/BufferObject.java +++ /dev/null @@ -1,834 +0,0 @@ -package com.jme3.shader; - -import com.jme3.math.*; -import com.jme3.renderer.Caps; -import com.jme3.renderer.Renderer; -import com.jme3.util.BufferUtils; -import com.jme3.util.NativeObject; -import com.jme3.util.SafeArrayList; - -import java.nio.ByteBuffer; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * The base implementation of BO. - * - * @author JavaSaBr - */ -public class BufferObject extends NativeObject { - - private static final Map, VarType> CLASS_TO_VAR_TYPE = new HashMap<>(); - - static { - CLASS_TO_VAR_TYPE.put(Float.class, VarType.Float); - CLASS_TO_VAR_TYPE.put(Integer.class, VarType.Int); - CLASS_TO_VAR_TYPE.put(Boolean.class, VarType.Boolean); - CLASS_TO_VAR_TYPE.put(Vector2f.class, VarType.Vector2); - CLASS_TO_VAR_TYPE.put(Vector3f.class, VarType.Vector3); - CLASS_TO_VAR_TYPE.put(ColorRGBA.class, VarType.Vector4); - CLASS_TO_VAR_TYPE.put(Quaternion.class, VarType.Vector4); - CLASS_TO_VAR_TYPE.put(Vector4f.class, VarType.Vector4); - - CLASS_TO_VAR_TYPE.put(Vector2f[].class, VarType.Vector2Array); - CLASS_TO_VAR_TYPE.put(Vector3f[].class, VarType.Vector3Array); - CLASS_TO_VAR_TYPE.put(Vector4f[].class, VarType.Vector4Array); - CLASS_TO_VAR_TYPE.put(ColorRGBA[].class, VarType.Vector4Array); - CLASS_TO_VAR_TYPE.put(Quaternion[].class, VarType.Vector4Array); - - CLASS_TO_VAR_TYPE.put(Matrix3f.class, VarType.Matrix3); - CLASS_TO_VAR_TYPE.put(Matrix4f.class, VarType.Matrix4); - CLASS_TO_VAR_TYPE.put(Matrix3f[].class, VarType.Matrix3Array); - CLASS_TO_VAR_TYPE.put(Matrix4f[].class, VarType.Matrix4Array); - } - - protected static VarType getVarTypeByValue(final Object value) { - - final VarType varType = CLASS_TO_VAR_TYPE.get(value.getClass()); - if (varType != null) { - return varType; - } else if (value instanceof Collection && ((Collection) value).isEmpty()) { - throw new IllegalArgumentException("Can't calculate a var type for the empty collection value[" + value + "]."); - } else if (value instanceof List) { - return getVarTypeByValue(((List) value).get(0)); - } else if (value instanceof Collection) { - return getVarTypeByValue(((Collection) value).iterator().next()); - } - - throw new IllegalArgumentException("Can't calculate a var type for the value " + value); - } - - public enum Layout { - std140, - /** unsupported yet */ - @Deprecated - std430, - } - - public enum BufferType { - ShaderStorageBufferObject(Caps.ShaderStorageBufferObject), - UniformBufferObject(Caps.UniformBufferObject), - ; - - private final Caps requiredCaps; - - BufferType(final Caps requiredCaps) { - this.requiredCaps = requiredCaps; - } - - /** - * Get the required caps. - * - * @return the required caps. - */ - public Caps getRequiredCaps() { - return requiredCaps; - } - } - - /** - * The fields of this BO. - */ - private final Map fields; - - /** - * The field's array. - */ - private final SafeArrayList fieldArray; - - /** - * The buffer's data layout. - */ - private final Layout layout; - - /** - * The binding number. - */ - private final int binding; - - /** - * The buffer's type. - */ - private BufferType bufferType; - - /** - * The previous data buffer. - */ - private ByteBuffer previousData; - - public BufferObject(final int binding, final Layout layout, final BufferType bufferType) { - this.handleRef = new Object(); - this.bufferType = bufferType; - this.binding = binding; - this.layout = layout; - this.fields = new HashMap<>(); - this.fieldArray = new SafeArrayList<>(BufferObjectField.class); - } - - public BufferObject(final int binding, final Layout layout) { - this(binding, layout, BufferType.UniformBufferObject); - } - - public BufferObject(final int binding, final BufferType bufferType) { - this(binding, Layout.std140, bufferType); - } - - public BufferObject(final BufferType bufferType) { - this(1, Layout.std140, bufferType); - } - - public BufferObject(final Layout layout) { - this(1, layout, BufferType.UniformBufferObject); - } - - public BufferObject(final int binding) { - this(binding, Layout.std140, BufferType.UniformBufferObject); - } - - public BufferObject() { - this(1, Layout.std140, BufferType.UniformBufferObject); - } - - private BufferObject(final Void unused, final int id) { - super(id); - this.fieldArray = null; - this.fields = null; - this.layout = null; - this.binding = 0; - } - - /** - * Declares a filed in this BO. - * - * @param name the field's name. - * @param varType the field's type. - */ - public void declareField(final String name, final VarType varType) { - - if (fields.containsKey(name)) { - throw new IllegalArgumentException("The field " + name + " is already declared."); - } - - final BufferObjectField field = new BufferObjectField(name, varType); - - fields.put(name, field); - fieldArray.add(field); - } - - /** - * Gets the buffer's type. - * - * @return the buffer's type. - */ - public BufferType getBufferType() { - return bufferType; - } - - /** - * Sets the buffer's type. - * - * @param bufferType the buffer's type. - */ - public void setBufferType(final BufferType bufferType) { - - if (getId() != -1) { - throw new IllegalStateException("Can't change buffer's type when this buffer is already initialized."); - } - - this.bufferType = bufferType; - } - - /** - * Sets the value to the filed by the field's name. - * - * @param name the field's name. - * @param value the value. - */ - public void setFieldValue(final String name, final Object value) { - - BufferObjectField field = fields.get(name); - - if (field == null) { - declareField(name, getVarTypeByValue(value)); - field = fields.get(name); - } - - field.setValue(value); - setUpdateNeeded(); - } - - /** - * Gets the current value of the field by the name. - * - * @param name the field name. - * @param the value's type. - * @return the current value. - */ - @SuppressWarnings("unchecked") - public T getFieldValue(final String name) { - - final BufferObjectField field = fields.get(name); - if (field == null) { - throw new IllegalArgumentException("Unknown a field with the name " + name); - } - - return (T) field.getValue(); - } - - /** - * Get the binding number. - * - * @return the binding number. - */ - public int getBinding() { - return binding; - } - - @Override - public void resetObject() { - this.id = -1; - setUpdateNeeded(); - } - - /** - * Computes the current binary data of this BO. - * - * @param maxSize the max data size. - * @return the current binary data of this BO. - */ - public ByteBuffer computeData(final int maxSize) { - - int estimateSize = 0; - - for (final BufferObjectField field : fieldArray) { - estimateSize += estimateSize(field); - } - - if(maxSize < estimateSize) { - throw new IllegalStateException("The estimated size(" + estimateSize + ") of this BO is bigger than " + - "maximum available size " + maxSize); - } - - if (previousData != null) { - if (previousData.capacity() < estimateSize) { - BufferUtils.destroyDirectBuffer(previousData); - previousData = null; - } else { - previousData.clear(); - } - } - - final ByteBuffer data = previousData == null ? BufferUtils.createByteBuffer(estimateSize) : previousData; - - for (final BufferObjectField field : fieldArray) { - writeField(field, data); - } - - data.flip(); - - this.previousData = data; - - return data; - } - - /** - * Estimates size of the field. - * - * @param field the field. - * @return the estimated size. - */ - protected int estimateSize(final BufferObjectField field) { - - switch (field.getType()) { - case Float: - case Int: { - if (layout == Layout.std140) { - return 16; - } - return 4; - } - case Boolean: { - if (layout == Layout.std140) { - return 16; - } - return 1; - } - case Vector2: { - return 4 * 2; - } - case Vector3: { - final int multiplier = layout == Layout.std140 ? 4 : 3; - return 4 * multiplier; - } - case Vector4: - return 16; - case IntArray: { - return estimate((int[]) field.getValue()); - } - case FloatArray: { - return estimate((float[]) field.getValue()); - } - case Vector2Array: { - return estimateArray(field.getValue(), 8); - } - case Vector3Array: { - final int multiplier = layout == Layout.std140 ? 16 : 12; - return estimateArray(field.getValue(), multiplier); - } - case Vector4Array: { - return estimateArray(field.getValue(), 16); - } - case Matrix3: { - final int multiplier = layout == Layout.std140 ? 16 : 12; - return 3 * 3 * multiplier; - } - case Matrix4: { - return 4 * 4 * 4; - } - case Matrix3Array: { - int multiplier = layout == Layout.std140 ? 16 : 12; - multiplier = 3 * 3 * multiplier; - return estimateArray(field.getValue(), multiplier); - } - case Matrix4Array: { - final int multiplier = 4 * 4 * 16; - return estimateArray(field.getValue(), multiplier); - } - default: { - throw new IllegalArgumentException("The type of BO field " + field.getType() + " doesn't support."); - } - } - } - - /** - * Estimates byte count to present the value on the GPU. - * - * @param value the value. - * @param multiplier the multiplier. - * @return the estimated byte count. - */ - protected int estimateArray(final Object value, final int multiplier) { - - if (value instanceof Object[]) { - return ((Object[]) value).length * multiplier; - } else if (value instanceof Collection) { - return ((Collection) value).size() * multiplier; - } - - throw new IllegalArgumentException("Unexpected value " + value); - } - - /** - * Estimates byte count to present the values on the GPU. - * - * @param values the values. - * @return the estimated byte count. - */ - protected int estimate(final float[] values) { - return values.length * 4; - } - - /** - * Estimates byte count to present the values on the GPU. - * - * @param values the values. - * @return the estimated byte count. - */ - protected int estimate(final int[] values) { - return values.length * 4; - } - - /** - * Writes the field to the data buffer. - * - * @param field the field. - * @param data the data buffer. - */ - protected void writeField(final BufferObjectField field, final ByteBuffer data) { - - final Object value = field.getValue(); - - switch (field.getType()) { - case Int: { - data.putInt(((Number) value).intValue()); - if (layout == Layout.std140) { - data.putInt(0); - data.putLong(0); - } - break; - } - case Float: { - data.putFloat(((Number) value).floatValue()); - if (layout == Layout.std140) { - data.putInt(0); - data.putLong(0); - } - break; - } - case Boolean: - data.put((byte) (((Boolean) value) ? 1 : 0)); - if (layout == Layout.std140) { - data.putInt(0); - data.putLong(0); - data.putShort((short) 0); - data.put((byte) 0); - } - break; - case Vector2: - write(data, (Vector2f) value); - break; - case Vector3: - write(data, (Vector3f) value); - break; - case Vector4: - writeVec4(data, value); - break; - case IntArray: { - write(data, (int[]) value); - break; - } - case FloatArray: { - write(data, (float[]) value); - break; - } - case Vector2Array: { - writeVec2Array(data, value); - break; - } - case Vector3Array: { - writeVec3Array(data, value); - break; - } - case Vector4Array: { - writeVec4Array(data, value); - break; - } - case Matrix3: { - write(data, (Matrix3f) value); - break; - } - case Matrix4: { - write(data, (Matrix4f) value); - break; - } - case Matrix3Array: { - writeMat3Array(data, value); - break; - } - case Matrix4Array: { - writeMat4Array(data, value); - break; - } - default: { - throw new IllegalArgumentException("The type of BO field " + field.getType() + " doesn't support."); - } - } - } - - /** - * Writes the value to the data buffer. - * - * @param data the data buffer. - * @param value the value. - */ - @SuppressWarnings("unchecked") - protected void writeMat3Array(final ByteBuffer data, final Object value) { - - if (value instanceof Matrix3f[]) { - - final Matrix3f[] values = (Matrix3f[]) value; - for (final Matrix3f mat : values) { - write(data, mat); - } - - } else if(value instanceof SafeArrayList) { - - final SafeArrayList values = (SafeArrayList) value; - for (final Matrix3f mat : values.getArray()) { - write(data, mat); - } - - } else if(value instanceof Collection) { - - final Collection values = (Collection) value; - for (final Matrix3f mat : values) { - write(data, mat); - } - } - } - - /** - * Writes the value to the data buffer. - * - * @param data the data buffer. - * @param value the value. - */ - @SuppressWarnings("unchecked") - protected void writeMat4Array(final ByteBuffer data, final Object value) { - - if (value instanceof Matrix4f[]) { - - final Matrix4f[] values = (Matrix4f[]) value; - for (final Matrix4f mat : values) { - write(data, mat); - } - - } else if(value instanceof SafeArrayList) { - - final SafeArrayList values = (SafeArrayList) value; - for (final Matrix4f mat : values.getArray()) { - write(data, mat); - } - - } else if(value instanceof Collection) { - - final Collection values = (Collection) value; - for (final Matrix4f mat : values) { - write(data, mat); - } - } - } - - - /** - * Writes the value to the data buffer. - * - * @param data the data buffer. - * @param value the value. - */ - @SuppressWarnings("unchecked") - protected void writeVec4Array(final ByteBuffer data, final Object value) { - - if (value instanceof Object[]) { - - final Object[] values = (Object[]) value; - for (final Object vec : values) { - writeVec4(data, vec); - } - - } else if(value instanceof SafeArrayList) { - - final SafeArrayList values = (SafeArrayList) value; - for (final Object vec : values.getArray()) { - writeVec4(data, vec); - } - - } else if(value instanceof Collection) { - - final Collection values = (Collection) value; - for (final Object vec : values) { - writeVec4(data, vec); - } - } - } - - /** - * Writes the value to the data buffer. - * - * @param data the data buffer. - * @param value the value. - */ - @SuppressWarnings("unchecked") - protected void writeVec3Array(final ByteBuffer data, final Object value) { - - if (value instanceof Vector3f[]) { - - final Vector3f[] values = (Vector3f[]) value; - for (final Vector3f vec : values) { - write(data, vec); - } - - } else if(value instanceof SafeArrayList) { - - final SafeArrayList values = (SafeArrayList) value; - for (final Vector3f vec : values.getArray()) { - write(data, vec); - } - - } else if(value instanceof Collection) { - - final Collection values = (Collection) value; - for (final Vector3f vec : values) { - write(data, vec); - } - } - } - - /** - * Writes the value to the data buffer. - * - * @param data the data buffer. - * @param value the value. - */ - @SuppressWarnings("unchecked") - protected void writeVec2Array(final ByteBuffer data, final Object value) { - - if (value instanceof Vector2f[]) { - - final Vector2f[] values = (Vector2f[]) value; - for (final Vector2f vec : values) { - write(data, vec); - } - - } else if(value instanceof SafeArrayList) { - - final SafeArrayList values = (SafeArrayList) value; - for (final Vector2f vec : values.getArray()) { - write(data, vec); - } - - } else if(value instanceof Collection) { - - final Collection values = (Collection) value; - for (final Vector2f vec : values) { - write(data, vec); - } - } - } - - /** - * Writes the value to the data buffer. - * - * @param data the data buffer. - * @param value the value. - */ - protected void write(final ByteBuffer data, final float[] value) { - for (float val : value) { - data.putFloat(val); - } - } - - /** - * Writes the value to the data buffer. - * - * @param data the data buffer. - * @param value the value. - */ - protected void write(final ByteBuffer data, final int[] value) { - for (int val : value) { - data.putInt(val); - } - } - - /** - * Writes the value to the data buffer. - * - * @param data the data buffer. - * @param value the value. - */ - protected void writeVec4(final ByteBuffer data, final Object value) { - - if (value == null) { - data.putLong(0).putLong(0); - } else if (value instanceof Vector4f) { - - final Vector4f vec4 = (Vector4f) value; - data.putFloat(vec4.getX()) - .putFloat(vec4.getY()) - .putFloat(vec4.getZ()) - .putFloat(vec4.getW()); - - } else if(value instanceof Quaternion) { - - final Quaternion vec4 = (Quaternion) value; - data.putFloat(vec4.getX()) - .putFloat(vec4.getY()) - .putFloat(vec4.getZ()) - .putFloat(vec4.getW()); - - } else if(value instanceof ColorRGBA) { - - final ColorRGBA vec4 = (ColorRGBA) value; - data.putFloat(vec4.getRed()) - .putFloat(vec4.getGreen()) - .putFloat(vec4.getBlue()) - .putFloat(vec4.getAlpha()); - } - } - - /** - * Writes the value to the data buffer. - * - * @param data the data buffer. - * @param value the value. - */ - protected void write(final ByteBuffer data, final Vector3f value) { - - if (value == null) { - data.putLong(0).putInt(0); - } else { - data.putFloat(value.getX()) - .putFloat(value.getY()) - .putFloat(value.getZ()); - } - - if (layout == Layout.std140) { - data.putInt(0); - } - } - - /** - * Writes the value to the data buffer. - * - * @param data the data buffer. - * @param x the x value. - * @param y the y value. - * @param z the z value. - */ - protected void write(final ByteBuffer data, final float x, final float y, final float z) { - - data.putFloat(x) - .putFloat(y) - .putFloat(z); - - if (layout == Layout.std140) { - data.putInt(0); - } - } - - /** - * Writes the value to the data buffer. - * - * @param data the data buffer. - * @param x the x value. - * @param y the y value. - * @param z the z value. - * @param w the w value. - */ - protected void write(final ByteBuffer data, final float x, final float y, final float z, final float w) { - data.putFloat(x) - .putFloat(y) - .putFloat(z) - .putFloat(w); - } - - /** - * Writes the value to the data buffer. - * - * @param data the data buffer. - * @param value the value. - */ - protected void write(final ByteBuffer data, final Vector2f value) { - if (value == null) { - data.putLong(0); - } else { - data.putFloat(value.getX()).putFloat(value.getY()); - } - } - - /** - * Writes the value to the data buffer. - * - * @param data the data buffer. - * @param value the value. - */ - protected void write(final ByteBuffer data, final Matrix3f value) { - write(data, value.get(0, 0), value.get(1, 0), value.get(2, 0)); - write(data, value.get(0, 1), value.get(1, 1), value.get(2, 1)); - write(data, value.get(0, 2), value.get(1, 2), value.get(2, 2)); - } - - /** - * Writes the value to the data buffer. - * - * @param data the data buffer. - * @param value the value. - */ - protected void write(final ByteBuffer data, final Matrix4f value) { - write(data, value.get(0, 0), value.get(1, 0), value.get(2, 0), value.get(3, 0)); - write(data, value.get(0, 1), value.get(1, 1), value.get(2, 1), value.get(3, 1)); - write(data, value.get(0, 2), value.get(1, 2), value.get(2, 2), value.get(3, 2)); - write(data, value.get(0, 3), value.get(1, 3), value.get(2, 3), value.get(3, 3)); - } - - @Override - public void deleteObject(final Object rendererObject) { - - if (!(rendererObject instanceof Renderer)) { - throw new IllegalArgumentException("This bo can't be deleted from " + rendererObject); - } - - ((Renderer) rendererObject).deleteBuffer(this); - } - - @Override - public NativeObject createDestructableClone() { - return new BufferObject(null, getId()); - } - - @Override - protected void deleteNativeBuffers() { - super.deleteNativeBuffers(); - if (previousData != null) { - BufferUtils.destroyDirectBuffer(previousData); - previousData = null; - } - } - - @Override - public long getUniqueId() { - return ((long) OBJTYPE_BO << 32) | (0xffffffffL & (long) id); - } -} diff --git a/jme3-core/src/main/java/com/jme3/shader/BufferObjectField.java b/jme3-core/src/main/java/com/jme3/shader/BufferObjectField.java deleted file mode 100644 index 798b418fc4..0000000000 --- a/jme3-core/src/main/java/com/jme3/shader/BufferObjectField.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.jme3.shader; - -import static java.util.Objects.requireNonNull; - -/** - * The class to describe a filed in BO. - * - * @author JavaSaBr - */ -public class BufferObjectField { - - - /** - * The field name. - */ - private final String name; - - /** - * The field type. - */ - private final VarType type; - - /** - * The field value. - */ - private Object value; - - public BufferObjectField(final String name, final VarType type) { - this.name = name; - this.type = type; - } - - /** - * Get the field name. - * - * @return the field name. - */ - public String getName() { - return name; - } - - /** - * Gets the field type. - * - * @return the field type. - */ - public VarType getType() { - return type; - } - - /** - * Gets the field value. - * - * @return the field value. - */ - public Object getValue() { - return value; - } - - /** - * Sets the field value. - * - * @param value the field value. - */ - public void setValue(final Object value) { - this.value = requireNonNull(value, "The field's value can't be null."); - } - - @Override - public String toString() { - return "BufferObjectField{" + - "name='" + name + '\'' + - ", type=" + type + - ", value=" + value + - '}'; - } -} diff --git a/jme3-core/src/main/java/com/jme3/shader/ShaderBufferBlock.java b/jme3-core/src/main/java/com/jme3/shader/ShaderBufferBlock.java index 27b44d18b3..fb39090f42 100644 --- a/jme3-core/src/main/java/com/jme3/shader/ShaderBufferBlock.java +++ b/jme3-core/src/main/java/com/jme3/shader/ShaderBufferBlock.java @@ -31,34 +31,49 @@ */ package com.jme3.shader; +import java.lang.ref.WeakReference; + +import com.jme3.shader.bufferobject.BufferObject; + /** * Implementation of shader's buffer block. * - * @author JavaSaBr + * @author JavaSaBr, Riccardo Balbo */ public class ShaderBufferBlock extends ShaderVariable { + + public static enum BufferType { + UniformBufferObject, ShaderStorageBufferObject + } /** * Current used buffer object. */ protected BufferObject bufferObject; + protected WeakReference bufferObjectRef; + protected BufferType type; /** * Set the new buffer object. * - * @param bufferObject the new buffer object. + * @param bufferObject + * the new buffer object. */ - public void setBufferObject(final BufferObject bufferObject) { - + public void setBufferObject(BufferType type, BufferObject bufferObject) { if (bufferObject == null) { throw new IllegalArgumentException("for storage block " + name + ": storageData cannot be null"); } - + if (bufferObject == this.bufferObject && type == this.type) return; this.bufferObject = bufferObject; - + this.bufferObjectRef = new WeakReference(bufferObject); + this.type = type; updateNeeded = true; } + public BufferType getType() { + return type; + } + /** * Return true if need to update this storage block. * @@ -90,4 +105,13 @@ public void reset(){ public BufferObject getBufferObject() { return bufferObject; } + + public WeakReference getBufferObjectRef() { + return bufferObjectRef; + } + + public void setBufferObjectRef(WeakReference bufferObjectRef) { + this.bufferObjectRef = bufferObjectRef; + } + } diff --git a/jme3-core/src/main/java/com/jme3/shader/Uniform.java b/jme3-core/src/main/java/com/jme3/shader/Uniform.java index 45006a5a6c..0d4a18a15f 100644 --- a/jme3-core/src/main/java/com/jme3/shader/Uniform.java +++ b/jme3-core/src/main/java/com/jme3/shader/Uniform.java @@ -31,6 +31,7 @@ */ package com.jme3.shader; +import com.jme3.material.Material.BindUnits; import com.jme3.math.*; import com.jme3.util.BufferUtils; import com.jme3.util.TempVars; @@ -197,7 +198,8 @@ public void clearValue(){ } } - public void setValue(VarType type, Object value){ + public void setValue(VarType type, Object value) { + assert !(value instanceof BindUnits); if (location == LOC_NOT_DEFINED) { return; } diff --git a/jme3-core/src/main/java/com/jme3/shader/VarType.java b/jme3-core/src/main/java/com/jme3/shader/VarType.java index 3a1ca47fa2..3bc6716ea4 100644 --- a/jme3-core/src/main/java/com/jme3/shader/VarType.java +++ b/jme3-core/src/main/java/com/jme3/shader/VarType.java @@ -31,8 +31,8 @@ */ package com.jme3.shader; import com.jme3.math.*; +import com.jme3.shader.bufferobject.BufferObject; import com.jme3.texture.*; -import com.jme3.shader.BufferObject; public enum VarType { Float("float",float.class,Float.class), @@ -60,8 +60,8 @@ public enum VarType { TextureArray(false,true,"sampler2DArray|sampler2DArrayShadow",TextureArray.class,Texture.class), TextureCubeMap(false,true,"samplerCube",TextureCubeMap.class,Texture.class), Int("int",int.class,Integer.class), - BufferObject(false, false, "custom", BufferObject.class); - + UniformBufferObject(false, false, "custom",BufferObject.class), + ShaderStorageBufferObject(false, false, "custom",BufferObject.class); private boolean usesMultiData = false; private boolean textureType = false; diff --git a/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferObject.java b/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferObject.java new file mode 100644 index 0000000000..de75393cfc --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferObject.java @@ -0,0 +1,345 @@ +package com.jme3.shader.bufferobject; + +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +import com.jme3.export.InputCapsule; +import com.jme3.export.JmeExporter; +import com.jme3.export.JmeImporter; +import com.jme3.export.OutputCapsule; +import com.jme3.export.Savable; +import com.jme3.renderer.Renderer; +import com.jme3.util.BufferUtils; +import com.jme3.util.NativeObject; + +/** + * A generic memory buffer that can be divided in logical regions + * + * @author Riccardo Balbo + */ +public class BufferObject extends NativeObject implements Savable { + /** + * Hint to suggest the renderer how to access this buffer + */ + public static enum AccessHint { + /** + * The data store contents will be modified once and used many times. + */ + Static, + /** + * The data store contents will be modified once and used at most a few + * times. + */ + Stream, + /** + * The data store contents will be modified repeatedly and used many + * times. + */ + Dynamic, + /** + * Used only by the cpu. + */ + CpuOnly + } + + /** + * Hint to suggest the renderer how the data should be used + */ + public static enum NatureHint { + /** + * The data store contents are modified by the application, and used as + * the source for GL drawing and image specification commands. + */ + Draw, + /** + * The data store contents are modified by reading data from the GL, and + * used to return that data when queried by the application. + */ + Read, + /** + * The data store contents are modified by reading data from the GL, and + * used as the source for GL drawing and image specification commands. + */ + Copy + } + + private AccessHint accessHint = AccessHint.Dynamic; + private NatureHint natureHint = NatureHint.Draw; + + private transient WeakReference weakRef; + private transient int binding = -1; + protected transient DirtyRegionsIterator dirtyRegionsIterator; + + protected ByteBuffer data = null; + protected ArrayList regions = new ArrayList(); + + public BufferObject() { + super(); + } + + + protected BufferObject(int id) { + super(id); + } + + + /** + * Internal use only. Indicates that the object has changed and its state + * needs to be updated. Mark all the regions as dirty. + */ + public final void setUpdateNeeded() { + setUpdateNeeded(true); + } + + /** + * Indicates that the object has changed and its state needs to be updated. + * + * @param dirtyAll + * mark all regions for update + */ + public void setUpdateNeeded(boolean dirtyAll) { + if (dirtyAll) markAllRegionsDirty(); + updateNeeded = true; + } + + + /** + * Get binding point + * + * @return the binding point + */ + public int getBinding() { + return binding; + } + + + /** + * Initialize an empty buffer object of the given length + * + * @param length expected length of the buffer object + */ + public void initializeEmpty(int length) { + if (data != null) { + BufferUtils.destroyDirectBuffer(data); + } + this.data = BufferUtils.createByteBuffer(length); + } + + + /** + * Transfer remaining bytes of passed buffer to the internal buffer of this buffer object + * + * @param data ByteBuffer containing the data to pass + */ + public void setData(ByteBuffer data) { + if (data != null) { + BufferUtils.destroyDirectBuffer(data); + } + this.data = BufferUtils.createByteBuffer(data.limit() - data.position()); + this.data.put(data); + } + + + + /** + * Rewind and return buffer data + * + * @return + */ + public ByteBuffer getData() { + if (regions.size() == 0) { + if (data == null) data = BufferUtils.createByteBuffer(0); + } else { + int regionsEnd = regions.get(regions.size() - 1).getEnd(); + if (data == null) { + data = BufferUtils.createByteBuffer(regionsEnd + 1); + } else if (data.limit() < regionsEnd) { + // new buffer + ByteBuffer newData = BufferUtils.createByteBuffer(regionsEnd + 1); + + // copy old buffer in new buffer + if (newData.limit() < data.limit()) data.limit(newData.limit()); + newData.put(data); + + // destroy old buffer + BufferUtils.destroyDirectBuffer(data); + + data = newData; + } + } + data.rewind(); + return data; + } + + /** + * Get dirty regions + * + * @return Helper object to iterate through dirty regions + */ + public DirtyRegionsIterator getDirtyRegions() { + if (dirtyRegionsIterator == null) dirtyRegionsIterator = new DirtyRegionsIterator(this); + dirtyRegionsIterator.rewind(); + return dirtyRegionsIterator; + } + + /** + * Reset layour definition + */ + public void unsetRegions() { + regions.clear(); + regions.trimToSize(); + } + + /** + * Add a region at the end of the layout + * + * @param lr + */ + public void setRegions(List lr) { + regions.clear(); + regions.addAll(lr); + regions.trimToSize(); + setUpdateNeeded(); + } + + + /** + * Return all the regions of this layout + * + * @return ordered list of regions + */ + public BufferRegion getRegion(int i) { + BufferRegion region = regions.get(i); + region.bo = this; + return region; + } + + /** + * Mark all regions as dirty + */ + public void markAllRegionsDirty() { + for (BufferRegion r : regions) r.markDirty(); + } + + + @Override + public void resetObject() { + this.id = -1; + } + + @Override + protected void deleteNativeBuffers() { + super.deleteNativeBuffers(); + if (data != null) BufferUtils.destroyDirectBuffer(data); + } + + @Override + public void deleteObject(final Object rendererObject) { + if (!(rendererObject instanceof Renderer)) { + throw new IllegalArgumentException("This bo can't be deleted from " + rendererObject); + } + ((Renderer) rendererObject).deleteBuffer(this); + } + + @Override + public NativeObject createDestructableClone() { + return new BufferObject(getId()); + } + + @Override + public long getUniqueId() { + return ((long) OBJTYPE_BO << 32) | (0xffffffffL & (long) id); + } + + /** + * Set binding point + * @param binding binding point + */ + public void setBinding(final int binding) { + this.binding = binding; + } + + public WeakReference getWeakRef() { + if (weakRef == null) weakRef = new WeakReference(this); + return weakRef; + } + + public AccessHint getAccessHint() { + return accessHint; + } + + /** + * Set AccessHint to hint the renderer on how to access this data. + * + * @param natureHint + */ + public void setAccessHint(AccessHint accessHint) { + this.accessHint = accessHint; + setUpdateNeeded(); + } + + public NatureHint getNatureHint() { + return natureHint; + } + + /** + * Set NatureHint to hint the renderer on how to use this data. + * + * @param natureHint + */ + public void setNatureHint(NatureHint natureHint) { + this.natureHint = natureHint; + setUpdateNeeded(); + } + + @Override + public void write(JmeExporter ex) throws IOException { + OutputCapsule oc = ex.getCapsule(this); + oc.write(accessHint.ordinal(), "accessHint", 0); + oc.write(natureHint.ordinal(), "natureHint", 0); + oc.writeSavableArrayList(regions, "regions", null); + oc.write(data, "data", null); + } + + @Override + public void read(JmeImporter im) throws IOException { + InputCapsule ic = im.getCapsule(this); + accessHint = AccessHint.values()[ic.readInt("accessHint", 0)]; + natureHint = NatureHint.values()[ic.readInt("natureHint", 0)]; + regions.addAll(ic.readSavableArrayList("regions", null)); + data = ic.readByteBuffer("data", null); + setUpdateNeeded(true); + } + + @Override + public BufferObject clone() { + BufferObject clone = (BufferObject) super.clone(); + clone.binding = -1; + clone.weakRef = null; + clone.data = BufferUtils.clone(data); + clone.regions = new ArrayList(); + assert clone.regions != regions; + for (BufferRegion r : regions) { + clone.regions.add(r.clone()); + } + clone.dirtyRegionsIterator = null; + + clone.setUpdateNeeded(); + return clone; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getClass().getSimpleName()).append("{\n"); + for (BufferRegion r : regions) { + sb.append(" ").append(r).append("\n"); + } + sb.append("}"); + return sb.toString(); + } + +} diff --git a/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferRegion.java b/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferRegion.java new file mode 100644 index 0000000000..06efbd82a1 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferRegion.java @@ -0,0 +1,149 @@ +package com.jme3.shader.bufferobject; + +import java.io.IOException; +import java.nio.ByteBuffer; + +import com.jme3.export.InputCapsule; +import com.jme3.export.JmeExporter; +import com.jme3.export.JmeImporter; +import com.jme3.export.OutputCapsule; +import com.jme3.export.Savable; + +/** + * A slice of a buffer + * + * @author Riccardo Balbo + * + */ +public class BufferRegion implements Savable, Cloneable { + protected int start = -1; + protected int end = -1; + protected boolean dirty = true; + protected boolean fullBufferRegion = false; + protected BufferObject bo; + protected ByteBuffer slice; + protected ByteBuffer source; + + public BufferRegion(int start, int end) { + this.start = start; + this.end = end; + } + + public BufferRegion() { + + } + + /** + * Rewind and get a ByteBuffer pointing to this region of the main buffer + * + * @return ByteBuffer + */ + public ByteBuffer getData() { + ByteBuffer d = bo.getData(); + if (source == null || d != source || slice == null) { + source = d; + int currentPos = source.position(); + int currentLimit = source.limit(); + source.position(start); + assert end < source.capacity() : "Can't set limit at " + end + " on capacity " + source.capacity(); + source.limit(end + 1); + slice = source.slice(); + slice.order(source.order()); + assert slice.limit() == (end - start + 1) : "Capacity is " + slice.limit() + " but " + (end - start + 1) + " expected"; + source.position(currentPos); + source.limit(currentLimit); + } + slice.rewind(); + return slice; + } + + /** + * Get beginning of the region + * + * @return position in the buffer + */ + public int getStart() { + return start; + } + + /** + * Get end of the region + * + * @return position in the buffer + */ + public int getEnd() { + return end; + } + + /** + * Get the length of this region + * + * @return the length of this region + */ + public int length() { + return end - start + 1; + } + + /** + * Returns true of the region is dirty + * + * @return + */ + public boolean isDirty() { + return dirty; + } + + /** + * Mark this region for update + */ + public void markDirty() { + dirty = true; + } + + /** + * Clear this region mark + */ + public void clearDirty() { + dirty = false; + } + + /** + * Returns true if this region includes the entire buffer. Can be used for + * optimization. + * + * @return + */ + public boolean isFullBufferRegion() { + return fullBufferRegion; + } + + @Override + public String toString() { + return "Region [start=" + start + ", end=" + end + ", size=" + (end - start) + ", dirty=" + dirty + "]"; + } + + @Override + public void write(JmeExporter ex) throws IOException { + OutputCapsule oc = ex.getCapsule(this); + oc.write(start, "start", 0); + oc.write(end, "end", 0); + oc.write(dirty, "dirty", false); + } + + @Override + public void read(JmeImporter im) throws IOException { + InputCapsule ic = im.getCapsule(this); + start = ic.readInt("start", 0); + end = ic.readInt("end", 0); + dirty = ic.readBoolean("dirty", false); + } + + @Override + public BufferRegion clone() { + try { + return (BufferRegion) super.clone(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/jme3-core/src/main/java/com/jme3/shader/bufferobject/DirtyRegionsIterator.java b/jme3-core/src/main/java/com/jme3/shader/bufferobject/DirtyRegionsIterator.java new file mode 100644 index 0000000000..ecaaab171d --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shader/bufferobject/DirtyRegionsIterator.java @@ -0,0 +1,86 @@ +package com.jme3.shader.bufferobject; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +/** + * An helper class that iterates and merges dirty regions + * + * @author Riccardo Balbo + */ +public class DirtyRegionsIterator { + + private static class DirtyRegion extends BufferRegion { + List regions = new ArrayList(); + + @Override + public ByteBuffer getData() { + ByteBuffer d = bo.getData(); + if (source == null || d != source || slice == null) { + source = d; + int currentPos = source.position(); + int currentLimit = source.limit(); + source.position(0); + source.limit(source.capacity()); + slice = source.slice(); + source.position(currentPos); + source.limit(currentLimit); + } + slice.position(start); + slice.limit(end); + return slice; + } + + public void clearDirty() { + regions.forEach(BufferRegion::clearDirty); + super.clearDirty(); + } + } + + private BufferObject bufferObject; + + public DirtyRegionsIterator(BufferObject bufferObject) { + this.bufferObject = bufferObject; + } + + private final DirtyRegion dirtyRegion = new DirtyRegion(); + private int pos = 0; + + public void rewind() { + pos = 0; + } + + public BufferRegion getNext() { + + dirtyRegion.bo = bufferObject; + dirtyRegion.regions.clear(); + + if (bufferObject.regions.size() == 0) { + if (!bufferObject.isUpdateNeeded()) return null; + dirtyRegion.fullBufferRegion = true; + dirtyRegion.end = bufferObject.getData().limit(); + dirtyRegion.start = 0; + return dirtyRegion; + } + + int dirtRegions = 0; + + while (pos < bufferObject.regions.size()) { + BufferRegion dr = bufferObject.regions.get(pos++); + if (dr.isDirty()) { + if (dirtRegions == 0) dirtyRegion.start = dr.start; + dirtyRegion.end = dr.end; + dirtRegions++; + dirtyRegion.regions.add(dr); + } else if (dirtRegions != 0) break; + } + + if (dirtRegions == 0) return null; + dirtyRegion.fullBufferRegion = dirtRegions == bufferObject.regions.size(); + dirtyRegion.markDirty(); + + return dirtyRegion; + } + +} diff --git a/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/BufferLayout.java b/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/BufferLayout.java new file mode 100644 index 0000000000..66fed64242 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/BufferLayout.java @@ -0,0 +1,116 @@ +package com.jme3.shader.bufferobject.layout; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +import com.jme3.math.FastMath; +import com.jme3.util.functional.Function; + +/** + * Layout serializer for buffers + * + * @author Riccardo Balbo + */ +public abstract class BufferLayout { + + public static abstract class ObjectSerializer { + private Function filter; + + public ObjectSerializer(Class cls) { + this(obj -> { + Class objc = obj instanceof Class ? (Class) obj : obj.getClass(); + return cls.isAssignableFrom(objc); + }); + + } + + public ObjectSerializer(Function filter) { + this.filter = filter; + } + + public final boolean canSerialize(Object obj) { + return filter.eval(obj); + } + + public abstract int length(BufferLayout layout, T obj); + + public abstract int basicAlignment(BufferLayout layout, T obj); + + public abstract void write(BufferLayout layout, ByteBuffer bbf, T obj); + } + + protected List> serializers = new ArrayList>(); + + protected ObjectSerializer getSerializer(Object obj) { + for (int i = serializers.size() - 1; i >= 0; i--) { + ObjectSerializer sr = serializers.get(i); + if (sr.canSerialize(obj)) return sr; + + } + throw new RuntimeException("Serializer not found for " + obj + " of type " + obj.getClass()); + } + + /** + * Register a serializer + * + * @param type + */ + protected void registerSerializer(ObjectSerializer serializer) { + serializers.add(serializer); + } + + /** + * Estimate size of Object when serialized accordingly with std140 + * + * @param o + * the object to serialize + * @return the size + */ + public int estimateSize(Object o) { + ObjectSerializer s = getSerializer(o); + return s.length(this, o); + } + /** + * Get basic alignment of Object when serialized accordingly with std140 + * + * @param o + * the object to serialize + * @return the basic alignment + */ + + public int getBasicAlignment(Object o) { + ObjectSerializer s = getSerializer(o); + return s.basicAlignment(this, o); + } + /** + * Align a position to the given basicAlignment + * + * @param pos + * the position to align + * @param basicAlignment + * the basic alignment + * @return the aligned position + */ + public int align(int pos, int basicAlignment) { + return pos==0?pos:FastMath.toMultipleOf(pos, basicAlignment); + } + + /** + * Serialize an object accordingly with the std140 layout and write the + * result to a BufferObject + * + * @param out + * the output BufferObject where the object will be serialized + * (starting from the current position) + * @param o + * the Object to serialize + */ + public void write(ByteBuffer out, Object o) { + ObjectSerializer s = getSerializer(o); + s.write(this, out, o); + } + + + public abstract String getId(); +} diff --git a/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/RawLayout.java b/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/RawLayout.java new file mode 100644 index 0000000000..5b502b7db7 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/RawLayout.java @@ -0,0 +1,511 @@ +package com.jme3.shader.bufferobject.layout; + +import java.nio.ByteBuffer; + +import com.jme3.math.ColorRGBA; +import com.jme3.math.Matrix3f; +import com.jme3.math.Matrix4f; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector2f; +import com.jme3.math.Vector3f; +import com.jme3.math.Vector4f; + +/** + * Simple serializer + * + * @author Riccardo Balbo + */ +public class RawLayout extends BufferLayout { + public RawLayout() { + // Init default serializers + registerSerializer(new ObjectSerializer(byte[].class) { + @Override + public int length(BufferLayout serializer, byte[] obj) { + return obj.length; + } + + @Override + public int basicAlignment(BufferLayout serializer, byte[] obj) { + return 1; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, byte[] obj) { + bbf.put(obj); + } + }); + + registerSerializer(new ObjectSerializer(Integer.class) { + @Override + public int length(BufferLayout serializer, Integer obj) { + return 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Integer obj) { + return 1; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Integer obj) { + bbf.putInt(obj); + } + }); + + registerSerializer(new ObjectSerializer(Boolean.class) { + @Override + public int length(BufferLayout serializer, Boolean obj) { + return 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Boolean obj) { + return 1; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Boolean obj) { + bbf.putInt(obj ? 1 : 0); + } + }); + + registerSerializer(new ObjectSerializer(Float.class) { + @Override + public int length(BufferLayout serializer, Float obj) { + return 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Float obj) { + return 1; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Float obj) { + bbf.putFloat(obj); + } + }); + + registerSerializer(new ObjectSerializer(Vector2f.class) { + @Override + public int length(BufferLayout serializer, Vector2f obj) { + return 4 * 2; + } + + @Override + public int basicAlignment(BufferLayout serializer, Vector2f obj) { + return 1; + + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Vector2f obj) { + bbf.putFloat(obj.x); + bbf.putFloat(obj.y); + } + }); + + registerSerializer(new ObjectSerializer(ColorRGBA.class) { + @Override + public int length(BufferLayout serializer, ColorRGBA obj) { + return 4 * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, ColorRGBA obj) { + return 1; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, ColorRGBA obj) { + bbf.putFloat(obj.r); + bbf.putFloat(obj.g); + bbf.putFloat(obj.b); + bbf.putFloat(obj.a); + } + }); + + registerSerializer(new ObjectSerializer(Quaternion.class) { + @Override + public int length(BufferLayout serializer, Quaternion obj) { + return 4 * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Quaternion obj) { + return 1; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Quaternion obj) { + bbf.putFloat(obj.getX()); + bbf.putFloat(obj.getY()); + bbf.putFloat(obj.getZ()); + bbf.putFloat(obj.getW()); + } + }); + + registerSerializer(new ObjectSerializer(Vector4f.class) { + @Override + public int length(BufferLayout serializer, Vector4f obj) { + return 4 * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Vector4f obj) { + return 1; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Vector4f obj) { + bbf.putFloat(obj.x); + bbf.putFloat(obj.y); + bbf.putFloat(obj.z); + bbf.putFloat(obj.w); + + } + }); + + registerSerializer(new ObjectSerializer(Vector3f.class) { + @Override + public int length(BufferLayout serializer, Vector3f obj) { + return 4 * 3; + } + + @Override + public int basicAlignment(BufferLayout serializer, Vector3f obj) { + return 1; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Vector3f obj) { + bbf.putFloat(obj.x); + bbf.putFloat(obj.y); + bbf.putFloat(obj.z); + } + }); + + registerSerializer(new ObjectSerializer(Integer[].class) { + @Override + public int length(BufferLayout serializer, Integer[] obj) { + return 4 * obj.length; + } + + @Override + public int basicAlignment(BufferLayout serializer, Integer[] obj) { + return 1; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Integer[] obj) { + for (int i : obj) { + bbf.putInt(i); + } + } + }); + + registerSerializer(new ObjectSerializer(Float[].class) { + @Override + public int length(BufferLayout serializer, Float[] obj) { + return 4 * obj.length; + } + + @Override + public int basicAlignment(BufferLayout serializer, Float[] obj) { + return 1; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Float[] obj) { + for (float i : obj) { + bbf.putFloat(i); + } + } + }); + + registerSerializer(new ObjectSerializer(Boolean[].class) { + @Override + public int length(BufferLayout serializer, Boolean[] obj) { + return 4 * obj.length; + } + + @Override + public int basicAlignment(BufferLayout serializer, Boolean[] obj) { + return 1; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Boolean[] obj) { + for (boolean i : obj) { + bbf.putInt(i ? 1 : 0); + + } + } + }); + + registerSerializer(new ObjectSerializer(Vector2f[].class) { + @Override + public int length(BufferLayout serializer, Vector2f[] obj) { + return 4 * obj.length * 2; + } + + @Override + public int basicAlignment(BufferLayout serializer, Vector2f[] obj) { + return 1; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Vector2f[] obj) { + for (Vector2f i : obj) { + bbf.putFloat(i.x); + bbf.putFloat(i.y); + + } + } + }); + + registerSerializer(new ObjectSerializer(Vector3f[].class) { + @Override + public int length(BufferLayout serializer, Vector3f[] obj) { + return 4 * obj.length * 3; + } + + @Override + public int basicAlignment(BufferLayout serializer, Vector3f[] obj) { + return 1; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Vector3f[] obj) { + for (Vector3f i : obj) { + bbf.putFloat(i.x); + bbf.putFloat(i.y); + bbf.putFloat(i.z); + } + } + }); + + registerSerializer(new ObjectSerializer(Vector4f[].class) { + @Override + public int length(BufferLayout serializer, Vector4f[] obj) { + return 4 * obj.length * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Vector4f[] obj) { + return 1; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Vector4f[] obj) { + for (Vector4f i : obj) { + bbf.putFloat(i.x); + bbf.putFloat(i.y); + bbf.putFloat(i.z); + bbf.putFloat(i.w); + } + } + }); + + registerSerializer(new ObjectSerializer(ColorRGBA[].class) { + @Override + public int length(BufferLayout serializer, ColorRGBA[] obj) { + return 4 * obj.length * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, ColorRGBA[] obj) { + return 1; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, ColorRGBA[] obj) { + for (ColorRGBA i : obj) { + bbf.putFloat(i.r); + bbf.putFloat(i.g); + bbf.putFloat(i.b); + bbf.putFloat(i.a); + } + } + }); + registerSerializer(new ObjectSerializer(Quaternion[].class) { + @Override + public int length(BufferLayout serializer, Quaternion[] obj) { + return 4 * obj.length * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Quaternion[] obj) { + return 1; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Quaternion[] obj) { + for (Quaternion i : obj) { + bbf.putFloat(i.getX()); + bbf.putFloat(i.getY()); + bbf.putFloat(i.getZ()); + bbf.putFloat(i.getW()); + } + } + }); + + registerSerializer(new ObjectSerializer(Matrix3f.class) { + @Override + public int length(BufferLayout serializer, Matrix3f obj) { + return 3 * 4 * 3; + } + + @Override + public int basicAlignment(BufferLayout serializer, Matrix3f obj) { + return 1; + } + + final Vector3f tmp = new Vector3f(); + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Matrix3f obj) { + obj.getColumn(0, tmp); + bbf.putFloat(tmp.x); + bbf.putFloat(tmp.y); + bbf.putFloat(tmp.z); + + obj.getColumn(1, tmp); + bbf.putFloat(tmp.x); + bbf.putFloat(tmp.y); + bbf.putFloat(tmp.z); + + obj.getColumn(2, tmp); + bbf.putFloat(tmp.x); + bbf.putFloat(tmp.y); + bbf.putFloat(tmp.z); + } + }); + + registerSerializer(new ObjectSerializer(Matrix4f.class) { + @Override + public int length(BufferLayout serializer, Matrix4f obj) { + return 4 * 4 * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Matrix4f obj) { + return 1; + } + + final float[] tmpF = new float[4]; + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Matrix4f obj) { + obj.getColumn(0, tmpF); + bbf.putFloat(tmpF[0]); + bbf.putFloat(tmpF[1]); + bbf.putFloat(tmpF[2]); + bbf.putFloat(tmpF[3]); + + obj.getColumn(1, tmpF); + bbf.putFloat(tmpF[0]); + bbf.putFloat(tmpF[1]); + bbf.putFloat(tmpF[2]); + bbf.putFloat(tmpF[3]); + + obj.getColumn(2, tmpF); + bbf.putFloat(tmpF[0]); + bbf.putFloat(tmpF[1]); + bbf.putFloat(tmpF[2]); + bbf.putFloat(tmpF[3]); + + obj.getColumn(3, tmpF); + bbf.putFloat(tmpF[0]); + bbf.putFloat(tmpF[1]); + bbf.putFloat(tmpF[2]); + bbf.putFloat(tmpF[3]); + + } + }); + + registerSerializer(new ObjectSerializer(Matrix3f[].class) { + @Override + public int length(BufferLayout serializer, Matrix3f[] obj) { + return 3 * 4 * 3 * obj.length; + } + + @Override + public int basicAlignment(BufferLayout serializer, Matrix3f[] obj) { + return 1; + } + + final Vector3f tmp = new Vector3f(); + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Matrix3f[] objs) { + for (Matrix3f obj : objs) { + obj.getColumn(0, tmp); + bbf.putFloat(tmp.x); + bbf.putFloat(tmp.y); + bbf.putFloat(tmp.z); + + obj.getColumn(1, tmp); + bbf.putFloat(tmp.x); + bbf.putFloat(tmp.y); + bbf.putFloat(tmp.z); + + obj.getColumn(2, tmp); + bbf.putFloat(tmp.x); + bbf.putFloat(tmp.y); + bbf.putFloat(tmp.z); + } + } + }); + + registerSerializer(new ObjectSerializer(Matrix4f[].class) { + @Override + public int length(BufferLayout serializer, Matrix4f[] obj) { + return 4 * 4 * 4 * obj.length; + } + + @Override + public int basicAlignment(BufferLayout serializer, Matrix4f[] obj) { + return 1; + } + + final float[] tmpF = new float[4]; + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Matrix4f[] objs) { + for (Matrix4f obj : objs) { + obj.getColumn(0, tmpF); + bbf.putFloat(tmpF[0]); + bbf.putFloat(tmpF[1]); + bbf.putFloat(tmpF[2]); + bbf.putFloat(tmpF[3]); + + obj.getColumn(1, tmpF); + bbf.putFloat(tmpF[0]); + bbf.putFloat(tmpF[1]); + bbf.putFloat(tmpF[2]); + bbf.putFloat(tmpF[3]); + + obj.getColumn(2, tmpF); + bbf.putFloat(tmpF[0]); + bbf.putFloat(tmpF[1]); + bbf.putFloat(tmpF[2]); + bbf.putFloat(tmpF[3]); + + obj.getColumn(3, tmpF); + bbf.putFloat(tmpF[0]); + bbf.putFloat(tmpF[1]); + bbf.putFloat(tmpF[2]); + bbf.putFloat(tmpF[3]); + } + + } + }); + + } + + @Override + public String getId() { + return "raw"; + } +} diff --git a/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/Std140Layout.java b/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/Std140Layout.java new file mode 100644 index 0000000000..19454726a9 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/Std140Layout.java @@ -0,0 +1,583 @@ +package com.jme3.shader.bufferobject.layout; + +import java.nio.ByteBuffer; + +import com.jme3.math.ColorRGBA; +import com.jme3.math.Matrix3f; +import com.jme3.math.Matrix4f; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector2f; +import com.jme3.math.Vector3f; +import com.jme3.math.Vector4f; + +/** + * Serializer that respects the Std140 layout + * (https://www.khronos.org/registry/OpenGL/specs/gl/glspec45.core.pdf#page=159) + * (www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt) + * + * @author Riccardo Balbo + */ +public class Std140Layout extends BufferLayout { + public Std140Layout() { + // Init default serializers + // 1. If the member is a scalar consuming N basic machine units, the + // base alignment is N . + registerSerializer(new ObjectSerializer(Integer.class) { + @Override + public int length(BufferLayout serializer, Integer obj) { + return 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Integer obj) { + return 4; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Integer obj) { + bbf.putInt(obj); + } + }); + + registerSerializer(new ObjectSerializer(Boolean.class) { + @Override + public int length(BufferLayout serializer, Boolean obj) { + return 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Boolean obj) { + return 4; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Boolean obj) { + bbf.putInt(obj ? 1 : 0); + } + }); + + registerSerializer(new ObjectSerializer(Float.class) { + @Override + public int length(BufferLayout serializer, Float obj) { + return 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Float obj) { + return 4; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Float obj) { + bbf.putFloat(obj); + } + }); + + // 2. If the member is a two- or four-component vector with components + // consuming N basic machine units, the base alignment is 2N or 4N , + // respectively + registerSerializer(new ObjectSerializer(Vector2f.class) { + @Override + public int length(BufferLayout serializer, Vector2f obj) { + return 4 * 2; + } + + @Override + public int basicAlignment(BufferLayout serializer, Vector2f obj) { + return 4 * 2; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Vector2f obj) { + bbf.putFloat(obj.x); + bbf.putFloat(obj.y); + } + }); + + registerSerializer(new ObjectSerializer(ColorRGBA.class) { + @Override + public int length(BufferLayout serializer, ColorRGBA obj) { + return 4 * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, ColorRGBA obj) { + return 4 * 4; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, ColorRGBA obj) { + bbf.putFloat(obj.r); + bbf.putFloat(obj.g); + bbf.putFloat(obj.b); + bbf.putFloat(obj.a); + } + }); + + registerSerializer(new ObjectSerializer(Quaternion.class) { + @Override + public int length(BufferLayout serializer, Quaternion obj) { + return 4 * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Quaternion obj) { + return 4 * 4; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Quaternion obj) { + bbf.putFloat(obj.getX()); + bbf.putFloat(obj.getY()); + bbf.putFloat(obj.getZ()); + bbf.putFloat(obj.getW()); + } + }); + + registerSerializer(new ObjectSerializer(Vector4f.class) { + @Override + public int length(BufferLayout serializer, Vector4f obj) { + return 4 * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Vector4f obj) { + return 4 * 4; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Vector4f obj) { + bbf.putFloat(obj.x); + bbf.putFloat(obj.y); + bbf.putFloat(obj.z); + bbf.putFloat(obj.w); + + } + }); + + // 3. If the member is a three-component vector with components + // consuming N + // basic machine units, the base alignment is 4N + registerSerializer(new ObjectSerializer(Vector3f.class) { + @Override + public int length(BufferLayout serializer, Vector3f obj) { + return 4 * 3; + } + + @Override + public int basicAlignment(BufferLayout serializer, Vector3f obj) { + return 4 * 4; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Vector3f obj) { + bbf.putFloat(obj.x); + bbf.putFloat(obj.y); + bbf.putFloat(obj.z); + // bbf.putFloat(0); + + } + }); + + // 4. If the member is an array of scalars or vectors, the base + // alignment and array + // stride are set to match the base alignment of a single array element, + // according + // to rules (1), (2), and (3), and rounded up to the base alignment of a + // vec4. The + // array may have padding at the end; the base offset of the member + // following + // the array is rounded up to the next multiple of the base alignment. + + registerSerializer(new ObjectSerializer(Integer[].class) { + @Override + public int length(BufferLayout serializer, Integer[] obj) { + return 4 * obj.length * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Integer[] obj) { + return 4 * 4; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Integer[] obj) { + for (int i : obj) { + bbf.putInt(i); + bbf.putInt(0); + bbf.putInt(0); + bbf.putInt(0); + } + } + }); + + registerSerializer(new ObjectSerializer(Float[].class) { + @Override + public int length(BufferLayout serializer, Float[] obj) { + return 4 * obj.length * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Float[] obj) { + return 4 * 4; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Float[] obj) { + for (float i : obj) { + bbf.putFloat(i); + bbf.putInt(0); + bbf.putInt(0); + bbf.putInt(0); + } + } + }); + + registerSerializer(new ObjectSerializer(Boolean[].class) { + @Override + public int length(BufferLayout serializer, Boolean[] obj) { + return 4 * obj.length * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Boolean[] obj) { + return 4 * 4; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Boolean[] obj) { + for (boolean i : obj) { + bbf.putInt(i ? 1 : 0); + bbf.putInt(0); + bbf.putInt(0); + bbf.putInt(0); + } + } + }); + + registerSerializer(new ObjectSerializer(Vector2f[].class) { + @Override + public int length(BufferLayout serializer, Vector2f[] obj) { + return 4 * obj.length * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Vector2f[] obj) { + return 4 * 4; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Vector2f[] obj) { + for (Vector2f i : obj) { + bbf.putFloat(i.x); + bbf.putFloat(i.y); + bbf.putInt(0); + bbf.putInt(0); + } + } + }); + + registerSerializer(new ObjectSerializer(Vector3f[].class) { + @Override + public int length(BufferLayout serializer, Vector3f[] obj) { + return 4 * obj.length * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Vector3f[] obj) { + return 4 * 4; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Vector3f[] obj) { + for (Vector3f i : obj) { + bbf.putFloat(i.x); + bbf.putFloat(i.y); + bbf.putFloat(i.z); + bbf.putInt(0); + } + } + }); + + registerSerializer(new ObjectSerializer(Vector4f[].class) { + @Override + public int length(BufferLayout serializer, Vector4f[] obj) { + return 4 * obj.length * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Vector4f[] obj) { + return 4 * 4; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Vector4f[] obj) { + for (Vector4f i : obj) { + bbf.putFloat(i.x); + bbf.putFloat(i.y); + bbf.putFloat(i.z); + bbf.putFloat(i.w); + } + } + }); + + registerSerializer(new ObjectSerializer(ColorRGBA[].class) { + @Override + public int length(BufferLayout serializer, ColorRGBA[] obj) { + return 4 * obj.length * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, ColorRGBA[] obj) { + return 4 * 4; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, ColorRGBA[] obj) { + for (ColorRGBA i : obj) { + bbf.putFloat(i.r); + bbf.putFloat(i.g); + bbf.putFloat(i.b); + bbf.putFloat(i.a); + } + } + }); + registerSerializer(new ObjectSerializer(Quaternion[].class) { + @Override + public int length(BufferLayout serializer, Quaternion[] obj) { + return 4 * obj.length * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Quaternion[] obj) { + return 4 * 4; + } + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Quaternion[] obj) { + for (Quaternion i : obj) { + bbf.putFloat(i.getX()); + bbf.putFloat(i.getY()); + bbf.putFloat(i.getZ()); + bbf.putFloat(i.getW()); + } + } + }); + + // 5. If the member is a column-major matrix with C columns and R rows, + // the + // matrix is stored identically to an array of C column vectors with R + // compo- + // nents each, according to rule (4). + + registerSerializer(new ObjectSerializer(Matrix3f.class) { + @Override + public int length(BufferLayout serializer, Matrix3f obj) { + return 3 * 4 * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Matrix3f obj) { + return 4 * 4; + } + + final Vector3f tmp = new Vector3f(); + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Matrix3f obj) { + obj.getColumn(0, tmp); + bbf.putFloat(tmp.x); + bbf.putFloat(tmp.y); + bbf.putFloat(tmp.z); + bbf.putFloat(0); + + obj.getColumn(1, tmp); + bbf.putFloat(tmp.x); + bbf.putFloat(tmp.y); + bbf.putFloat(tmp.z); + bbf.putFloat(0); + + obj.getColumn(2, tmp); + bbf.putFloat(tmp.x); + bbf.putFloat(tmp.y); + bbf.putFloat(tmp.z); + bbf.putFloat(0); + } + }); + + registerSerializer(new ObjectSerializer(Matrix4f.class) { + @Override + public int length(BufferLayout serializer, Matrix4f obj) { + return 4 * 4 * 4; + } + + @Override + public int basicAlignment(BufferLayout serializer, Matrix4f obj) { + return 4 * 4; + } + + final float[] tmpF = new float[4]; + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Matrix4f obj) { + obj.getColumn(0, tmpF); + bbf.putFloat(tmpF[0]); + bbf.putFloat(tmpF[1]); + bbf.putFloat(tmpF[2]); + bbf.putFloat(tmpF[3]); + + obj.getColumn(1, tmpF); + bbf.putFloat(tmpF[0]); + bbf.putFloat(tmpF[1]); + bbf.putFloat(tmpF[2]); + bbf.putFloat(tmpF[3]); + + obj.getColumn(2, tmpF); + bbf.putFloat(tmpF[0]); + bbf.putFloat(tmpF[1]); + bbf.putFloat(tmpF[2]); + bbf.putFloat(tmpF[3]); + + obj.getColumn(3, tmpF); + bbf.putFloat(tmpF[0]); + bbf.putFloat(tmpF[1]); + bbf.putFloat(tmpF[2]); + bbf.putFloat(tmpF[3]); + + } + }); + + // 6. If the member is an array of S column-major matrices with C + // columns and + // R rows, the matrix is stored identically to a row of S × C column + // vectors + // with R components each, according to rule (4). + + registerSerializer(new ObjectSerializer(Matrix3f[].class) { + @Override + public int length(BufferLayout serializer, Matrix3f[] obj) { + return 3 * 4 * 4 * obj.length; + } + + @Override + public int basicAlignment(BufferLayout serializer, Matrix3f[] obj) { + return 4 * 4; + } + + final Vector3f tmp = new Vector3f(); + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Matrix3f[] objs) { + for (Matrix3f obj : objs) { + obj.getColumn(0, tmp); + bbf.putFloat(tmp.x); + bbf.putFloat(tmp.y); + bbf.putFloat(tmp.z); + bbf.putFloat(0); + + obj.getColumn(1, tmp); + bbf.putFloat(tmp.x); + bbf.putFloat(tmp.y); + bbf.putFloat(tmp.z); + bbf.putFloat(0); + + obj.getColumn(2, tmp); + bbf.putFloat(tmp.x); + bbf.putFloat(tmp.y); + bbf.putFloat(tmp.z); + bbf.putFloat(0); + } + } + }); + + registerSerializer(new ObjectSerializer(Matrix4f[].class) { + @Override + public int length(BufferLayout serializer, Matrix4f[] obj) { + return 4 * 4 * 4 * obj.length; + } + + @Override + public int basicAlignment(BufferLayout serializer, Matrix4f[] obj) { + return 4 * 4; + } + + final float[] tmpF = new float[4]; + + @Override + public void write(BufferLayout serializer, ByteBuffer bbf, Matrix4f[] objs) { + for (Matrix4f obj : objs) { + obj.getColumn(0, tmpF); + bbf.putFloat(tmpF[0]); + bbf.putFloat(tmpF[1]); + bbf.putFloat(tmpF[2]); + bbf.putFloat(tmpF[3]); + + obj.getColumn(1, tmpF); + bbf.putFloat(tmpF[0]); + bbf.putFloat(tmpF[1]); + bbf.putFloat(tmpF[2]); + bbf.putFloat(tmpF[3]); + + obj.getColumn(2, tmpF); + bbf.putFloat(tmpF[0]); + bbf.putFloat(tmpF[1]); + bbf.putFloat(tmpF[2]); + bbf.putFloat(tmpF[3]); + + obj.getColumn(3, tmpF); + bbf.putFloat(tmpF[0]); + bbf.putFloat(tmpF[1]); + bbf.putFloat(tmpF[2]); + bbf.putFloat(tmpF[3]); + } + + } + }); + + // 7. If the member is a row-major matrix with C columns and R rows, the + // matrix + // is stored identically to an array of R row vectors with C components + // each, + // according to rule (4). + + // Nothing: jme matrices are column-major + + // 8. If the member is an array of S row-major matrices with C columns + // and R + // rows, the matrix is stored identically to a row of S × R row vectors + // with C + // components each, according to rule (4) + + // Nothing: jme matrices are column-major + + // 9. If the member is a structure, the base alignment of the structure + // is N , where + // N is the largest base alignment value of any of its members, and + // rounded + // up to the base alignment of a vec4. The individual members of this + // sub- + // structure are then assigned offsets by applying this set of rules + // recursively, + // where the base offset of the first member of the sub-structure is + // equal to the + // aligned offset of the structure. The structure may have padding at + // the end; + // the base offset of the member following the sub-structure is rounded + // up to + // the next multiple of the base alignment of the structure. + + // IMPLEMENTED AT A HIGHER LEVEL + + // 10. If the member is an array of S structures, the S elements of the + // array are laid + // out in order, according to rule (9) + + // IMPLEMENTED AT A HIGHER LEVEL + + } + + @Override + public String getId() { + return "std140"; + } +} diff --git a/jme3-core/src/main/java/com/jme3/system/NullRenderer.java b/jme3-core/src/main/java/com/jme3/system/NullRenderer.java index 4975b69a17..666222af23 100644 --- a/jme3-core/src/main/java/com/jme3/system/NullRenderer.java +++ b/jme3-core/src/main/java/com/jme3/system/NullRenderer.java @@ -42,9 +42,9 @@ import com.jme3.renderer.TextureUnitException; import com.jme3.scene.Mesh; import com.jme3.scene.VertexBuffer; -import com.jme3.shader.BufferObject; import com.jme3.shader.Shader; import com.jme3.shader.Shader.ShaderSource; +import com.jme3.shader.bufferobject.BufferObject; import com.jme3.texture.FrameBuffer; import com.jme3.texture.Image; import com.jme3.texture.Texture; @@ -179,9 +179,6 @@ public void modifyTexture(Texture tex, Image pixels, int x, int y) { public void updateBufferData(VertexBuffer vb) { } - @Override - public void updateBufferData(BufferObject bo) { - } @Override public void deleteBuffer(VertexBuffer vb) { } @@ -298,4 +295,23 @@ public boolean isMainFrameBufferSrgb() { public FrameBuffer getCurrentFrameBuffer() { return null; } + + public void updateShaderStorageBufferObjectData(BufferObject bo) { + + } + + @Override + public void updateUniformBufferObjectData(BufferObject bo) { + + } + + @Override + public void setShaderStorageBufferObject(int bindingPoint, BufferObject bufferObject) { + + } + + @Override + public void setUniformBufferObject(int bindingPoint, BufferObject bufferObject) { + + } } diff --git a/jme3-core/src/main/java/com/jme3/util/struct/Struct.java b/jme3-core/src/main/java/com/jme3/util/struct/Struct.java new file mode 100644 index 0000000000..cca31e0831 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/Struct.java @@ -0,0 +1,12 @@ +package com.jme3.util.struct; + +/** + * Classes implementing this interface are considered struct-like constructs. + * Class fields using one of the com.jme3.util.struct.fields.* classes as type + * will be considered part of the struct and must be declared as final, + * everything else will be ignored. + * + * @author Riccardo Balbo + */ +public interface Struct { +} \ No newline at end of file diff --git a/jme3-core/src/main/java/com/jme3/util/struct/StructField.java b/jme3-core/src/main/java/com/jme3/util/struct/StructField.java new file mode 100644 index 0000000000..d968bdc5fc --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/StructField.java @@ -0,0 +1,104 @@ +package com.jme3.util.struct; + +/** + * A field of a struct + * + * @author Riccardo Balbo + */ +public abstract class StructField { + + private int position; + protected T value; + protected boolean isUpdateNeeded = true; + private String name; + private int depth = 0; + private int group = 0; + + protected StructField(int position, String name, T value) { + this.position = position; + this.value = value; + this.name = name; + } + + /** + * Get depth of the field + * + * @return + */ + public int getDepth() { + return depth; + } + + /** + * Get the group to which this field belongs (eg. a parent struct) + * + * @return id of the group + */ + public int getGroup() { + return group; + } + + void setGroup(int group) { + this.group = group; + } + + void setDepth(int depth) { + this.depth = depth; + } + + void setPosition(int position) { + this.position = position; + } + + /** + * Get position inside the struct + * + * @return position inside the struct + */ + public int getPosition() { + return position; + } + + /** + * Get value of this field + * + * @return value + */ + public T getValue() { + return value; + } + + /** + * Check if field needs update + * + * @return + */ + public boolean isUpdateNeeded() { + return isUpdateNeeded; + } + + /** + * Clear update needed used internally + */ + public void clearUpdateNeeded() { + isUpdateNeeded = false; + } + + /** + * Get simple name of the field + * + * @return + */ + public String getName() { + String friendlyName; + if (name != null) friendlyName = name; + else friendlyName = value.getClass().getSimpleName(); + return friendlyName; + } + + @Override + public String toString() { + return "StructField[" + getName() + "] = " + value.toString(); + } + +} \ No newline at end of file diff --git a/jme3-core/src/main/java/com/jme3/util/struct/StructStd140BufferObject.java b/jme3-core/src/main/java/com/jme3/util/struct/StructStd140BufferObject.java new file mode 100644 index 0000000000..a45fd47c5d --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/StructStd140BufferObject.java @@ -0,0 +1,106 @@ +package com.jme3.util.struct; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; + +import com.jme3.export.InputCapsule; +import com.jme3.export.JmeExporter; +import com.jme3.export.JmeImporter; +import com.jme3.export.OutputCapsule; +import com.jme3.shader.bufferobject.BufferObject; +import com.jme3.shader.bufferobject.layout.Std140Layout; + +/** + * A BufferObject containing a struct serialized with Std140 layout. + * + * @author Riccardo Balbo + */ +public class StructStd140BufferObject extends BufferObject { + private static final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(StructStd140BufferObject.class.getName()); + private transient Class rootStruct; + private transient List> resolvedFields; + private final Std140Layout std140 = new Std140Layout(); + + /** + * Create an empty Struct buffer + * + * @param str + */ + public StructStd140BufferObject() { + } + + /** + * Internal only + */ + public StructStd140BufferObject(int id) { + super(id); + } + + /** + * Create a Struct buffer from a Struct + * @param str the source struct + */ + public StructStd140BufferObject(Struct str) { + this(); + update(str); + } + + private void loadLayout(Struct struct) { + ArrayList classFields = new ArrayList(); + resolvedFields = StructUtils.getFields(struct, classFields); + for (Field field : classFields) { + if (!Modifier.isFinal(field.getModifiers())) throw new RuntimeException("Can't load layout for " + struct + " every field must be final"); + } + rootStruct = struct.getClass(); + StructUtils.setStd140BufferLayout(resolvedFields, std140, this); + } + + /** + * Update data and layout (when needed) using a Struct class. + * + * @param struct + */ + public void update(Struct struct) { + boolean forceUpdate = false; + if (rootStruct != struct.getClass()) { + if (logger.isLoggable(java.util.logging.Level.FINE)) { + logger.log(java.util.logging.Level.FINE, "Change in layout {0} =/= {1} ", new Object[] { rootStruct, struct.getClass() }); + } + loadLayout(struct); + forceUpdate = true; + } + StructUtils.updateBufferData(resolvedFields, forceUpdate, std140, this); + } + + @Override + public void write(JmeExporter ex) throws IOException { + super.write(ex); + OutputCapsule oc = ex.getCapsule(this); + oc.write(rootStruct.getName(), "rootClass", null); + } + + @Override + public void read(JmeImporter im) throws IOException { + super.read(im); + InputCapsule ic = im.getCapsule(this); + try { + String rootClass = ic.readString("rootClass", null); + if (rootClass == null) throw new Exception("rootClass is undefined"); + Class rootStructClass = (Class) Class.forName(rootClass); + Struct rootStruct = rootStructClass.newInstance(); + loadLayout(rootStruct); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public StructStd140BufferObject clone() { + StructStd140BufferObject clone = (StructStd140BufferObject) super.clone(); + return clone; + } + +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/StructUtils.java b/jme3-core/src/main/java/com/jme3/util/struct/StructUtils.java new file mode 100644 index 0000000000..195f0bc412 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/StructUtils.java @@ -0,0 +1,186 @@ +package com.jme3.util.struct; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +import com.jme3.shader.bufferobject.BufferObject; +import com.jme3.shader.bufferobject.BufferRegion; +import com.jme3.shader.bufferobject.layout.BufferLayout; +import com.jme3.shader.bufferobject.layout.Std140Layout; + +/** + * StructUtils + * + * @author Riccardo Balbo + */ +public class StructUtils { + private static final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(StructUtils.class.getName()); + + private static final Comparator> fieldComparator = new Comparator>() { + @Override + public int compare(final StructField a, final StructField b) { + return a.getPosition() - b.getPosition(); + } + }; + + /** + * In-place sort a List of StructFields accordingly to their position + * + * @param fields + * list to sort + * @return the passed list + */ + public static List> sortFields(List> fields) { + fields.sort(fieldComparator); + return fields; + } + + /** + * Get sorted List of StructFields from a Struct object + * + * @param struct + * the struct object + * @return the sorted list + */ + public static List> getFields(Struct struct) { + return getFields(struct, 0, null); + } + + public static List> getFields(Struct struct, ArrayList classFields) { + return getFields(struct, 0, classFields); + } + + private static List> getFields(Struct struct, int depth, ArrayList classFields) {// , + // final + // List + // fieldList) + // { + ArrayList> structFields = new ArrayList>(); + + Class structClass = struct.getClass(); + try { + // for each class field + // Extract class fields into a StructField List + // (Note: class methods are iterated in undefined order) + Field[] fields = structClass.getDeclaredFields(); + for (Field field : fields) { + field.setAccessible(true); + + Object o = field.get(struct); + if (o instanceof StructField) { + if (classFields != null) classFields.add(field); + StructField so = (StructField) o; + structFields.add(so); + } + } + + // Sort by position + sortFields(structFields); + + ArrayList> expandedStructFields = new ArrayList>(); + + // Expand sub struct and arrays to flat list + for (int i = 0; i < structFields.size(); i++) { + StructField so = structFields.get(i); + if (so.getValue() instanceof Struct) { // substruct + List> subStruct = getFields((Struct) so.getValue(), depth + 1, classFields); + expandedStructFields.addAll(subStruct); + } else if (so.getValue().getClass().isArray() && Struct.class.isAssignableFrom(so.getValue().getClass().getComponentType())) { // array + // of + // substruct + + Struct[] subA = (Struct[]) so.getValue(); + for (int j = 0; j < subA.length; j++) { + Struct sub = subA[j]; + List> subStruct = getFields(sub, depth + 1, classFields); + expandedStructFields.addAll(subStruct); + } + + } else { + so.setDepth(depth); + so.setGroup(struct.hashCode()); + expandedStructFields.add(so); + } + } + structFields = expandedStructFields; + + // Recompute positions in flat list + int i = 0; + for (StructField so : structFields) { + so.setPosition(i); + i++; + } + + } catch (final Exception e) { + throw new RuntimeException(e); + } + assert structFields.size() != 0; + return structFields; + } + + public static BufferObject setStd140BufferLayout(List> fields, Std140Layout serializer, BufferObject out) {// , + // final + // List + // fieldList) + // { + + int pos = -1; + + List regions = new ArrayList(); + + for (int i = 0; i < fields.size(); i++) { + StructField f = fields.get(i); + Object v = f.getValue(); + + int basicAlignment = serializer.getBasicAlignment(v); + int length = serializer.estimateSize(v); + + int start = serializer.align(pos + 1, basicAlignment); + int end = start + length - 1; + + if ((i == fields.size() - 1) || f.getGroup()!= fields.get(i + 1).getGroup()){// > fields.get(i + 1).getDepth()) { + end = (serializer.align(end, 16)) - 1; + } + + BufferRegion r = new BufferRegion(start, end); + regions.add(r); + pos = end; + } + + out.setRegions(regions); + + return out; + } + + /** + * Update data using a List of StructFields The current layout will be + * maintained unless previously invalidated + * + * @param fields + * sorted list of struct fields + */ + public static void updateBufferData(List> fields, boolean forceUpdate, BufferLayout layout, BufferObject out) { + boolean updateNeeded = false; + for (StructField f : fields) { + if (forceUpdate || f.isUpdateNeeded()) { + + BufferRegion region = out.getRegion(f.getPosition()); + if (logger.isLoggable(java.util.logging.Level.FINER)) { + logger.log(java.util.logging.Level.FINER, "Serialize {0} in {1} ", new Object[] { f, region }); + } + layout.write(region.getData(), f.getValue()); + region.markDirty(); + f.clearUpdateNeeded(); + updateNeeded = true; + } else { + if (logger.isLoggable(java.util.logging.Level.FINER)) { + logger.log(java.util.logging.Level.FINER, "Already up to date. Skip {0} ", new Object[] { f }); + } + } + } + if (updateNeeded) out.setUpdateNeeded(false); + } + +} \ No newline at end of file diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/BooleanArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/BooleanArrayField.java new file mode 100644 index 0000000000..d4b8ffaafe --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/BooleanArrayField.java @@ -0,0 +1,32 @@ +package com.jme3.util.struct.fields; + +import com.jme3.util.struct.StructField; + +public class BooleanArrayField extends StructField { + + public BooleanArrayField(int position, String name, Boolean[] value) { + super(position, name, value); + initializeToZero(); + } + + public BooleanArrayField(int position, String name, int length) { + super(position, name, new Boolean[length]); + initializeToZero(); + } + + private void initializeToZero() { + for (int i = 0; i < value.length; i++) { + if (value[i] == null) value[i] = false; + } + } + + /** + * Get value and mark field for update + * + * @return + */ + public Boolean[] getValueForUpdate() { + isUpdateNeeded = true; + return value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/BooleanField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/BooleanField.java new file mode 100644 index 0000000000..df64b95d97 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/BooleanField.java @@ -0,0 +1,20 @@ +package com.jme3.util.struct.fields; + +import com.jme3.util.struct.StructField; + +public class BooleanField extends StructField { + + public BooleanField(int position, String name, Boolean value) { + super(position, name, value); + } + + /** + * Set value for this field and mark for update + * + * @param value + */ + public void setValue(Boolean value) { + isUpdateNeeded = true; + this.value = value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/ColorRGBAArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/ColorRGBAArrayField.java new file mode 100644 index 0000000000..bd1be43683 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/ColorRGBAArrayField.java @@ -0,0 +1,33 @@ +package com.jme3.util.struct.fields; + +import com.jme3.math.ColorRGBA; +import com.jme3.util.struct.StructField; + +public class ColorRGBAArrayField extends StructField { + + public ColorRGBAArrayField(int position, String name, ColorRGBA[] value) { + super(position, name, value); + initializeToZero(); + } + + public ColorRGBAArrayField(int position, String name, int length) { + super(position, name, new ColorRGBA[length]); + initializeToZero(); + } + + private void initializeToZero() { + for (int i = 0; i < value.length; i++) { + if (value[i] == null) value[i] = new ColorRGBA(); + } + } + + /** + * Get value and mark field for update + * + * @return + */ + public ColorRGBA[] getValueForUpdate() { + isUpdateNeeded = true; + return value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/ColorRGBAField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/ColorRGBAField.java new file mode 100644 index 0000000000..7b0420f92e --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/ColorRGBAField.java @@ -0,0 +1,21 @@ +package com.jme3.util.struct.fields; + +import com.jme3.math.ColorRGBA; +import com.jme3.util.struct.StructField; + +public class ColorRGBAField extends StructField { + + public ColorRGBAField(int position, String name, ColorRGBA value) { + super(position, name, value); + } + + /** + * Get value and mark field for update + * + * @return + */ + public ColorRGBA getValueForUpdate() { + isUpdateNeeded = true; + return value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/FloatArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/FloatArrayField.java new file mode 100644 index 0000000000..a5f9c8fb4b --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/FloatArrayField.java @@ -0,0 +1,32 @@ +package com.jme3.util.struct.fields; + +import com.jme3.util.struct.StructField; + +public class FloatArrayField extends StructField { + + public FloatArrayField(int position, String name, Float[] value) { + super(position, name, value); + initializeToZero(); + } + + public FloatArrayField(int position, String name, int length) { + super(position, name, new Float[length]); + initializeToZero(); + } + + private void initializeToZero() { + for (int i = 0; i < value.length; i++) { + if (value[i] == null) value[i] = 0f; + } + } + + /** + * Get value and mark field for update + * + * @return + */ + public Float[] getValueForUpdate() { + isUpdateNeeded = true; + return value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/FloatField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/FloatField.java new file mode 100644 index 0000000000..f5044d6272 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/FloatField.java @@ -0,0 +1,20 @@ +package com.jme3.util.struct.fields; + +import com.jme3.util.struct.StructField; + +public class FloatField extends StructField { + + public FloatField(int position, String name, Float value) { + super(position, name, value); + } + + /** + * Set value for this field and mark for update + * + * @param value + */ + public void setValue(Float value) { + isUpdateNeeded = true; + this.value = value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/IntArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/IntArrayField.java new file mode 100644 index 0000000000..ec54880699 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/IntArrayField.java @@ -0,0 +1,32 @@ +package com.jme3.util.struct.fields; + +import com.jme3.util.struct.StructField; + +public class IntArrayField extends StructField { + + public IntArrayField(int position, String name, Integer[] value) { + super(position, name, value); + initializeToZero(); + } + + public IntArrayField(int position, String name, Integer length) { + super(position, name, new Integer[length]); + initializeToZero(); + } + + private void initializeToZero() { + for (int i = 0; i < value.length; i++) { + if (value[i] == null) value[i] = 0; + } + } + + /** + * Get value and mark field for update + * + * @return + */ + public Integer[] getValueForUpdate() { + isUpdateNeeded = true; + return value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/IntField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/IntField.java new file mode 100644 index 0000000000..c047def194 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/IntField.java @@ -0,0 +1,20 @@ +package com.jme3.util.struct.fields; + +import com.jme3.util.struct.StructField; + +public class IntField extends StructField { + + public IntField(int position, String name, Integer value) { + super(position, name, value); + } + + /** + * Set value for this field and mark for update + * + * @param value + */ + public void setValue(Integer value) { + isUpdateNeeded = true; + this.value = value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix3fArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix3fArrayField.java new file mode 100644 index 0000000000..c65aee9b61 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix3fArrayField.java @@ -0,0 +1,33 @@ +package com.jme3.util.struct.fields; + +import com.jme3.math.Matrix3f; +import com.jme3.util.struct.StructField; + +public class Matrix3fArrayField extends StructField { + + public Matrix3fArrayField(int position, String name, Matrix3f[] value) { + super(position, name, value); + initializeToZero(); + } + + public Matrix3fArrayField(int position, String name, int length) { + super(position, name, new Matrix3f[length]); + initializeToZero(); + } + + private void initializeToZero() { + for (int i = 0; i < value.length; i++) { + if (value[i] == null) value[i] = new Matrix3f(); + } + } + + /** + * Get value and mark field for update + * + * @return + */ + public Matrix3f[] getValueForUpdate() { + isUpdateNeeded = true; + return value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix3fField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix3fField.java new file mode 100644 index 0000000000..3f6289a766 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix3fField.java @@ -0,0 +1,21 @@ +package com.jme3.util.struct.fields; + +import com.jme3.math.Matrix3f; +import com.jme3.util.struct.StructField; + +public class Matrix3fField extends StructField { + + public Matrix3fField(int position, String name, Matrix3f value) { + super(position, name, value); + } + + /** + * Get value and mark field for update + * + * @return + */ + public Matrix3f getValueForUpdate() { + isUpdateNeeded = true; + return value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix4fArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix4fArrayField.java new file mode 100644 index 0000000000..717b87706a --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix4fArrayField.java @@ -0,0 +1,33 @@ +package com.jme3.util.struct.fields; + +import com.jme3.math.Matrix4f; +import com.jme3.util.struct.StructField; + +public class Matrix4fArrayField extends StructField { + + public Matrix4fArrayField(int position, String name, Matrix4f[] value) { + super(position, name, value); + initializeToZero(); + } + + public Matrix4fArrayField(int position, String name, int length) { + super(position, name, new Matrix4f[length]); + initializeToZero(); + } + + private void initializeToZero() { + for (int i = 0; i < value.length; i++) { + if (value[i] == null) value[i] = new Matrix4f(); + } + } + + /** + * Get value and mark field for update + * + * @return + */ + public Matrix4f[] getValueForUpdate() { + isUpdateNeeded = true; + return value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix4fField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix4fField.java new file mode 100644 index 0000000000..8babc949d5 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix4fField.java @@ -0,0 +1,21 @@ +package com.jme3.util.struct.fields; + +import com.jme3.math.Matrix4f; +import com.jme3.util.struct.StructField; + +public class Matrix4fField extends StructField { + + public Matrix4fField(int position, String name, Matrix4f value) { + super(position, name, value); + } + + /** + * Get value and mark field for update + * + * @return + */ + public Matrix4f getValueForUpdate() { + isUpdateNeeded = true; + return value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/QuaternionArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/QuaternionArrayField.java new file mode 100644 index 0000000000..a6b1d90f8d --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/QuaternionArrayField.java @@ -0,0 +1,33 @@ +package com.jme3.util.struct.fields; + +import com.jme3.math.Quaternion; +import com.jme3.util.struct.StructField; + +public class QuaternionArrayField extends StructField { + + public QuaternionArrayField(int position, String name, Quaternion[] value) { + super(position, name, value); + initializeToZero(); + } + + public QuaternionArrayField(int position, String name, int length) { + super(position, name, new Quaternion[length]); + initializeToZero(); + } + + private void initializeToZero() { + for (int i = 0; i < value.length; i++) { + if (value[i] == null) value[i] = new Quaternion(); + } + } + + /** + * Get value and mark field for update + * + * @return + */ + public Quaternion[] getValueForUpdate() { + isUpdateNeeded = true; + return value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/QuaternionField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/QuaternionField.java new file mode 100644 index 0000000000..9377a1ffdf --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/QuaternionField.java @@ -0,0 +1,21 @@ +package com.jme3.util.struct.fields; + +import com.jme3.math.Quaternion; +import com.jme3.util.struct.StructField; + +public class QuaternionField extends StructField { + + public QuaternionField(int position, String name, Quaternion value) { + super(position, name, value); + } + + /** + * Get value and mark field for update + * + * @return + */ + public Quaternion getValueForUpdate() { + isUpdateNeeded = true; + return value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/SubStructArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/SubStructArrayField.java new file mode 100644 index 0000000000..9c8a3d29ef --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/SubStructArrayField.java @@ -0,0 +1,33 @@ +package com.jme3.util.struct.fields; + +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; + +import com.jme3.util.struct.Struct; +import com.jme3.util.struct.StructField; + +public class SubStructArrayField extends StructField { + + public SubStructArrayField(int position, String name, T[] value) { + super(position, name, value); + initializeToZero((Class) value[0].getClass()); + } + + public SubStructArrayField(int position, String name, int length, Class structClass) { + super(position, name, (T[]) Array.newInstance(structClass, length)); + initializeToZero(structClass); + } + + private void initializeToZero(Class structClass) { + for (int i = 0; i < value.length; i++) { + if (value[i] == null) try { + Constructor constructor = structClass.getDeclaredConstructor(); + constructor.setAccessible(true); + value[i] = constructor.newInstance(); + } catch (Exception e) { + throw new RuntimeException("Can't create new instance of " + structClass + " default constructor is missing? ",e); + } + } + } + +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/SubStructField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/SubStructField.java new file mode 100644 index 0000000000..56eb890c4d --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/SubStructField.java @@ -0,0 +1,13 @@ +package com.jme3.util.struct.fields; + +import com.jme3.util.struct.Struct; +import com.jme3.util.struct.StructField; + + +public class SubStructField extends StructField { + + public SubStructField(int position, String name, T value) { + super(position, name, value); + } + +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector2fArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector2fArrayField.java new file mode 100644 index 0000000000..b61f2439ff --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector2fArrayField.java @@ -0,0 +1,33 @@ +package com.jme3.util.struct.fields; + +import com.jme3.math.Vector2f; +import com.jme3.util.struct.StructField; + +public class Vector2fArrayField extends StructField { + + public Vector2fArrayField(int position, String name, Vector2f[] value) { + super(position, name, value); + initializeToZero(); + } + + public Vector2fArrayField(int position, String name, int length) { + super(position, name, new Vector2f[length]); + initializeToZero(); + } + + private void initializeToZero() { + for (int i = 0; i < value.length; i++) { + if (value[i] == null) value[i] = new Vector2f(); + } + } + + /** + * Get value and mark field for update + * + * @return + */ + public Vector2f[] getValueForUpdate() { + isUpdateNeeded = true; + return value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector2fField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector2fField.java new file mode 100644 index 0000000000..98340263f4 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector2fField.java @@ -0,0 +1,21 @@ +package com.jme3.util.struct.fields; + +import com.jme3.math.Vector2f; +import com.jme3.util.struct.StructField; + +public class Vector2fField extends StructField { + + public Vector2fField(int position, String name, Vector2f value) { + super(position, name, value); + } + + /** + * Get value and mark field for update + * + * @return + */ + public Vector2f getValueForUpdate() { + isUpdateNeeded = true; + return value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector3fArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector3fArrayField.java new file mode 100644 index 0000000000..a3340a1703 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector3fArrayField.java @@ -0,0 +1,33 @@ +package com.jme3.util.struct.fields; + +import com.jme3.math.Vector3f; +import com.jme3.util.struct.StructField; + +public class Vector3fArrayField extends StructField { + + public Vector3fArrayField(int position, String name, Vector3f[] value) { + super(position, name, value); + initializeToZero(); + } + + public Vector3fArrayField(int position, String name, int length) { + super(position, name, new Vector3f[length]); + initializeToZero(); + } + + private void initializeToZero() { + for (int i = 0; i < value.length; i++) { + if (value[i] == null) value[i] = new Vector3f(); + } + } + + /** + * Get value and mark field for update + * + * @return + */ + public Vector3f[] getValueForUpdate() { + isUpdateNeeded = true; + return value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector3fField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector3fField.java new file mode 100644 index 0000000000..d5a0dcbcf5 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector3fField.java @@ -0,0 +1,21 @@ +package com.jme3.util.struct.fields; + +import com.jme3.math.Vector3f; +import com.jme3.util.struct.StructField; + +public class Vector3fField extends StructField { + + public Vector3fField(int position, String name, Vector3f value) { + super(position, name, value); + } + + /** + * Get value and mark field for update + * + * @return + */ + public Vector3f getValueForUpdate() { + isUpdateNeeded = true; + return value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector4fArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector4fArrayField.java new file mode 100644 index 0000000000..894480b6b7 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector4fArrayField.java @@ -0,0 +1,33 @@ +package com.jme3.util.struct.fields; + +import com.jme3.math.Vector4f; +import com.jme3.util.struct.StructField; + +public class Vector4fArrayField extends StructField { + + public Vector4fArrayField(int position, String name, Vector4f[] value) { + super(position, name, value); + initializeToZero(); + } + + public Vector4fArrayField(int position, String name, int length) { + super(position, name, new Vector4f[length]); + initializeToZero(); + } + + private void initializeToZero() { + for (int i = 0; i < value.length; i++) { + if (value[i] == null) value[i] = new Vector4f(); + } + } + + /** + * Get value and mark field for update + * + * @return + */ + public Vector4f[] getValueForUpdate() { + isUpdateNeeded = true; + return value; + } +} diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector4fField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector4fField.java new file mode 100644 index 0000000000..20828f4231 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector4fField.java @@ -0,0 +1,21 @@ +package com.jme3.util.struct.fields; + +import com.jme3.math.Vector4f; +import com.jme3.util.struct.StructField; + +public class Vector4fField extends StructField { + + public Vector4fField(int position, String name, Vector4f value) { + super(position, name, value); + } + + /** + * Get value and mark field for update + * + * @return + */ + public Vector4f getValueForUpdate() { + isUpdateNeeded = true; + return value; + } +} diff --git a/jme3-core/src/test/java/com/jme3/util/StructTest.java b/jme3-core/src/test/java/com/jme3/util/StructTest.java new file mode 100644 index 0000000000..65b4e77692 --- /dev/null +++ b/jme3-core/src/test/java/com/jme3/util/StructTest.java @@ -0,0 +1,218 @@ +package com.jme3.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.nio.ByteBuffer; + +import com.jme3.shader.bufferobject.BufferObject; +import com.jme3.shader.bufferobject.BufferRegion; +import com.jme3.shader.bufferobject.DirtyRegionsIterator; +import com.jme3.shader.bufferobject.layout.Std140Layout; +import com.jme3.util.struct.Struct; +import com.jme3.util.struct.StructField; +import com.jme3.util.struct.StructUtils; +import com.jme3.util.struct.fields.*; + +import org.junit.Test; + +public class StructTest { + static class SubStruct implements Struct { + public final IntField subIntField0 = new IntField(0, "subIntField0", 100); + public final FloatField subFloatField1 = new FloatField(1, "subFloatField1", 100f); + + } + + static class TestStruct implements Struct { + public final IntField intField0 = new IntField(0, "intField0", 100); + public final FloatField floatField1 = new FloatField(1, "floatField1", 100f); + public final FloatArrayField floatFieldArray2 = new FloatArrayField(2, "floatFieldArray2", new Float[] { 100f, 200f, 300f }); + public final SubStructField structField3 = new SubStructField(3, "structField3", new SubStruct()); + public final SubStructArrayField structArrayField5 = new SubStructArrayField(5, "structArrayField5", new SubStruct[] { new SubStruct(), new SubStruct() }); + public final BooleanField boolField6 = new BooleanField(6, "boolField6", true); + } + + @Test + public void testFieldsExtraction() { + TestStruct test = new TestStruct(); + java.util.List> fields = StructUtils.getFields(test); + String checkString = ""; + for (StructField f : fields) { + String s = f.getPosition() + " " + f.getName() + " " + f.getDepth() + "\n"; + checkString += s; + } + String expectedString = "0 intField0 0\n1 floatField1 0\n2 floatFieldArray2 0\n3 subIntField0 1\n4 subFloatField1 1\n5 subIntField0 1\n6 subFloatField1 1\n7 subIntField0 1\n8 subFloatField1 1\n9 boolField6 0\n"; + assertEquals(expectedString, checkString); + } + + @Test + public void testStd140Serialization() { + TestStruct test = new TestStruct(); + java.util.List> fields = StructUtils.getFields(test); + + Std140Layout layout = new Std140Layout(); + BufferObject bo = new BufferObject(); + StructUtils.setStd140BufferLayout(fields, layout, bo); + System.out.println(bo.getData().getInt()); + + StructUtils.updateBufferData(fields, false, layout, bo); + + ByteBuffer bbf = bo.getData(); + + String expectedData = "100 0 0 0 0 0 -56 66 0 0 0 0 0 0 0 0 0 0 -56 66 0 0 0 0 0 0 0 0 0 0 0 0 0 0 72 67 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -106 67 0 0 0 0 0 0 0 0 0 0 0 0 100 0 0 0 0 0 -56 66 0 0 0 0 0 0 0 0 100 0 0 0 0 0 -56 66 0 0 0 0 0 0 0 0 100 0 0 0 0 0 -56 66 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "; + String actualData = ""; + while (bbf.hasRemaining()) { + actualData += bbf.get() + " "; + } + assertEquals(expectedData, actualData); + } + + @Test + public void testStd140PartialUpdate() { + TestStruct test = new TestStruct(); + + Std140Layout layout = new Std140Layout(); + BufferObject bo = new BufferObject(); + + java.util.List> fields = StructUtils.getFields(test); + StructUtils.setStd140BufferLayout(fields, layout, bo); + int bolength = bo.getData().limit(); + assertEquals(128, bolength); + assertEquals(128, bo.getData().capacity()); + + int nUpdated; + + // Update full + System.out.println("Test Full Update"); + StructUtils.updateBufferData(fields, false, layout, bo); + DirtyRegionsIterator dirtyI = bo.getDirtyRegions(); + nUpdated = 0; + assertTrue(bo.isUpdateNeeded()); + while (true) { + BufferRegion region = dirtyI.getNext(); + if (region == null) break; + int start = region.getStart(); + int end = region.getEnd(); + System.out.println("Update from " + start + " to " + end + " in buffer of length " + bolength); + assertEquals(0, start); + assertEquals(127,end); + assertTrue(region.isFullBufferRegion()); + assertTrue(region.isDirty()); + region.clearDirty(); + assertFalse(region.isDirty()); + nUpdated++; + } + bo.clearUpdateNeeded(); + assertFalse(bo.isUpdateNeeded()); + assertEquals(1, nUpdated); + + + // Update nothing + System.out.println("Test No Update"); + fields = StructUtils.getFields(test); + StructUtils.updateBufferData(fields, false, layout, bo); + dirtyI = bo.getDirtyRegions(); + assertFalse(bo.isUpdateNeeded()); + nUpdated = 0; + while (true) { + BufferRegion region = dirtyI.getNext(); + if (region == null) break; + + assertFalse("Update not expected", true); + nUpdated++; + } + bo.clearUpdateNeeded(); + assertFalse(bo.isUpdateNeeded()); + assertEquals(0, nUpdated); + + // Update something + System.out.println("Test Partial Update"); + test.floatField1.setValue(2f); + StructUtils.updateBufferData(fields, false, layout, bo); + dirtyI = bo.getDirtyRegions(); + assertTrue(bo.isUpdateNeeded()); + nUpdated = 0; + while (true) { + BufferRegion region = dirtyI.getNext(); + if (region == null) break; + assertTrue(region.isDirty()); + + int start = region.getStart(); + int end = region.getEnd(); + System.out.println("Update from " + start + " to " + end + " in buffer of length " + bolength); + assertEquals(4, start); + assertEquals(7, end); + assertFalse(region.isFullBufferRegion()); + assertTrue(region.isDirty()); + region.clearDirty(); + nUpdated++; + } + bo.clearUpdateNeeded(); + assertFalse(bo.isUpdateNeeded()); + assertEquals(1, nUpdated); + + // Update something2 + System.out.println("Test Partial Update 2"); + test.floatField1.setValue(2f); + test.boolField6.setValue(true); + StructUtils.updateBufferData(fields, false, layout, bo); + dirtyI = bo.getDirtyRegions(); + assertTrue(bo.isUpdateNeeded()); + nUpdated = 0; + while (true) { + BufferRegion region = dirtyI.getNext(); + if (region == null) break; + assertTrue(region.isDirty()); + + int start = region.getStart(); + int end = region.getEnd(); + System.out.println("Update from " + start + " to " + end + " in buffer of length " + bolength); + if (nUpdated == 0) { + assertEquals(4, start); + assertEquals(7, end); + } else { + assertEquals(112, start); + assertEquals(127, end); + } + assertFalse(region.isFullBufferRegion()); + assertTrue(region.isDirty()); + region.clearDirty(); + nUpdated++; + } + bo.clearUpdateNeeded(); + assertFalse(bo.isUpdateNeeded()); + assertEquals(2, nUpdated); + + + // Update substruct + System.out.println("Test Partial Update Substruct"); + test.structField3.getValue().subIntField0.setValue(3); + StructUtils.updateBufferData(fields, false, layout, bo); + dirtyI = bo.getDirtyRegions(); + assertTrue(bo.isUpdateNeeded()); + nUpdated = 0; + while (true) { + BufferRegion region = dirtyI.getNext(); + if (region == null) break; + assertTrue(region.isDirty()); + + int start = region.getStart(); + int end = region.getEnd(); + System.out.println("Update from " + start + " to " + end + " in buffer of length " + bolength); + assertEquals(64, start); + assertEquals(67, end); + assertFalse(region.isFullBufferRegion()); + assertTrue(region.isDirty()); + region.clearDirty(); + nUpdated++; + } + bo.clearUpdateNeeded(); + assertFalse(bo.isUpdateNeeded()); + assertEquals(1, nUpdated); + + + + + } +} diff --git a/jme3-examples/src/main/java/jme3test/material/TestUBO.java b/jme3-examples/src/main/java/jme3test/material/TestUBO.java new file mode 100644 index 0000000000..e24a1a7204 --- /dev/null +++ b/jme3-examples/src/main/java/jme3test/material/TestUBO.java @@ -0,0 +1,149 @@ +package jme3test.material; + +import com.jme3.app.SimpleApplication; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.math.Matrix3f; +import com.jme3.math.Matrix4f; +import com.jme3.math.Vector3f; +import com.jme3.scene.Geometry; +import com.jme3.scene.shape.Box; +import com.jme3.system.AppSettings; +import com.jme3.util.struct.Struct; +import com.jme3.util.struct.StructStd140BufferObject; +import com.jme3.util.struct.fields.ColorRGBAField; +import com.jme3.util.struct.fields.FloatField; +import com.jme3.util.struct.fields.IntField; +import com.jme3.util.struct.fields.Matrix3fField; +import com.jme3.util.struct.fields.Matrix4fField; +import com.jme3.util.struct.fields.SubStructArrayField; +import com.jme3.util.struct.fields.SubStructField; +import com.jme3.util.struct.fields.Vector3fField; + +/** + * This is an example of UBO usage and an unit test for the Struct Buffer Object. + * If everything works as expected, a green square should appear, if not the square will be red. + * + * RenderDOC can be used to see the UBO on the gpu. + */ +public class TestUBO extends SimpleApplication { + + public final static class PointLight implements Struct { + public final Vector3fField position = new Vector3fField(0, "position", new Vector3f()); + public final FloatField radius = new FloatField(1, "radius", 1f); + public final ColorRGBAField color = new ColorRGBAField(2, "color", new ColorRGBA()); + + PointLight() { + } + + PointLight(Vector3f position, float radius, ColorRGBA color) { + this.position.getValueForUpdate().set(position); + this.color.getValueForUpdate().set(color); + this.radius.setValue(radius); + } + } + + public final static class DirectLight implements Struct { + public final Vector3fField direction = new Vector3fField(0, "direction", new Vector3f()); + public final ColorRGBAField color = new ColorRGBAField(1, "color", new ColorRGBA()); + + DirectLight() { + } + + DirectLight(Vector3f direction, ColorRGBA color) { + this.direction.getValueForUpdate().set(direction); + this.color.getValueForUpdate().set(color); + } + } + + public final static class Lights implements Struct { + public final IntField nDirectLights = new IntField(0, "nDirectLights", 1); + + public final SubStructField test1 = new SubStructField(1, "test1", new DirectLight( + new Vector3f(0,1,0), + ColorRGBA.Blue + )); + + public final IntField test2 = new IntField(2, "test2", 111); + + public final SubStructField test3 = new SubStructField(3, "test3", new PointLight( + new Vector3f(7,9,7), + 99f, + ColorRGBA.Red + )); + + public final IntField test4 = new IntField(4, "test4", 222); + + public final Matrix3fField test5 = new Matrix3fField(5,"test5",new Matrix3f(1,2,3,4,5,6,7,8,9)); + public final IntField test6 = new IntField(6, "test6", 333); + + public final Matrix4fField test7 = new Matrix4fField(7, "test7", new Matrix4f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)); + public final IntField test8 = new IntField(8, "test8", 444); + + public final SubStructArrayField directLights = new SubStructArrayField(9, "directLights", new DirectLight[] { + new DirectLight(new Vector3f(0, 0, 1), ColorRGBA.Green), + }); + + public final IntField nPointLights = new IntField(10, "nPointLights", 2); + + public final SubStructArrayField pointLights = new SubStructArrayField(11, "pointLights", new PointLight[] { + new PointLight(new Vector3f(5, 9, 7), 9f, ColorRGBA.Red), + new PointLight(new Vector3f(5, 10, 7), 8f, ColorRGBA.Green), + }); + public final SubStructArrayField pointLights2 = new SubStructArrayField(12, "pointLights2", new PointLight[] { + new PointLight(new Vector3f(3, 9, 7), 91f, ColorRGBA.Green), + new PointLight(new Vector3f(3, 10, 7), 90f, ColorRGBA.Blue), + }); + + public final IntField test13 = new IntField(13, "test13", 555); + + } + + StructStd140BufferObject lightsBO; + StructStd140BufferObject lightsBO2; + Lights lights = new Lights(); + int n = 0; + + @Override + public void simpleInitApp() { + flyCam.setEnabled(false); + + lightsBO = new StructStd140BufferObject(lights); + lightsBO2 = lightsBO.clone(); + + Material mat = new Material(assetManager, "jme3test/ubo/TestUBO.j3md"); + mat.setUniformBufferObject("TestStruct1", lightsBO); + mat.setUniformBufferObject("TestStruct2", lightsBO2); + + Geometry geo = new Geometry("Test", new Box(1, 1, 1)); + geo.setMaterial(mat); + rootNode.attachChild(geo); + geo.setLocalTranslation(0, 0, 1); + + cam.lookAt(geo.getWorldTranslation(), Vector3f.UNIT_Y); + } + + @Override + public void update() { + super.update(); + n++; + if (n > 10) { + lights.test8.setValue(999999); + lights.test13.setValue(111); + lightsBO2.update(lights); + } + } + + + public static void main(String[] args) { + AppSettings sett = new AppSettings(true); + sett.putBoolean("GraphicsDebug", true); + sett.setRenderer(AppSettings.LWJGL_OPENGL32); + TestUBO app = new TestUBO(); + app.setSettings(sett); + app.setPauseOnLostFocus(false); + app.start(); + } + +} + diff --git a/jme3-examples/src/main/resources/jme3test/ubo/TestUBO.frag b/jme3-examples/src/main/resources/jme3test/ubo/TestUBO.frag new file mode 100644 index 0000000000..3be23b6876 --- /dev/null +++ b/jme3-examples/src/main/resources/jme3test/ubo/TestUBO.frag @@ -0,0 +1,107 @@ + +struct PointLight { + vec3 position; + float radius; + vec4 color; +}; + +struct DirectLight { + vec3 direction; + vec4 color; +}; + +struct TestStruct{ + int nDirectLights; + DirectLight test1; + int test2; + PointLight test3; + int test4; + mat3 test5; + int test6; + mat4 test7; + int test8; + DirectLight directLights[1]; + int nPointLights; + PointLight pointLights[2]; + PointLight pointLights2[2]; + int test13; +}; + +layout (std140) uniform m_TestStruct1 { + TestStruct testStruct1; +}; + +layout (std140) uniform m_TestStruct2 { + TestStruct testStruct2; +}; + +out vec4 outFragColor; + +void main(){ + if( + testStruct1.nDirectLights==1 + &&testStruct1.test1.direction==vec3(0,1,0) + &&testStruct1.test1.color==vec4(0,0,1,1) + &&testStruct1.test2==111 + &&testStruct1.test3.position==vec3(7.,9.,7.) + &&testStruct1.test3.radius==99. + &&testStruct1.test3.color==vec4(1.,0.,0.,1.) + &&testStruct1.test4==222 + &&testStruct1.test5==transpose(mat3(1,2,3,4,5,6,7,8,9) ) + &&testStruct1.test6==333 + &&testStruct1.test7==transpose(mat4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)) + &&testStruct1.test8==444 + &&testStruct1.directLights[0].direction==vec3(0.,0.,1.) + &&testStruct1.directLights[0].color==vec4(0.,1.,0.,1.) + &&testStruct1.nPointLights==2 + &&testStruct1.pointLights[0].position==vec3(5.,9.,7.) + &&testStruct1.pointLights[0].radius==9. + &&testStruct1.pointLights[0].color==vec4(1.,0.,0.,1.) + &&testStruct1.pointLights[1].position==vec3(5.,10.,7.) + &&testStruct1.pointLights[1].radius==8. + &&testStruct1.pointLights[1].color==vec4(0.,1.,0.,1.) + &&testStruct1.pointLights2[0].position==vec3(3.,9.,7.) + &&testStruct1.pointLights2[0].radius==91. + &&testStruct1.pointLights2[0].color==vec4(0.,1.,0.,1.) + &&testStruct1.pointLights2[1].position==vec3(3.,10.,7.) + &&testStruct1.pointLights2[1].radius==90. + &&testStruct1.pointLights2[1].color==vec4(0.,0.,1.,1.) + &&testStruct1.test13==555 + + && + + testStruct2.nDirectLights==1 + &&testStruct2.test1.direction==vec3(0,1,0) + &&testStruct2.test1.color==vec4(0,0,1,1) + &&testStruct2.test2==111 + &&testStruct2.test3.position==vec3(7.,9.,7.) + &&testStruct2.test3.radius==99. + &&testStruct2.test3.color==vec4(1.,0.,0.,1.) + &&testStruct2.test4==222 + &&testStruct2.test5==transpose(mat3(1,2,3,4,5,6,7,8,9) ) + &&testStruct2.test6==333 + &&testStruct2.test7==transpose(mat4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)) + &&testStruct2.test8==999999 + &&testStruct2.directLights[0].direction==vec3(0.,0.,1.) + &&testStruct2.directLights[0].color==vec4(0.,1.,0.,1.) + &&testStruct2.nPointLights==2 + &&testStruct2.pointLights[0].position==vec3(5.,9.,7.) + &&testStruct2.pointLights[0].radius==9. + &&testStruct2.pointLights[0].color==vec4(1.,0.,0.,1.) + &&testStruct2.pointLights[1].position==vec3(5.,10.,7.) + &&testStruct2.pointLights[1].radius==8. + &&testStruct2.pointLights[1].color==vec4(0.,1.,0.,1.) + &&testStruct2.pointLights2[0].position==vec3(3.,9.,7.) + &&testStruct2.pointLights2[0].radius==91. + &&testStruct2.pointLights2[0].color==vec4(0.,1.,0.,1.) + &&testStruct2.pointLights2[1].position==vec3(3.,10.,7.) + &&testStruct2.pointLights2[1].radius==90. + &&testStruct2.pointLights2[1].color==vec4(0.,0.,1.,1.) + &&testStruct2.test13==111 + + ){ + outFragColor=vec4(0,1,0,1); + }else{ + outFragColor=vec4(1,0,0,1); + } +} \ No newline at end of file diff --git a/jme3-examples/src/main/resources/jme3test/ubo/TestUBO.j3md b/jme3-examples/src/main/resources/jme3test/ubo/TestUBO.j3md new file mode 100644 index 0000000000..91bfb29121 --- /dev/null +++ b/jme3-examples/src/main/resources/jme3test/ubo/TestUBO.j3md @@ -0,0 +1,16 @@ + +MaterialDef TestUBO { + MaterialParameters { + UniformBufferObject TestStruct1 + UniformBufferObject TestStruct2 + } + + Technique { + VertexShader GLSL150 : jme3test/ubo/TestUBO.vert + FragmentShader GLSL150 : jme3test/ubo/TestUBO.frag + + WorldParameters { + ViewProjectionMatrix + } + } +} diff --git a/jme3-examples/src/main/resources/jme3test/ubo/TestUBO.vert b/jme3-examples/src/main/resources/jme3test/ubo/TestUBO.vert new file mode 100644 index 0000000000..1f78b5f9da --- /dev/null +++ b/jme3-examples/src/main/resources/jme3test/ubo/TestUBO.vert @@ -0,0 +1,7 @@ + +in vec3 inPosition; +uniform mat4 g_ViewProjectionMatrix; +void main(){ + vec4 modelSpacePos = vec4(inPosition, 1.0); + gl_Position = g_ViewProjectionMatrix*modelSpacePos; +} \ No newline at end of file From d706348d370dd1255c8aa61200431ad44a3cf182 Mon Sep 17 00:00:00 2001 From: Riccardo Balbo Date: Sun, 21 Jan 2024 18:01:59 +0100 Subject: [PATCH 2/4] Fixes UBO context and location handling --- .../com/jme3/renderer/opengl/GLRenderer.java | 29 ++++++++++++++----- .../com/jme3/shader/ShaderBufferBlock.java | 3 +- .../shader/bufferobject/BufferRegion.java | 4 +-- .../bufferobject/DirtyRegionsIterator.java | 16 +++++----- 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index f9aa2203bd..0667539a51 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -1475,8 +1475,11 @@ protected void updateShaderBufferBlock(final Shader shader, final ShaderBufferBl case UniformBufferObject: { setUniformBufferObject(bindingPoint, bufferObject); // rebind buffer if needed if (bufferBlock.isUpdateNeeded()) { - int blockIndex = gl3.glGetUniformBlockIndex(shaderId, bufferBlock.getName()); - bufferBlock.setLocation(blockIndex); + int blockIndex = bufferBlock.getLocation(); + if (blockIndex < 0) { + blockIndex = gl3.glGetUniformBlockIndex(shaderId, bufferBlock.getName()); + bufferBlock.setLocation(blockIndex); + } if (bufferBlock.getLocation() != NativeObject.INVALID_ID) { gl3.glUniformBlockBinding(shaderId, bufferBlock.getLocation(), bindingPoint); } @@ -1486,8 +1489,11 @@ protected void updateShaderBufferBlock(final Shader shader, final ShaderBufferBl case ShaderStorageBufferObject: { setShaderStorageBufferObject(bindingPoint, bufferObject); // rebind buffer if needed if (bufferBlock.isUpdateNeeded() ) { - int blockIndex = gl4.glGetProgramResourceIndex(shaderId, GL4.GL_SHADER_STORAGE_BLOCK, bufferBlock.getName()); - bufferBlock.setLocation(blockIndex); + int blockIndex = bufferBlock.getLocation(); + if (blockIndex < 0) { + blockIndex = gl4.glGetProgramResourceIndex(shaderId, GL4.GL_SHADER_STORAGE_BLOCK, bufferBlock.getName()); + bufferBlock.setLocation(blockIndex); + } if (bufferBlock.getLocation() != NativeObject.INVALID_ID) { gl4.glShaderStorageBlockBinding(shaderId, bufferBlock.getLocation(), bindingPoint); } @@ -1560,7 +1566,7 @@ public void updateShaderSourceData(ShaderSource source) { source.setId(id); if (debug && caps.contains(Caps.GLDebug)) { - if(source.getName() != null) glext.glObjectLabel(GLExt.GL_SHADER, id, source.getName()); + if(source.getName()!=null) glext.glObjectLabel(GLExt.GL_SHADER, id, source.getName()); } } else { throw new RendererException("Cannot recompile shader source"); @@ -2217,7 +2223,7 @@ public void setFrameBuffer(FrameBuffer fb) { context.boundFB = fb; if (debug && caps.contains(Caps.GLDebug)) { - if (fb.getName() != null) glext.glObjectLabel(GL3.GL_FRAMEBUFFER, fb.getId(), fb.getName()); + if (fb.getName() != null) glext.glObjectLabel(GL3.GL_FRAMEBUFFER, fb.getId(), fb.getName()); } } } @@ -2761,6 +2767,10 @@ public void setUniformBufferObject(int bindingPoint, BufferObject bufferObject) bufferObject.setBinding(bindingPoint); + if (debug && caps.contains(Caps.GLDebug)) { + if (bufferObject.getName() != null) glext.glObjectLabel(GLExt.GL_BUFFER, bufferObject.getId(), bufferObject.getName()); + } + } @Override @@ -2774,6 +2784,10 @@ public void setShaderStorageBufferObject(int bindingPoint, BufferObject bufferOb context.boundBO[bindingPoint] = bufferObject.getWeakRef(); } bufferObject.setBinding(bindingPoint); + + if (debug && caps.contains(Caps.GLDebug)) { + if (bufferObject.getName() != null) glext.glObjectLabel(GLExt.GL_BUFFER, bufferObject.getId(), bufferObject.getName()); + } } /** @@ -3023,6 +3037,7 @@ private void updateBufferData(int type, BufferObject bo) { } gl.glBufferData(type, bbf, usage); gl3.glBindBuffer(type, 0); + reg.clearDirty(); break; } else { if (logger.isLoggable(java.util.logging.Level.FINER)) { @@ -3030,8 +3045,8 @@ private void updateBufferData(int type, BufferObject bo) { } gl.glBufferSubData(type, reg.getStart(), reg.getData()); gl3.glBindBuffer(type, 0); + reg.clearDirty(); } - reg.clearDirty(); } bo.clearUpdateNeeded(); } diff --git a/jme3-core/src/main/java/com/jme3/shader/ShaderBufferBlock.java b/jme3-core/src/main/java/com/jme3/shader/ShaderBufferBlock.java index fb39090f42..915c628083 100644 --- a/jme3-core/src/main/java/com/jme3/shader/ShaderBufferBlock.java +++ b/jme3-core/src/main/java/com/jme3/shader/ShaderBufferBlock.java @@ -93,7 +93,8 @@ public void clearUpdateNeeded(){ /** * Reset this storage block. */ - public void reset(){ + public void reset() { + location = -1; updateNeeded = true; } diff --git a/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferRegion.java b/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferRegion.java index 06efbd82a1..dea0dbb4d0 100644 --- a/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferRegion.java +++ b/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferRegion.java @@ -44,14 +44,14 @@ public ByteBuffer getData() { source = d; int currentPos = source.position(); int currentLimit = source.limit(); - source.position(start); assert end < source.capacity() : "Can't set limit at " + end + " on capacity " + source.capacity(); source.limit(end + 1); + source.position(start); slice = source.slice(); slice.order(source.order()); assert slice.limit() == (end - start + 1) : "Capacity is " + slice.limit() + " but " + (end - start + 1) + " expected"; - source.position(currentPos); source.limit(currentLimit); + source.position(currentPos); } slice.rewind(); return slice; diff --git a/jme3-core/src/main/java/com/jme3/shader/bufferobject/DirtyRegionsIterator.java b/jme3-core/src/main/java/com/jme3/shader/bufferobject/DirtyRegionsIterator.java index ecaaab171d..910d333847 100644 --- a/jme3-core/src/main/java/com/jme3/shader/bufferobject/DirtyRegionsIterator.java +++ b/jme3-core/src/main/java/com/jme3/shader/bufferobject/DirtyRegionsIterator.java @@ -21,14 +21,14 @@ public ByteBuffer getData() { source = d; int currentPos = source.position(); int currentLimit = source.limit(); - source.position(0); source.limit(source.capacity()); + source.position(0); slice = source.slice(); - source.position(currentPos); source.limit(currentLimit); + source.position(currentPos); } - slice.position(start); slice.limit(end); + slice.position(start); return slice; } @@ -64,20 +64,18 @@ public BufferRegion getNext() { return dirtyRegion; } - int dirtRegions = 0; while (pos < bufferObject.regions.size()) { BufferRegion dr = bufferObject.regions.get(pos++); if (dr.isDirty()) { - if (dirtRegions == 0) dirtyRegion.start = dr.start; + if (dirtyRegion.regions.size() == 0) dirtyRegion.start = dr.start; dirtyRegion.end = dr.end; - dirtRegions++; dirtyRegion.regions.add(dr); - } else if (dirtRegions != 0) break; + } else if (dirtyRegion.regions.size() != 0) break; } - if (dirtRegions == 0) return null; - dirtyRegion.fullBufferRegion = dirtRegions == bufferObject.regions.size(); + if (dirtyRegion.regions.size() == 0) return null; + dirtyRegion.fullBufferRegion = dirtyRegion.regions.size() == bufferObject.regions.size(); dirtyRegion.markDirty(); return dirtyRegion; From 42630c24c926d4950d9cfde825f33ed8f6b79c3b Mon Sep 17 00:00:00 2001 From: Riccardo Balbo Date: Sun, 21 Jan 2024 18:16:13 +0100 Subject: [PATCH 3/4] DirtyRegionsIterator extends Iterator, update copyright --- jme-angle/src/native/angle | 1 + .../main/java/com/jme3/material/Material.java | 2 +- .../java/com/jme3/material/Technique.java | 2 +- .../logic/DefaultTechniqueDefLogic.java | 2 +- .../logic/MultiPassLightingLogic.java | 2 +- .../SinglePassAndImageBasedLightingLogic.java | 2 +- .../logic/SinglePassLightingLogic.java | 2 +- .../logic/StaticPassLightingLogic.java | 2 +- .../material/logic/TechniqueDefLogic.java | 2 +- .../src/main/java/com/jme3/math/FastMath.java | 2 +- .../java/com/jme3/renderer/RenderContext.java | 2 +- .../main/java/com/jme3/renderer/Renderer.java | 2 +- .../com/jme3/renderer/opengl/GLRenderer.java | 4 +- .../com/jme3/shader/ShaderBufferBlock.java | 2 +- .../main/java/com/jme3/shader/Uniform.java | 2 +- .../main/java/com/jme3/shader/VarType.java | 2 +- .../shader/bufferobject/BufferObject.java | 31 ++++++++++++++ .../shader/bufferobject/BufferRegion.java | 31 ++++++++++++++ .../bufferobject/DirtyRegionsIterator.java | 40 ++++++++++++++++++- .../bufferobject/layout/BufferLayout.java | 31 ++++++++++++++ .../shader/bufferobject/layout/RawLayout.java | 31 ++++++++++++++ .../bufferobject/layout/Std140Layout.java | 31 ++++++++++++++ .../java/com/jme3/system/NullRenderer.java | 2 +- .../java/com/jme3/util/struct/Struct.java | 31 ++++++++++++++ .../com/jme3/util/struct/StructField.java | 31 ++++++++++++++ .../util/struct/StructStd140BufferObject.java | 31 ++++++++++++++ .../com/jme3/util/struct/StructUtils.java | 31 ++++++++++++++ .../util/struct/fields/BooleanArrayField.java | 31 ++++++++++++++ .../jme3/util/struct/fields/BooleanField.java | 31 ++++++++++++++ .../struct/fields/ColorRGBAArrayField.java | 31 ++++++++++++++ .../util/struct/fields/ColorRGBAField.java | 31 ++++++++++++++ .../util/struct/fields/FloatArrayField.java | 31 ++++++++++++++ .../jme3/util/struct/fields/FloatField.java | 31 ++++++++++++++ .../util/struct/fields/IntArrayField.java | 31 ++++++++++++++ .../com/jme3/util/struct/fields/IntField.java | 31 ++++++++++++++ .../struct/fields/Matrix3fArrayField.java | 31 ++++++++++++++ .../util/struct/fields/Matrix3fField.java | 31 ++++++++++++++ .../struct/fields/Matrix4fArrayField.java | 31 ++++++++++++++ .../util/struct/fields/Matrix4fField.java | 31 ++++++++++++++ .../struct/fields/QuaternionArrayField.java | 31 ++++++++++++++ .../util/struct/fields/QuaternionField.java | 31 ++++++++++++++ .../struct/fields/SubStructArrayField.java | 31 ++++++++++++++ .../util/struct/fields/SubStructField.java | 31 ++++++++++++++ .../struct/fields/Vector2fArrayField.java | 31 ++++++++++++++ .../util/struct/fields/Vector2fField.java | 31 ++++++++++++++ .../struct/fields/Vector3fArrayField.java | 31 ++++++++++++++ .../util/struct/fields/Vector3fField.java | 31 ++++++++++++++ .../struct/fields/Vector4fArrayField.java | 31 ++++++++++++++ .../util/struct/fields/Vector4fField.java | 31 ++++++++++++++ .../test/java/com/jme3/util/StructTest.java | 10 ++--- 50 files changed, 1022 insertions(+), 24 deletions(-) create mode 160000 jme-angle/src/native/angle diff --git a/jme-angle/src/native/angle b/jme-angle/src/native/angle new file mode 160000 index 0000000000..2319607679 --- /dev/null +++ b/jme-angle/src/native/angle @@ -0,0 +1 @@ +Subproject commit 2319607679d7781ff9bab5e821a34574ecb0bcc3 diff --git a/jme3-core/src/main/java/com/jme3/material/Material.java b/jme3-core/src/main/java/com/jme3/material/Material.java index 7940642b6c..8874c5e58d 100644 --- a/jme3-core/src/main/java/com/jme3/material/Material.java +++ b/jme3-core/src/main/java/com/jme3/material/Material.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/jme3-core/src/main/java/com/jme3/material/Technique.java b/jme3-core/src/main/java/com/jme3/material/Technique.java index 58e8cd6896..5091028a85 100644 --- a/jme3-core/src/main/java/com/jme3/material/Technique.java +++ b/jme3-core/src/main/java/com/jme3/material/Technique.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/jme3-core/src/main/java/com/jme3/material/logic/DefaultTechniqueDefLogic.java b/jme3-core/src/main/java/com/jme3/material/logic/DefaultTechniqueDefLogic.java index 9c5636c2ac..ca8f7d1efa 100644 --- a/jme3-core/src/main/java/com/jme3/material/logic/DefaultTechniqueDefLogic.java +++ b/jme3-core/src/main/java/com/jme3/material/logic/DefaultTechniqueDefLogic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/jme3-core/src/main/java/com/jme3/material/logic/MultiPassLightingLogic.java b/jme3-core/src/main/java/com/jme3/material/logic/MultiPassLightingLogic.java index 10774c0ef0..9340d3560d 100644 --- a/jme3-core/src/main/java/com/jme3/material/logic/MultiPassLightingLogic.java +++ b/jme3-core/src/main/java/com/jme3/material/logic/MultiPassLightingLogic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/jme3-core/src/main/java/com/jme3/material/logic/SinglePassAndImageBasedLightingLogic.java b/jme3-core/src/main/java/com/jme3/material/logic/SinglePassAndImageBasedLightingLogic.java index d9921298d6..127586fcde 100644 --- a/jme3-core/src/main/java/com/jme3/material/logic/SinglePassAndImageBasedLightingLogic.java +++ b/jme3-core/src/main/java/com/jme3/material/logic/SinglePassAndImageBasedLightingLogic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/jme3-core/src/main/java/com/jme3/material/logic/SinglePassLightingLogic.java b/jme3-core/src/main/java/com/jme3/material/logic/SinglePassLightingLogic.java index dd6cd9c385..58240569ef 100644 --- a/jme3-core/src/main/java/com/jme3/material/logic/SinglePassLightingLogic.java +++ b/jme3-core/src/main/java/com/jme3/material/logic/SinglePassLightingLogic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/jme3-core/src/main/java/com/jme3/material/logic/StaticPassLightingLogic.java b/jme3-core/src/main/java/com/jme3/material/logic/StaticPassLightingLogic.java index 516ee202bd..fe35dc4c4d 100644 --- a/jme3-core/src/main/java/com/jme3/material/logic/StaticPassLightingLogic.java +++ b/jme3-core/src/main/java/com/jme3/material/logic/StaticPassLightingLogic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/jme3-core/src/main/java/com/jme3/material/logic/TechniqueDefLogic.java b/jme3-core/src/main/java/com/jme3/material/logic/TechniqueDefLogic.java index de43c22b6e..31f970a176 100644 --- a/jme3-core/src/main/java/com/jme3/material/logic/TechniqueDefLogic.java +++ b/jme3-core/src/main/java/com/jme3/material/logic/TechniqueDefLogic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/jme3-core/src/main/java/com/jme3/math/FastMath.java b/jme3-core/src/main/java/com/jme3/math/FastMath.java index c32f31174c..2993c7eed0 100644 --- a/jme3-core/src/main/java/com/jme3/math/FastMath.java +++ b/jme3-core/src/main/java/com/jme3/math/FastMath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java b/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java index 4d8b9c4e1a..ea6088afb9 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java +++ b/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/jme3-core/src/main/java/com/jme3/renderer/Renderer.java b/jme3-core/src/main/java/com/jme3/renderer/Renderer.java index 9dcb038f2a..c92de923ae 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/Renderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/Renderer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 0667539a51..60e6b30265 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2023 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -3028,7 +3028,7 @@ private void updateBufferData(int type, BufferObject bo) { DirtyRegionsIterator it = bo.getDirtyRegions(); BufferRegion reg; - while ((reg = it.getNext()) != null) { + while ((reg = it.next()) != null) { gl3.glBindBuffer(type, bufferId); if (reg.isFullBufferRegion()) { ByteBuffer bbf = bo.getData(); diff --git a/jme3-core/src/main/java/com/jme3/shader/ShaderBufferBlock.java b/jme3-core/src/main/java/com/jme3/shader/ShaderBufferBlock.java index 915c628083..20d2061420 100644 --- a/jme3-core/src/main/java/com/jme3/shader/ShaderBufferBlock.java +++ b/jme3-core/src/main/java/com/jme3/shader/ShaderBufferBlock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2018 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/jme3-core/src/main/java/com/jme3/shader/Uniform.java b/jme3-core/src/main/java/com/jme3/shader/Uniform.java index 0d4a18a15f..ebd42f9605 100644 --- a/jme3-core/src/main/java/com/jme3/shader/Uniform.java +++ b/jme3-core/src/main/java/com/jme3/shader/Uniform.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/jme3-core/src/main/java/com/jme3/shader/VarType.java b/jme3-core/src/main/java/com/jme3/shader/VarType.java index 3bc6716ea4..74f8a560d3 100644 --- a/jme3-core/src/main/java/com/jme3/shader/VarType.java +++ b/jme3-core/src/main/java/com/jme3/shader/VarType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferObject.java b/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferObject.java index de75393cfc..68a929d726 100644 --- a/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferObject.java +++ b/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferObject.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.shader.bufferobject; import java.io.IOException; diff --git a/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferRegion.java b/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferRegion.java index dea0dbb4d0..dc19965a73 100644 --- a/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferRegion.java +++ b/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferRegion.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.shader.bufferobject; import java.io.IOException; diff --git a/jme3-core/src/main/java/com/jme3/shader/bufferobject/DirtyRegionsIterator.java b/jme3-core/src/main/java/com/jme3/shader/bufferobject/DirtyRegionsIterator.java index 910d333847..2ed3c99a77 100644 --- a/jme3-core/src/main/java/com/jme3/shader/bufferobject/DirtyRegionsIterator.java +++ b/jme3-core/src/main/java/com/jme3/shader/bufferobject/DirtyRegionsIterator.java @@ -1,7 +1,39 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.shader.bufferobject; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; /** @@ -9,7 +41,7 @@ * * @author Riccardo Balbo */ -public class DirtyRegionsIterator { +public class DirtyRegionsIterator implements Iterator { private static class DirtyRegion extends BufferRegion { List regions = new ArrayList(); @@ -51,7 +83,11 @@ public void rewind() { pos = 0; } - public BufferRegion getNext() { + public boolean hasNext() { + return pos < bufferObject.regions.size(); + } + + public BufferRegion next() { dirtyRegion.bo = bufferObject; dirtyRegion.regions.clear(); diff --git a/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/BufferLayout.java b/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/BufferLayout.java index 66fed64242..78198ad025 100644 --- a/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/BufferLayout.java +++ b/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/BufferLayout.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.shader.bufferobject.layout; import java.nio.ByteBuffer; diff --git a/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/RawLayout.java b/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/RawLayout.java index 5b502b7db7..b1b54fcde9 100644 --- a/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/RawLayout.java +++ b/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/RawLayout.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.shader.bufferobject.layout; import java.nio.ByteBuffer; diff --git a/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/Std140Layout.java b/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/Std140Layout.java index 19454726a9..62aa54e0fb 100644 --- a/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/Std140Layout.java +++ b/jme3-core/src/main/java/com/jme3/shader/bufferobject/layout/Std140Layout.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.shader.bufferobject.layout; import java.nio.ByteBuffer; diff --git a/jme3-core/src/main/java/com/jme3/system/NullRenderer.java b/jme3-core/src/main/java/com/jme3/system/NullRenderer.java index 666222af23..978a24211e 100644 --- a/jme3-core/src/main/java/com/jme3/system/NullRenderer.java +++ b/jme3-core/src/main/java/com/jme3/system/NullRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/jme3-core/src/main/java/com/jme3/util/struct/Struct.java b/jme3-core/src/main/java/com/jme3/util/struct/Struct.java index cca31e0831..8b49d00248 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/Struct.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/Struct.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct; /** diff --git a/jme3-core/src/main/java/com/jme3/util/struct/StructField.java b/jme3-core/src/main/java/com/jme3/util/struct/StructField.java index d968bdc5fc..1390f45261 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/StructField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/StructField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct; /** diff --git a/jme3-core/src/main/java/com/jme3/util/struct/StructStd140BufferObject.java b/jme3-core/src/main/java/com/jme3/util/struct/StructStd140BufferObject.java index a45fd47c5d..4529239865 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/StructStd140BufferObject.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/StructStd140BufferObject.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct; import java.io.IOException; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/StructUtils.java b/jme3-core/src/main/java/com/jme3/util/struct/StructUtils.java index 195f0bc412..707788cd29 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/StructUtils.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/StructUtils.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct; import java.lang.reflect.Field; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/BooleanArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/BooleanArrayField.java index d4b8ffaafe..59e124b160 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/BooleanArrayField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/BooleanArrayField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.util.struct.StructField; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/BooleanField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/BooleanField.java index df64b95d97..558ac0945a 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/BooleanField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/BooleanField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.util.struct.StructField; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/ColorRGBAArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/ColorRGBAArrayField.java index bd1be43683..6bf444cc71 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/ColorRGBAArrayField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/ColorRGBAArrayField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.math.ColorRGBA; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/ColorRGBAField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/ColorRGBAField.java index 7b0420f92e..c640e6cbe5 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/ColorRGBAField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/ColorRGBAField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.math.ColorRGBA; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/FloatArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/FloatArrayField.java index a5f9c8fb4b..3356a3b10b 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/FloatArrayField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/FloatArrayField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.util.struct.StructField; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/FloatField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/FloatField.java index f5044d6272..e19aa4579b 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/FloatField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/FloatField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.util.struct.StructField; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/IntArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/IntArrayField.java index ec54880699..7fa1433e97 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/IntArrayField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/IntArrayField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.util.struct.StructField; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/IntField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/IntField.java index c047def194..1ee7caf174 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/IntField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/IntField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.util.struct.StructField; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix3fArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix3fArrayField.java index c65aee9b61..04ccabadf9 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix3fArrayField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix3fArrayField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.math.Matrix3f; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix3fField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix3fField.java index 3f6289a766..554969e5c4 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix3fField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix3fField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.math.Matrix3f; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix4fArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix4fArrayField.java index 717b87706a..ba116f569b 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix4fArrayField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix4fArrayField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.math.Matrix4f; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix4fField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix4fField.java index 8babc949d5..bafeb546da 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix4fField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Matrix4fField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.math.Matrix4f; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/QuaternionArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/QuaternionArrayField.java index a6b1d90f8d..343e0c85fe 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/QuaternionArrayField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/QuaternionArrayField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.math.Quaternion; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/QuaternionField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/QuaternionField.java index 9377a1ffdf..5214d5fc24 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/QuaternionField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/QuaternionField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.math.Quaternion; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/SubStructArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/SubStructArrayField.java index 9c8a3d29ef..2bd904d398 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/SubStructArrayField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/SubStructArrayField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import java.lang.reflect.Array; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/SubStructField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/SubStructField.java index 56eb890c4d..f9025985fd 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/SubStructField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/SubStructField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.util.struct.Struct; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector2fArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector2fArrayField.java index b61f2439ff..2870c8683c 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector2fArrayField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector2fArrayField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.math.Vector2f; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector2fField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector2fField.java index 98340263f4..84bc884404 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector2fField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector2fField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.math.Vector2f; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector3fArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector3fArrayField.java index a3340a1703..934941314a 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector3fArrayField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector3fArrayField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.math.Vector3f; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector3fField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector3fField.java index d5a0dcbcf5..72e75da5ad 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector3fField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector3fField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.math.Vector3f; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector4fArrayField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector4fArrayField.java index 894480b6b7..67ed7be7ca 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector4fArrayField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector4fArrayField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.math.Vector4f; diff --git a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector4fField.java b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector4fField.java index 20828f4231..f119deb2d3 100644 --- a/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector4fField.java +++ b/jme3-core/src/main/java/com/jme3/util/struct/fields/Vector4fField.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2024 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.jme3.util.struct.fields; import com.jme3.math.Vector4f; diff --git a/jme3-core/src/test/java/com/jme3/util/StructTest.java b/jme3-core/src/test/java/com/jme3/util/StructTest.java index 65b4e77692..6dace56b16 100644 --- a/jme3-core/src/test/java/com/jme3/util/StructTest.java +++ b/jme3-core/src/test/java/com/jme3/util/StructTest.java @@ -90,7 +90,7 @@ public void testStd140PartialUpdate() { nUpdated = 0; assertTrue(bo.isUpdateNeeded()); while (true) { - BufferRegion region = dirtyI.getNext(); + BufferRegion region = dirtyI.next(); if (region == null) break; int start = region.getStart(); int end = region.getEnd(); @@ -116,7 +116,7 @@ public void testStd140PartialUpdate() { assertFalse(bo.isUpdateNeeded()); nUpdated = 0; while (true) { - BufferRegion region = dirtyI.getNext(); + BufferRegion region = dirtyI.next(); if (region == null) break; assertFalse("Update not expected", true); @@ -134,7 +134,7 @@ public void testStd140PartialUpdate() { assertTrue(bo.isUpdateNeeded()); nUpdated = 0; while (true) { - BufferRegion region = dirtyI.getNext(); + BufferRegion region = dirtyI.next(); if (region == null) break; assertTrue(region.isDirty()); @@ -161,7 +161,7 @@ public void testStd140PartialUpdate() { assertTrue(bo.isUpdateNeeded()); nUpdated = 0; while (true) { - BufferRegion region = dirtyI.getNext(); + BufferRegion region = dirtyI.next(); if (region == null) break; assertTrue(region.isDirty()); @@ -193,7 +193,7 @@ public void testStd140PartialUpdate() { assertTrue(bo.isUpdateNeeded()); nUpdated = 0; while (true) { - BufferRegion region = dirtyI.getNext(); + BufferRegion region = dirtyI.next(); if (region == null) break; assertTrue(region.isDirty()); From b5a4b20a3275c881533fa2a3b5d4770c6bcac463 Mon Sep 17 00:00:00 2001 From: Riccardo Balbo Date: Sun, 21 Jan 2024 18:18:08 +0100 Subject: [PATCH 4/4] Add name to buffer object --- .../shader/bufferobject/BufferObject.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferObject.java b/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferObject.java index 68a929d726..cb7a87b89d 100644 --- a/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferObject.java +++ b/jme3-core/src/main/java/com/jme3/shader/bufferobject/BufferObject.java @@ -106,6 +106,7 @@ public static enum NatureHint { protected ByteBuffer data = null; protected ArrayList regions = new ArrayList(); + private String name; public BufferObject() { super(); @@ -373,4 +374,22 @@ public String toString() { return sb.toString(); } + /** + * Get name of the buffer object + * + * @return the name of this buffer object, can be null + */ + public String getName() { + return name; + } + + /** + * Set name for debugging purposes + * + * @param name + * the name of this buffer object + */ + public void setName(String name) { + this.name = name; + } }