From 2a3d6a7f23ecc5af4f18dfd37cde2db796d0c280 Mon Sep 17 00:00:00 2001 From: Trevor Flynn Date: Sat, 12 Dec 2020 18:59:41 -0900 Subject: [PATCH 01/11] Added initial implementation for KHR_lights_punctual gltf extension --- .../plugins/gltf/CustomContentManager.java | 1 + .../gltf/LightsPunctualExtensionLoader.java | 220 ++++++++++ .../scene/plugins/gltf/GltfLoaderTest.java | 15 + .../MODEL_ROUNDED_CUBE_PART_1/indices.bin | Bin 0 -> 20688 bytes .../MODEL_ROUNDED_CUBE_PART_1/normals.bin | 385 ++++++++++++++++++ .../MODEL_ROUNDED_CUBE_PART_1/positions.bin | Bin 0 -> 41472 bytes .../test/resources/gltf/lights/lights.gltf | 226 ++++++++++ 7 files changed, 847 insertions(+) create mode 100644 jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java create mode 100644 jme3-plugins/src/test/resources/gltf/lights/MODEL_ROUNDED_CUBE_PART_1/indices.bin create mode 100644 jme3-plugins/src/test/resources/gltf/lights/MODEL_ROUNDED_CUBE_PART_1/normals.bin create mode 100644 jme3-plugins/src/test/resources/gltf/lights/MODEL_ROUNDED_CUBE_PART_1/positions.bin create mode 100644 jme3-plugins/src/test/resources/gltf/lights/lights.gltf diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java index 9886f4df66..d849f37cea 100644 --- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java @@ -55,6 +55,7 @@ public class CustomContentManager { static { defaultExtensionLoaders.put("KHR_materials_pbrSpecularGlossiness", new PBRSpecGlossExtensionLoader()); + defaultExtensionLoaders.put("KHR_lights_punctual", new LightsPunctualExtensionLoader()); } void init(GltfLoader gltfLoader) { diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java new file mode 100644 index 0000000000..63706fefc9 --- /dev/null +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2009-2020 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.scene.plugins.gltf; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.jme3.asset.AssetKey; +import com.jme3.asset.AssetLoadException; +import com.jme3.light.DirectionalLight; +import com.jme3.light.Light; +import com.jme3.light.PointLight; +import com.jme3.light.SpotLight; +import com.jme3.math.ColorRGBA; +import com.jme3.math.FastMath; +import com.jme3.math.Vector3f; +import com.jme3.scene.Node; + +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; + +import static com.jme3.scene.plugins.gltf.GltfUtils.getAsColor; +import static com.jme3.scene.plugins.gltf.GltfUtils.getAsFloat; + +/** + * Extension loader for KHR_lights_punctual extension which allows + * for lights to be added to the node from the gltf model + * Created by Trevor Flynn - 12/12/2020 + */ +public class LightsPunctualExtensionLoader implements ExtensionLoader { + + private HashSet pendingNodes = new HashSet<>(); + private HashMap lightDefinitions = new HashMap<>(); + + @Override + public Object handleExtension(GltfLoader loader, String parentName, JsonElement parent, JsonElement extension, Object input) throws IOException { + if (input instanceof Node) { //We are processing a node + JsonObject jsonObject = extension.getAsJsonObject(); + if (jsonObject.has("light")) { //These will get run first when loading the gltf file + //Add node to queue + JsonElement indexElement = jsonObject.get("light"); + int index = indexElement.getAsInt(); + if (!lightDefinitions.containsKey(index)) { + pendingNodes.add(new NodeNeedingLight((Node) input, index)); + } else { + addLight((Node) input, index); + } + } else if (jsonObject.has("lights")) { //This will get run last + //Process the light definitions + JsonArray lights = jsonObject.getAsJsonArray("lights"); + + for (int i = 0; i < lights.size(); i++) { + //Create light definition + JsonObject light = lights.get(i).getAsJsonObject(); + String type = light.get("type").getAsString(); + + Light lightNode; + switch (type) { + case "point": + lightNode = buildPointLight(light); + break; + case "directional": + lightNode = buildDirectionalLight(light); + break; + case "spot": + lightNode = buildSpotLight(light); + break; + default: + throw new AssetLoadException("KHR_lights_punctual unsupported light type: " + type); + } + + lightDefinitions.put(i, lightNode); + } + + //Build any lights that are pending now that we have definitions + for (NodeNeedingLight nodeInNeed : pendingNodes) { + addLight(nodeInNeed.getNode(), nodeInNeed.getLightIndex()); + } + pendingNodes.clear(); + } else { + throw new AssetLoadException("KHR_lights_punctual extension malformed json"); + } + + return input; + } else { + throw new AssetLoadException("KHR_lights_punctual extension added on unsupported element"); + } + } + + private SpotLight buildSpotLight(JsonObject obj) { + //Get properties + String name = obj.has("name") ? obj.get("name").getAsString() : ""; + + //TODO: How do we incorporate intensity + float intensity = obj.has("intensity") ? obj.get("intensity").getAsFloat() : 1.0f; + ColorRGBA color = obj.has("color") ? GltfUtils.getAsColor(obj, "color") : new ColorRGBA(ColorRGBA.White); + float range = obj.has("range") ? obj.get("range").getAsFloat() : Float.POSITIVE_INFINITY; + + //Spot specific + JsonObject spot = obj.getAsJsonObject("spot"); + float innerConeAngle = spot != null && spot.has("innerConeAngle") ? spot.get("innerConeAngle").getAsFloat() : 0f; + float outerConeAngle = spot != null && spot.has("outerConeAngle") ? spot.get("outerConeAngle").getAsFloat() : ((float) Math.PI) / 4f; + + /* + Correct floating point error on half PI, GLTF spec says that the outerConeAngle + can be less or equal to PI/2, but JME requires less than PI/2. + We will being the angle within PI/2 if it is equal or larger than PI/2 + */ + if (outerConeAngle >= FastMath.HALF_PI) { + outerConeAngle = FastMath.HALF_PI - 0.000001f; + } + + SpotLight spotLight = new SpotLight(); + spotLight.setName(name); + spotLight.setColor(color); + spotLight.setSpotRange(range); + spotLight.setSpotInnerAngle(innerConeAngle); + spotLight.setSpotOuterAngle(outerConeAngle); + spotLight.setDirection(Vector3f.UNIT_Z.negate()); + + return spotLight; + } + + private DirectionalLight buildDirectionalLight(JsonObject obj) { + //Get properties + String name = obj.has("name") ? obj.get("name").getAsString() : ""; + + //TODO: How do we incorporate intensity + float intensity = obj.has("intensity") ? obj.get("intensity").getAsFloat() : 1.0f; + ColorRGBA color = obj.has("color") ? GltfUtils.getAsColor(obj, "color") : new ColorRGBA(ColorRGBA.White); + + DirectionalLight directionalLight = new DirectionalLight(); + directionalLight.setName(name); + directionalLight.setColor(color); + directionalLight.setDirection(Vector3f.UNIT_Z.negate()); + + return directionalLight; + } + + private PointLight buildPointLight(JsonObject obj) { + //Get properties + String name = obj.has("name") ? obj.get("name").getAsString() : ""; + + //TODO: How do we incorporate intensity + float intensity = obj.has("intensity") ? obj.get("intensity").getAsFloat() : 1.0f; + ColorRGBA color = obj.has("color") ? GltfUtils.getAsColor(obj, "color") : new ColorRGBA(ColorRGBA.White); + float range = obj.has("range") ? obj.get("range").getAsFloat() : Float.POSITIVE_INFINITY; + + PointLight pointLight = new PointLight(); + pointLight.setName(name); + pointLight.setColor(color); + pointLight.setRadius(range); + + return pointLight; + } + + private void addLight(Node node, int light) { + if (lightDefinitions.containsKey(light)) { + node.addLight(lightDefinitions.get(light)); + } else { + throw new AssetLoadException("KHR_lights_punctual extension accessed undefined light at index " + light); + } + } + + private class NodeNeedingLight { + private Node node; + private int lightIndex; + + public NodeNeedingLight(Node node, int lightIndex) { + this.node = node; + this.lightIndex = lightIndex; + } + + public Node getNode() { + return node; + } + + public void setNode(Node node) { + this.node = node; + } + + public int getLightIndex() { + return lightIndex; + } + + public void setLightIndex(int lightIndex) { + this.lightIndex = lightIndex; + } + } +} diff --git a/jme3-plugins/src/test/java/com/jme3/scene/plugins/gltf/GltfLoaderTest.java b/jme3-plugins/src/test/java/com/jme3/scene/plugins/gltf/GltfLoaderTest.java index ede109b8b8..25156ae33a 100644 --- a/jme3-plugins/src/test/java/com/jme3/scene/plugins/gltf/GltfLoaderTest.java +++ b/jme3-plugins/src/test/java/com/jme3/scene/plugins/gltf/GltfLoaderTest.java @@ -2,6 +2,7 @@ import com.jme3.asset.AssetLoadException; import com.jme3.asset.AssetManager; +import com.jme3.light.Light; import com.jme3.material.plugin.TestMaterialWrite; import com.jme3.scene.Node; import com.jme3.scene.Spatial; @@ -46,11 +47,25 @@ public void testLoadEmptyScene() { } } + @Test + public void testLightsPunctualExtension() { + try { + Spatial scene = assetManager.loadModel("gltf/lights/lights.gltf"); + dumpScene(scene, 0); + } catch (AssetLoadException ex) { + ex.printStackTrace(); + Assert.fail("Failed to import gltf model with lights punctual extension"); + } + } + private void dumpScene(Spatial s, int indent) { System.err.println(indentString.substring(0, indent) + s.getName() + " (" + s.getClass().getSimpleName() + ") / " + s.getLocalTransform().getTranslation().toString() + ", " + s.getLocalTransform().getRotation().toString() + ", " + s.getLocalTransform().getScale().toString()); + for (Light light : s.getLocalLightList()) { + System.err.println(indentString.substring(0, indent + 1) + " (" + light.getClass().getSimpleName() + ")" ); + } if (s instanceof Node) { Node n = (Node) s; for (Spatial spatial : n.getChildren()) { diff --git a/jme3-plugins/src/test/resources/gltf/lights/MODEL_ROUNDED_CUBE_PART_1/indices.bin b/jme3-plugins/src/test/resources/gltf/lights/MODEL_ROUNDED_CUBE_PART_1/indices.bin new file mode 100644 index 0000000000000000000000000000000000000000..f178d8db9cfdc9163f8e20fe0b639f73b2fed588 GIT binary patch literal 20688 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 literal 0 HcmV?d00001 diff --git a/jme3-plugins/src/test/resources/gltf/lights/MODEL_ROUNDED_CUBE_PART_1/normals.bin b/jme3-plugins/src/test/resources/gltf/lights/MODEL_ROUNDED_CUBE_PART_1/normals.bin new file mode 100644 index 0000000000..bdbda393f8 --- /dev/null +++ b/jme3-plugins/src/test/resources/gltf/lights/MODEL_ROUNDED_CUBE_PART_1/normals.bin @@ -0,0 +1,385 @@ +���~����;Ϡ�,e}���;Ϡ�,e}�������~�����Ϡ�,e}���;v����u�6v�;v����u�6v��Ϡ�,e}����v����u�6v�;ʋԾ��h�k;ʋԾ��h�k�v����u�6v��ʋԾ��h�k;�\ +��bW�SM;�\ +��bW�SM�ʋԾ��h�k��\ +��bW�SM;��'�B{A��L?;��'�B{A��L?��\ +��bW�SM���'�B{A��L?;B{A���'��L?;B{A���'��L?���'�B{A��L?�B{A���'��L?;�bW��\ +�SM;�bW��\ +�SM�B{A���'��L?��bW��\ +�SM;��h���Ծk;��h���Ծk��bW��\ +�SM���h���Ծk;��u�v��6v�;��u�v��6v����h���Ծk���u�v��6v�;,e}�Ϡ���;,e}�Ϡ������u�v��6v��,e}�Ϡ���;~�������;~��������,e}�Ϡ����������~�?���Ϡ�,e}?��;Ϡ�,e}?��;���~�?���Ϡ�,e}?6v��v����u?6v�;v����u?��;Ϡ�,e}?6v��v����u?k���Ծ��h?k;��Ծ��h?6v�;v����u?k���Ծ��h?SM��\ +��bW?SM;�\ +��bW?k;��Ծ��h?SM��\ +��bW?�L?���'�B{A?�L?;��'�B{A?SM;�\ +��bW?�L?���'�B{A?�L?�B{A���'?�L?;B{A���'?�L?;��'�B{A?�L?�B{A���'?SM��bW��\ +?SM;�bW��\ +?�L?;B{A���'?SM��bW��\ +?k���h����>k;��h����>SM;�bW��\ +?k���h����>6v����u�v�>6v�;��u�v�>k;��h����>6v����u�v�>���,e}�Ϡ>��;,e}�Ϡ>6v�;��u�v�>���,e}�Ϡ>���~����;��;~����;��;,e}�Ϡ>~�������;,e}����Ϡ>,e}���;Ϡ>~����;��;,e}����Ϡ>��u�6v��v�>��u�6v�;v�>,e}���;Ϡ>��u�6v��v�>��h�k����>��h�k;���>��u�6v�;v�>��h�k����>�bW�SM��\ +?�bW�SM;�\ +?��h�k;���>�bW�SM��\ +?B{A��L?���'?B{A��L?;��'?�bW�SM;�\ +?B{A��L?���'?��'��L?�B{A?��'��L?;B{A?B{A��L?;��'?��'��L?�B{A?�\ +�SM��bW?�\ +�SM;�bW?��'��L?;B{A?�\ +�SM��bW?��Ծk���h?��Ծk;��h?�\ +�SM;�bW?��Ծk���h?v��6v����u?v��6v�;��u?��Ծk;��h?v��6v����u?�����,e}?����;,e}?v��6v�;��u?�����,e}?������~�?�����;~�?����;,e}?~�?�����;,e}?Ϡ���;,e}?Ϡ����~�?������,e}?Ϡ���;��u?v��6v�;��u?v��6v��,e}?Ϡ������u?v��6v�;��h?��Ծk;��h?��Ծk���u?v��6v����h?��Ծk;�bW?�\ +�SM;�bW?�\ +�SM���h?��Ծk��bW?�\ +�SM;B{A?��'��L?;B{A?��'��L?��bW?�\ +�SM�B{A?��'��L?;��'?B{A��L?;��'?B{A��L?�B{A?��'��L?���'?B{A��L?;�\ +?�bW�SM;�\ +?�bW�SM���'?B{A��L?��\ +?�bW�SM;ʋ�>��h�k;ʋ�>��h�k��\ +?�bW�SM�ʋ�>��h�k;v�>��u�6v�;v�>��u�6v��ʋ�>��h�k�v�>��u�6v�;Ϡ>,e}���;Ϡ>,e}����v�>��u�6v��Ϡ>,e}���;��;~����;��;~�����Ϡ>,e}������;���~�?�>���,e}?�>��;,e}?��;��;~�?�>���,e}?v�>6v����u?v�>6v�;��u?�>��;,e}?v�>6v����u?���>k���h?���>k;��h?v�>6v�;��u?���>k���h?�\ +?SM��bW?�\ +?SM;�bW?���>k;��h?�\ +?SM��bW?��'?�L?�B{A?��'?�L?;B{A?�\ +?SM;�bW?��'?�L?�B{A?B{A?�L?���'?B{A?�L?;��'?��'?�L?;B{A?B{A?�L?���'?�bW?SM��\ +?�bW?SM;�\ +?B{A?�L?;��'?�bW?SM��\ +?��h?k����>��h?k;���>�bW?SM;�\ +?��h?k����>��u?6v��v�>��u?6v�;v�>��h?k;���>��u?6v��v�>,e}?���Ϡ>,e}?��;Ϡ>��u?6v�;v�>,e}?���Ϡ>~�?�����;~�?��;��;,e}?��;Ϡ>~����;��;,e}�Ϡ>��;,e}�Ϡ>���~����;���,e}�Ϡ>��;��u�v�>6v�;��u�v�>6v��,e}�Ϡ>�����u�v�>6v�;��h����>k;��h����>k���u�v�>6v����h����>k;�bW��\ +?SM;�bW��\ +?SM���h����>k��bW��\ +?SM;B{A���'?�L?;B{A���'?�L?��bW��\ +?SM�B{A���'?�L?;¡'�1{A?�L?;¡'�1{A?�L?�B{A���'?�L?�¡'�1{A?�L?;�\ +��bW?SM;�\ +��bW?SM�¡'�1{A?�L?��\ +��bW?SM;��Ծ��h?k;��Ծ��h?k��\ +��bW?SM���Ծ��h?k;U����u?6v�;U����u?6v����Ծ��h?k�U����u?6v�;Ϡ�,e}?��;Ϡ�,e}?���U����u?6v��Ϡ�,e}?��;���~�?��;���~�?���Ϡ�,e}?������~�?��;���,e}?Ϡ>��;,e}?Ϡ>��;~�?��;���,e}?Ϡ>6v����u?U�>6v�;��u?U�>��;,e}?Ϡ>6v����u?U�>k���h?���>k;��h?���>6v�;��u?U�>k���h?���>SM��bW?�\ +?SM;�bW?�\ +?k;��h?���>SM��bW?�\ +?�L?�1{A?¡'?�L?;1{A?¡'?SM;�bW?�\ +?�L?�1{A?¡'?�L?���'?B{A?�L?;��'?B{A?�L?;1{A?¡'?�L?���'?B{A?SM��\ +?�bW?SM;�\ +?�bW?�L?;��'?B{A?SM��\ +?�bW?k����>��h?k;���>��h?SM;�\ +?�bW?k����>��h?6v��v�>��u?6v�;v�>��u?k;���>��h?6v��v�>��u?���Ϡ>,e}?��;Ϡ>,e}?6v�;v�>��u?���Ϡ>,e}?�����;~�?��;��;~�?��;Ϡ>,e}?��;~�?��;Ϡ>,e}?��;Ϡ>,e}?�����;~�?���Ϡ>,e}?��;U�>��u?6v�;U�>��u?6v��Ϡ>,e}?���U�>��u?6v�;���>��h?k;���>��h?k�U�>��u?6v�����>��h?k;�\ +?�bW?SM;�\ +?�bW?SM����>��h?k��\ +?�bW?SM;¡'?1{A?�L?;¡'?1{A?�L?��\ +?�bW?SM�¡'?1{A?�L?;B{A?��'?�L?;B{A?��'?�L?�¡'?1{A?�L?�B{A?��'?�L?;�bW?�\ +?SM;�bW?�\ +?SM�B{A?��'?�L?��bW?�\ +?SM;��h?���>k;��h?���>k��bW?�\ +?SM���h?���>k;��u?v�>6v�;��u?v�>6v����h?���>k���u?v�>6v�;,e}?Ϡ>��;,e}?Ϡ>�����u?v�>6v��,e}?Ϡ>��;~�?��;��;~�?��;���,e}?Ϡ>���~����;���,e}���;Ϡ�,e}����Ϡ�~��������,e}���;Ϡ���u�6v�;v����u�6v��v��,e}����Ϡ���u�6v�;v����h�k;��Ծ��h�k���Ծ��u�6v��v����h�k;��Ծ�bW�SM;�\ +��bW�SM��\ +���h�k���Ծ�bW�SM;�\ +�B{A��L?;��'�B{A��L?���'��bW�SM��\ +�B{A��L?;��'���'��L?;B{A���'��L?�B{A�B{A��L?���'���'��L?;B{A��\ +�SM;�bW��\ +�SM��bW���'��L?�B{A��\ +�SM;�bW���Ծk;��h���Ծk���h��\ +�SM��bW���Ծk;��h�v��6v�;��u�v��6v����u���Ծk���h�v��6v�;��u�����;,e}������,e}�v��6v����u�����;,e}������;~��������~�������,e}������;~�����Ϡ>,e}���;Ϡ>,e}���;��;~�����Ϡ>,e}�6v��v�>��u�6v�;v�>��u���;Ϡ>,e}�6v��v�>��u�k����>��h�k;���>��h�6v�;v�>��u�k����>��h�SM��\ +?�bW�SM;�\ +?�bW�k;���>��h�SM��\ +?�bW��L?���'?B{A��L?;��'?B{A�SM;�\ +?�bW��L?���'?B{A��L?�1{A?¡'��L?;1{A?¡'��L?;��'?B{A��L?�1{A?¡'�SM��bW?�\ +�SM;�bW?�\ +��L?;1{A?¡'�SM��bW?�\ +�k���h?��Ծk;��h?��ԾSM;�bW?�\ +�k���h?��Ծ6v����u?U��6v�;��u?U��k;��h?��Ծ6v����u?U�����,e}?Ϡ���;,e}?Ϡ�6v�;��u?U�����,e}?Ϡ����~�?�����;~�?�����;,e}?Ϡ���;��;~���>��;,e}��>���,e}���;���~���>��;,e}�v�>6v�;��u�v�>6v����u��>���,e}�v�>6v�;��u����>k;��h����>k���h�v�>6v����u����>k;��h��\ +?SM;�bW��\ +?SM��bW����>k���h��\ +?SM;�bW���'?�L?;B{A���'?�L?�B{A��\ +?SM��bW���'?�L?;B{A�B{A?�L?;��'�B{A?�L?���'���'?�L?�B{A�B{A?�L?;��'��bW?SM;�\ +��bW?SM��\ +�B{A?�L?���'��bW?SM;�\ +���h?k;��Ծ��h?k���Ծ�bW?SM��\ +���h?k;��Ծ��u?6v�;v����u?6v��v����h?k���Ծ��u?6v�;v��,e}?��;Ϡ�,e}?���Ϡ���u?6v��v��,e}?��;Ϡ�~�?��;���~�?������,e}?���Ϡ����~��������,e}�Ϡ���;,e}�Ϡ���;~��������,e}�Ϡ�6v����u�v��6v�;��u�v����;,e}�Ϡ�6v����u�v��k���h���Ծk;��h���Ծ6v�;��u�v��k���h���ԾSM��bW��\ +�SM;�bW��\ +�k;��h���ԾSM��bW��\ +��L?�B{A���'��L?;B{A���'�SM;�bW��\ +��L?�B{A���'��L?���'�B{A��L?;��'�B{A��L?;B{A���'��L?���'�B{A�SM��\ +��bW�SM;�\ +��bW��L?;��'�B{A�SM��\ +��bW�k���Ծ��h�k;��Ծ��h�SM;�\ +��bW�k���Ծ��h�6v��v����u�6v�;v����u�k;��Ծ��h�6v��v����u����Ϡ�,e}���;Ϡ�,e}�6v�;v����u����Ϡ�,e}�������~����;���~����;Ϡ�,e}�������~�?��;���~�?��;��;~�?�����;~�?���~�?��;��;~�?��;��;~�?������~�?��������;~����;��;~����;���~��������~�����~�������;~�������;~����;���~����;~�?�����;~�?������~�?��;���~�?��;��;~��������~�������;~����;��;~����;���,e}����Ϡ>~�������;,e}�Ϡ���;�z�d;��;>�z�d;��;>,e}�Ϡ���;��u�v��6v�;��s��y��� >��s��y��� >��u�v��6v�;��h���Ծk;��g�{оJ��=��g�{оJ��=��h���Ծk;�bW��\ +�SM;��V�?;�B"�=��V�?;�B"�=�bW��\ +�SM;B{A���'��L?;U�@��$&�;��=U�@��$&�;��=B{A���'��L?;��'�B{A��L?;�$&�U�@�;��=�$&�U�@�;��=��'�B{A��L?;�\ +��bW�SM;.;���V�B"�=.;���V�B"�=�\ +��bW�SM;ʋԾ��h�k;�о��g�J��=�о��g�J��=ʋԾ��h�k;v����u�6v�;z����s�� >z����s�� >v����u�6v�;Ϡ�,e}���;�;��z�d;>Ϡ�,e}���;���~����;���,e}�Ϡ>�;��z�d;>�;��z�d;>���,e}�Ϡ>6v����u�v�>� ���s�z�>� ���s�z�>6v����u�v�>k���h����>J�����g�{�>J�����g�{�>k���h����>SM��bW��\ +?B"����V�.;?B"����V�.;?SM��bW��\ +?�L?�B{A���'?;��U�@��$&?;��U�@��$&?�L?�B{A���'?�L?���'�B{A?;���$&�U�@?;���$&�U�@?�L?���'�B{A?SM��\ +��bW?B"��.;���V?B"��.;���V?SM��\ +��bW?k���Ծ��h?J����о��g?J����о��g?k���Ծ��h?6v��v����u?� �z����s?� �z����s?6v��v����u?���Ϡ�,e}?d;��;��z?���Ϡ�,e}?������~�?�����,e}?d;��;��z?d;��;��z?�����,e}?v��6v����u?z��� ���s?z��� ���s?v��6v����u?��Ծk���h?�оJ�����g?�оJ�����g?��Ծk���h?�\ +�SM��bW?.;�B"����V?.;�B"����V?�\ +�SM��bW?��'��L?�B{A?�$&�;��U�@?�$&�;��U�@?��'��L?�B{A?B{A��L?���'?U�@�;���$&?U�@�;���$&?B{A��L?���'?�bW�SM��\ +?��V�B"��.;?��V�B"��.;?�bW�SM��\ +?��h�k����>��g�J�����>��g�J�����>��h�k����>��u�6v��v�>��s�� �z�>��s�� �z�>��u�6v��v�>,e}����Ϡ>�z�d;��;>��s�� �z�>�z�d;��;>��s��y��� >OYm�r������>OYm�r������>��s��y��� >��g�{оJ��=#�b�shɾ�^|>#�b�shɾ�^|>��g�{оJ��=��V�?;�B"�=l�R���� l>l�R���� l>��V�?;�B"�=U�@��$&�;��=Na=���"��3b>Na=���"��3b>U�@��$&�;��=�$&�U�@�;��=��"�Na=��3b>��"�Na=��3b>�$&�U�@�;��=.;���V�B"�=��l�R�� l>��l�R�� l>.;���V�B"�=�о��g�J��=shɾ#�b��^|>shɾ#�b��^|>�о��g�J��=z����s�� >����OYm�r��>z����s�� >�;��z�d;>� ���s�z�>����OYm�r��>����OYm�r��>� ���s�z�>J�����g�{�>�^|�#�b�sh�>�^|�#�b�sh�>J�����g�{�>B"����V�.;?� l�l�R��?� l�l�R��?B"����V�.;?;��U�@��$&?�3b�Na=���"?�3b�Na=���"?;��U�@��$&?;���$&�U�@?�3b���"�Na=?�3b���"�Na=?;���$&�U�@?B"��.;���V?� l���l�R?� l���l�R?B"��.;���V?J����о��g?�^|�shɾ#�b?�^|�shɾ#�b?J����о��g?� �z����s?r�������>Ym?� �z����s?d;��;��z?z��� ���s?r�������>Ym?r�������>Ym?z��� ���s?�оJ�����g?shɾ�^|�#�b?shɾ�^|�#�b?�оJ�����g?.;�B"����V?��� l�l�R?��� l�l�R?.;�B"����V?�$&�;��U�@?��"��3b�Na=?��"��3b�Na=?�$&�;��U�@?U�@�;���$&?Na=��3b���"?Na=��3b���"?U�@�;���$&?��V�B"��.;?l�R�� l��?l�R�� l��?��V�B"��.;?��g�J�����>#�b��^|�sh�>#�b��^|�sh�>��g�J�����>��s�� �z�>OYm�r������>#�b��^|�sh�>OYm�r������>#�b�shɾ�^|>��Y��=���=�>��Y��=���=�>#�b�shɾ�^|>l�R���� l>rL�����Ư>rL�����Ư>l�R���� l>Na=���"��3b>�8����W�>�8����W�>Na=���"��3b>��"�Na=��3b>����8�5�>����8�5�>��"�Na=��3b>��l�R�� l>���rL��Ư>���rL��Ư>��l�R�� l>shɾ#�b��^|>�=����Y��=�>shɾ#�b��^|>����OYm�r��>�^|�#�b�sh�>�=����Y��=�>�=����Y��=�>�^|�#�b�sh�>� l�l�R��?�Ư�rL���>�Ư�rL���>� l�l�R��?�3b�Na=���"?W짾�8���?W짾�8���?�3b�Na=���"?�3b���"�Na=?5짾����8?5짾����8?�3b���"�Na=?� l���l�R?ǯ����rL?ǯ����rL?� l���l�R?�^|�shɾ#�b?�=���=����Y?�^|�shɾ#�b?r�������>Ym?shɾ�^|�#�b?�=���=����Y?�=���=����Y?shɾ�^|�#�b?��� l�l�R?����Ư�rL?����Ư�rL?��� l�l�R?��"��3b�Na=?���W짾�8?���W짾�8?��"��3b�Na=?Na=��3b���"?�8�5짾��?�8�5짾��?Na=��3b���"?l�R�� l��?rL��Ư���>rL��Ư���>l�R�� l��?#�b��^|�sh�>��Y��=���=�>rL��Ư���>��Y��=���=�>rL�����Ư>�"B���뾋��>�"B���뾋��>rL�����Ư>�8����W�>-z/�x���>-z/�x���>�8����W�>����8�5�>x�-z/���>x�-z/���>����8�5�>���rL��Ư>��뾒"B����>���rL��Ư>�=����Y��=�>�Ư�rL���>��뾒"B����>��뾒"B����>�Ư�rL���>W짾�8���?�޾-z/�x?�޾-z/�x?W짾�8���?5짾����8?�޾x�-z/?�޾x�-z/?5짾����8?ǯ����rL?��뾋�뾒"B?ǯ����rL?�=���=����Y?����Ư�rL?��뾋�뾒"B?��뾋�뾒"B?����Ư�rL?���W짾�8?x��޾-z/?x��޾-z/?���W짾�8?�8�5짾��?-z/��޾-x?-z/��޾-x?�8�5짾��?rL��Ư���>�"B���뾋��>-z/��޾-x?�"B���뾋��>-z/�x���>�%� +� +?�%� +� +?-z/�x���>x�-z/���> +� �%� +?x�-z/���>��뾒"B����>�޾-z/�x? +� �%� +? +� �%� +?�޾-z/�x?�޾x�-z/? +� +��%?�޾x�-z/?��뾋�뾒"B?x��޾-z/? +� +��%? +� +��%?x��޾-z/?-z/��޾-x?�%� +� +?�%� +� +? +� �%� +? +� +��%?��;,e}�Ϡ>��;~����;Ϡ>,e}���;�;>�z�d;>�;>�z�d;>Ϡ>,e}���;v�>��u�6v�;z�>��s�� >z�>��s�� >v�>��u�6v�;ʋ�>��h�k;��>��g�J��=��>��g�J��=ʋ�>��h�k;�\ +?�bW�SM;.;?��V�B"�=.;?��V�B"�=�\ +?�bW�SM;��'?B{A��L?;�$&?U�@�;��=�$&?U�@�;��=��'?B{A��L?;B{A?��'��L?;U�@?�$&�;��=U�@?�$&�;��=B{A?��'��L?;�bW?�\ +�SM;��V?.;�B"�=��V?.;�B"�=�bW?�\ +�SM;��h?��Ծk;��g?{оJ��=��g?{оJ��=��h?��Ծk;��u?v��6v�;��s?z��� >��s?z��� >��u?v��6v�;,e}?Ϡ���;�z?d;�d;>,e}?Ϡ���;~�?�����;,e}?���Ϡ>�z?d;�d;>�z?d;�d;>,e}?���Ϡ>��u?6v��v�>��s?� �z�>��s?� �z�>��u?6v��v�>��h?k����>��g?J�����>��g?J�����>��h?k����>�bW?SM��\ +?��V?B"��.;?��V?B"��.;?�bW?SM��\ +?B{A?�L?���'?U�@?;���$&?U�@?;���$&?B{A?�L?���'?��'?�L?�B{A?�$&?;��U�@?�$&?;��U�@?��'?�L?�B{A?�\ +?SM��bW?.;?B"����V?.;?B"����V?�\ +?SM��bW?���>k���h?��>J�����g?��>J�����g?���>k���h?v�>6v����u?z�>� ���s?z�>� ���s?v�>6v����u?�>���,e}?d;>�;��z?�>���,e}?��;���~�?��;Ϡ�,e}?d;>�;��z?d;>�;��z?��;Ϡ�,e}?6v�;v����u?� >z����s?� >z����s?6v�;v����u?k;��Ծ��h?J��=�о��g?J��=�о��g?k;��Ծ��h?SM;�\ +��bW?B"�=.;���V?B"�=.;���V?SM;�\ +��bW?�L?;��'�B{A?;��=�$&�U�@?;��=�$&�U�@?�L?;��'�B{A?�L?;B{A���'?;��=U�@��$&?;��=U�@��$&?�L?;B{A���'?SM;�bW��\ +?B"�=��V�.;?B"�=��V�.;?SM;�bW��\ +?k;��h����>J��=��g�{�>J��=��g�{�>k;��h����>6v�;��u�v�>� >��s�z�>� >��s�z�>6v�;��u�v�>��;,e}�Ϡ>�;>�z�d;>� >��s�z�>�;>�z�d;>z�>��s�� >���>OYm�r��>���>OYm�r��>z�>��s�� >��>��g�J��=sh�>#�b��^|>sh�>#�b��^|>��>��g�J��=.;?��V�B"�=�?l�R�� l>�?l�R�� l>.;?��V�B"�=�$&?U�@�;��=��"?Na=��3b>��"?Na=��3b>�$&?U�@�;��=U�@?�$&�;��=Na=?��"��3b>Na=?��"��3b>U�@?�$&�;��=��V?.;�B"�=l�R?��� l>l�R?��� l>��V?.;�B"�=��g?{оJ��=#�b?shɾ�^|>#�b?shɾ�^|>��g?{оJ��=��s?z��� >OYm?r������>��s?z��� >�z?d;�d;>��s?� �z�>OYm?r������>OYm?r������>��s?� �z�>��g?J�����>#�b?�^|�sh�>#�b?�^|�sh�>��g?J�����>��V?B"��.;?l�R?� l��?l�R?� l��?��V?B"��.;?U�@?;���$&?Na=?�3b���"?Na=?�3b���"?U�@?;���$&?�$&?;��U�@?��"?�3b�Na=?��"?�3b�Na=?�$&?;��U�@?.;?B"����V?�?� l�l�R?�?� l�l�R?.;?B"����V?��>J�����g?sh�>�^|�#�b?sh�>�^|�#�b?��>J�����g?z�>� ���s?r��>����OYm?z�>� ���s?d;>�;��z?� >z����s?r��>����OYm?r��>����OYm?� >z����s?J��=�о��g?�^|>shɾ#�b?�^|>shɾ#�b?J��=�о��g?B"�=.;���V?� l>��l�R?� l>��l�R?B"�=.;���V?;��=�$&�U�@?�3b>��"�Na=?�3b>��"�Na=?;��=�$&�U�@?;��=U�@��$&?�3b>Na=���"?�3b>Na=���"?;��=U�@��$&?B"�=��V�.;?� l>l�R��?� l>l�R��?B"�=��V�.;?J��=��g�{�>�^|>#�b�sh�>�^|>#�b�sh�>J��=��g�{�>� >��s�z�>���>OYm�r��>�^|>#�b�sh�>���>OYm�r��>sh�>#�b��^|>�=�>��Y��=�>�=�>��Y��=�>sh�>#�b��^|>�?l�R�� l>��>rL��Ư>��>rL��Ư>�?l�R�� l>��"?Na=��3b>��?�8�5�>��?�8�5�>��"?Na=��3b>Na=?��"��3b>�8?���W�>�8?���W�>Na=?��"��3b>l�R?��� l>rL?���ǯ>rL?���ǯ>l�R?��� l>#�b?shɾ�^|>��Y?�=���=�>#�b?shɾ�^|>OYm?r������>#�b?�^|�sh�>��Y?�=���=�>��Y?�=���=�>#�b?�^|�sh�>l�R?� l��?rL?ǯ���>rL?ǯ���>l�R?� l��?Na=?�3b���"?�8?5짾��?�8?5짾��?Na=?�3b���"?��"?�3b�Na=?��?W짾�8?��?W짾�8?��"?�3b�Na=?�?� l�l�R?��>ǯ�rL?��>ǯ�rL?�?� l�l�R?sh�>�^|�#�b?�=�>�=����Y?sh�>�^|�#�b?r��>����OYm?�^|>shɾ#�b?�=�>�=����Y?�=�>�=����Y?�^|>shɾ#�b?� l>��l�R?ǯ>���rL?ǯ>���rL?� l>��l�R?�3b>��"�Na=?5�>����8?5�>����8?�3b>��"�Na=?�3b>Na=���"?W�>�8���?W�>�8���?�3b>Na=���"?� l>l�R��?ǯ>rL���>ǯ>rL���>� l>l�R��?�^|>#�b�sh�>�=�>��Y��=�>ǯ>rL���>�=�>��Y��=�>��>rL��Ư>���>�"B����>���>�"B����>��>rL��Ư>��?�8�5�>-x?-z/���>-x?-z/���>��?�8�5�>�8?���W�>-z/?x���>-z/?x���>�8?���W�>rL?���ǯ>�"B?��뾋��>rL?���ǯ>��Y?�=���=�>rL?ǯ���>�"B?��뾋��>�"B?��뾋��>rL?ǯ���>�8?5짾��?-z/?�޾-x?-z/?�޾-x?�8?5짾��?��?W짾�8?x?�޾-z/?x?�޾-z/?��?W짾�8?��>ǯ�rL?���>��뾒"B?��>ǯ�rL?�=�>�=����Y?ǯ>���rL?���>��뾒"B?���>��뾒"B?ǯ>���rL?5�>����8?��>-x�-z/?��>-x�-z/?5�>����8?W�>�8���?��>-z/�x?��>-z/�x?W�>�8���?ǯ>rL���>���>�"B����>��>-z/�x?���>�"B����>-x?-z/���> +?�%�- +? +?�%�- +?-x?-z/���>-z/?x���>�%?- +� +?-z/?x���>�"B?��뾋��>-z/?�޾-x?�%?- +� +?�%?- +� +?-z/?�޾-x?x?�޾-z/?- +? +��%?x?�޾-z/?���>��뾒"B?��>-x�-z/?- +? +��%?- +? +��%?��>-x�-z/?��>-z/�x? +?�%�- +? +?�%�- +?�%?- +� +?- +? +��%?���,e}?Ϡ>���~�?��;Ϡ�,e}?��;d;��z?d;>d;��z?d;>Ϡ�,e}?��;U����u?6v�;z����s?� >z����s?� >U����u?6v�;��Ծ��h?k;{о��g?J��={о��g?J��=��Ծ��h?k;�\ +��bW?SM;.;���V?�"�=.;���V?�"�=�\ +��bW?SM;¡'�1{A?�L?;�$&�D�@?;��=�$&�D�@?;��=¡'�1{A?�L?;B{A���'?�L?;U�@��$&?;��=U�@��$&?;��=B{A���'?�L?;�bW��\ +?SM;��V�.;?B"�=��V�.;?B"�=�bW��\ +?SM;��h����>k;��g�{�>J��=��g�{�>J��=��h����>k;��u�v�>6v�;��s�z�>� >��s�z�>� >��u�v�>6v�;,e}�Ϡ>��;�z�d;>�;>,e}�Ϡ>��;~����;��;,e}���;Ϡ>�z�d;>�;>�z�d;>�;>,e}���;Ϡ>��u�6v�;v�>��s�� >z�>��s�� >z�>��u�6v�;v�>��h�k;���>��g�J��=��>��g�J��=��>��h�k;���>�bW�SM;�\ +?��V�B"�=.;?��V�B"�=.;?�bW�SM;�\ +?B{A��L?;��'?U�@�;��=�$&?U�@�;��=�$&?B{A��L?;��'?��'��L?;B{A?�$&�;��=U�@?�$&�;��=U�@?��'��L?;B{A?�\ +�SM;�bW??;�B"�=��V??;�B"�=��V?�\ +�SM;�bW?��Ծk;��h?�оJ��=��g?�оJ��=��g?��Ծk;��h?v��6v�;��u?�y��� >��s?�y��� >��s?v��6v�;��u?����;,e}?d;��;>�z?����;,e}?�����;~�?���Ϡ>,e}?d;��;>�z?d;��;>�z?���Ϡ>,e}?6v��v�>��u?� �z�>��s?� �z�>��s?6v��v�>��u?k����>��h?J���{�>��g?J���{�>��g?k����>��h?SM��\ +?�bW?�!��.;?��V?�!��.;?��V?SM��\ +?�bW?�L?���'?B{A?;���$&?U�@?;���$&?U�@?�L?���'?B{A?�L?�1{A?¡'?;��U�@?�$&?;��U�@?�$&?�L?�1{A?¡'?SM��bW?�\ +?B"����V?.;?B"����V?.;?SM��bW?�\ +?k���h?���>������g?{�>������g?{�>k���h?���>6v����u?U�>� ���s?z�>� ���s?z�>6v����u?U�>���,e}?Ϡ>d;��z?d;>� ���s?z�>d;��z?d;>z����s?� >����>Ym?r��>����>Ym?r��>z����s?� >{о��g?J��=shɾ#�b?�^|>shɾ#�b?�^|>{о��g?J��=.;���V?�"�=��l�R?� l>��l�R?� l>.;���V?�"�=�$&�D�@?;��=��"�Na=?�3b>��"�Na=?�3b>�$&�D�@?;��=U�@��$&?;��=Na=���"?�3b>Na=���"?�3b>U�@��$&?;��=��V�.;?B"�=l�R��?� l>l�R��?� l>��V�.;?B"�=��g�{�>J��=#�b�sh�>�^|>#�b�sh�>�^|>��g�{�>J��=��s�z�>� >OYm�r��>���>��s�z�>� >�z�d;>�;>��s�� >z�>OYm�r��>���>OYm�r��>���>��s�� >z�>��g�J��=��>#�b��^|>sh�>#�b��^|>sh�>��g�J��=��>��V�B"�=.;?l�R�� l>�?l�R�� l>�?��V�B"�=.;?U�@�;��=�$&?Na=��3b>��"?Na=��3b>��"?U�@�;��=�$&?�$&�;��=U�@?��"��3b>Na=?��"��3b>Na=?�$&�;��=U�@??;�B"�=��V?��� l>l�R?��� l>l�R??;�B"�=��V?�оJ��=��g?shɾ�^|>#�b?shɾ�^|>#�b?�оJ��=��g?�y��� >��s?r������>OYm?�y��� >��s?d;��;>�z?� �z�>��s?r������>OYm?r������>OYm?� �z�>��s?J���{�>��g?�^|�sh�>#�b?�^|�sh�>#�b?J���{�>��g?�!��.;?��V?� l��?l�R?� l��?l�R?�!��.;?��V?;���$&?U�@?�3b���"?Na=?�3b���"?Na=?;���$&?U�@?;��U�@?�$&?�3b�Na=?��"?�3b�Na=?��"?;��U�@?�$&?B"����V?.;?� l�l�R?�?� l�l�R?�?B"����V?.;?������g?{�>�^|�#�b?sh�>�^|�#�b?sh�>������g?{�>� ���s?z�>����>Ym?r��>�^|�#�b?sh�>����>Ym?r��>shɾ#�b?�^|>�=����Y?�=�>�=����Y?�=�>shɾ#�b?�^|>��l�R?� l>���rL?�Ư>���rL?�Ư>��l�R?� l>��"�Na=?�3b>����8?5�>����8?5�>��"�Na=?�3b>Na=���"?�3b>�8���?W�>�8���?W�>Na=���"?�3b>l�R��?� l>rL���>ǯ>rL���>ǯ>l�R��?� l>#�b�sh�>�^|>��Y��=�>�=�>#�b�sh�>�^|>OYm�r��>���>#�b��^|>sh�>��Y��=�>�=�>��Y��=�>�=�>#�b��^|>sh�>l�R�� l>�?rL�ǯ>��>rL�ǯ>��>l�R�� l>�?Na=��3b>��"?�8�5�>��?�8�5�>��?Na=��3b>��"?��"��3b>Na=?���5�>�8?���5�>�8?��"��3b>Na=?��� l>l�R?���ǯ>rL?���ǯ>rL?��� l>l�R?shɾ�^|>#�b?�=���=�>��Y?shɾ�^|>#�b?r������>OYm?�^|�sh�>#�b?�=���=�>��Y?�=���=�>��Y?�^|�sh�>#�b?� l��?l�R?ǯ���>rL?ǯ���>rL?� l��?l�R?�3b���"?Na=?5짾��?�8?5짾��?�8?�3b���"?Na=?�3b�Na=?��"?W짾�8?��?W짾�8?��?�3b�Na=?��"?� l�l�R?�?ǯ�rL?��>ǯ�rL?��>� l�l�R?�?�^|�#�b?sh�>�=����Y?�=�>ǯ�rL?��>�=����Y?�=�>���rL?�Ư>��뾒"B?���>��뾒"B?���>���rL?�Ư>����8?5�>-x�-z/?��>-x�-z/?��>����8?5�>�8���?W�>-z/�x?��>-z/�x?��>�8���?W�>rL���>ǯ>�"B����>���>rL���>ǯ>��Y��=�>�=�>rL�ǯ>��>�"B����>���>�"B����>���>rL�ǯ>��>�8�5�>��?-z/���>x?-z/���>x?�8�5�>��?���5�>�8?x���>-z/?x���>-z/?���5�>�8?���ǯ>rL?��뾋��>�"B?���ǯ>rL?�=���=�>��Y?ǯ���>rL?��뾋��>�"B?��뾋��>�"B?ǯ���>rL?5짾��?�8?�޾-x?-z/?�޾-x?-z/?5짾��?�8?W짾�8?��?�޾-z/?x?�޾-z/?x?W짾�8?��?ǯ�rL?��>��뾒"B?���>�޾-z/?x?��뾒"B?���>-x�-z/?��> +��%?- +? +��%?- +?-x�-z/?��>-z/�x?��>�%�- +? +?-z/�x?��>�"B����>���>-z/���>x?�%�- +? +?�%�- +? +?-z/���>x?x���>-z/?- +�- +?�%?x���>-z/?��뾋��>�"B?�޾-x?-z/?- +�- +?�%?- +�- +?�%?�޾-x?-z/?�޾-z/?x? +��%?- +? +��%?- +?�%�- +? +?- +�- +?�%?,e}?��;Ϡ>~�?��;��;,e}?Ϡ>��;�z?d;>�;>�z?d;>�;>,e}?Ϡ>��;��u?v�>6v�;��s?�y�>� >��s?�y�>� >��u?v�>6v�;��h?���>k;��g?{�>J��=��g?{�>J��=��h?���>k;�bW?�\ +?SM;��V?.;?B"�=��V?.;?B"�=�bW?�\ +?SM;B{A?��'?�L?;U�@?�$&?;��=U�@?�$&?;��=B{A?��'?�L?;¡'?1{A?�L?;�$&?D�@?;��=�$&?D�@?;��=¡'?1{A?�L?;�\ +?�bW?SM;.;?��V?�"�=.;?��V?�"�=�\ +?�bW?SM;���>��h?k;{�>��g?���={�>��g?���=���>��h?k;U�>��u?6v�;z�>��s?� >z�>��s?� >U�>��u?6v�;Ϡ>,e}?��;d;>�z?d;>Ϡ>,e}?��;��;~�?��;��;,e}?Ϡ>d;>�z?d;>d;>�z?d;>��;,e}?Ϡ>6v�;��u?U�>� >��s?z�>� >��s?z�>6v�;��u?U�>k;��h?���>���=��g?{�>���=��g?{�>k;��h?���>SM;�bW?�\ +?B"�=��V?.;?B"�=��V?.;?SM;�bW?�\ +?�L?;1{A?¡'?;��=D�@?�$&?;��=D�@?�$&?�L?;1{A?¡'?�L?;��'?B{A?;��=�$&?U�@?;��=�$&?U�@?�L?;��'?B{A?SM;�\ +?�bW?�!�=.;?��V?�!�=.;?��V?SM;�\ +?�bW?k;���>��h?J��=��>��g?J��=��>��g?k;���>��h?6v�;v�>��u?� >z�>��s?� >z�>��s?6v�;v�>��u?��;Ϡ>,e}?d;>�;>�z?��;Ϡ>,e}?��;��;~�?�>��;,e}?d;>�;>�z?d;>�;>�z?�>��;,e}?v�>6v�;��u?z�>� >��s?z�>� >��s?v�>6v�;��u?���>k;��h?��>J��=��g?��>J��=��g?���>k;��h?�\ +?SM;�bW?.;?B"�=��V?.;?B"�=��V?�\ +?SM;�bW?��'?�L?;B{A?�$&?;��=U�@?�$&?;��=U�@?��'?�L?;B{A?B{A?�L?;��'?U�@?;��=�$&?U�@?;��=�$&?B{A?�L?;��'?�bW?SM;�\ +?��V?B"�=.;?��V?B"�=.;?�bW?SM;�\ +?��h?k;���>��g?J��=��>��g?J��=��>��h?k;���>��u?6v�;v�>��s?� >z�>��s?� >z�>��u?6v�;v�>,e}?��;Ϡ>�z?d;>�;>��s?� >z�>�z?d;>�;>��s?�y�>� >OYm?r��>���>OYm?r��>���>��s?�y�>� >��g?{�>J��=#�b?sh�>�^|>#�b?sh�>�^|>��g?{�>J��=��V?.;?B"�=l�R?�?� l>l�R?�?� l>��V?.;?B"�=U�@?�$&?;��=Na=?��"?�3b>Na=?��"?�3b>U�@?�$&?;��=�$&?D�@?;��=��"?Na=?�3b>��"?Na=?�3b>�$&?D�@?;��=.;?��V?�"�=�?l�R?� l>�?l�R?� l>.;?��V?�"�={�>��g?���=sh�>#�b?�^|>sh�>#�b?�^|>{�>��g?���=z�>��s?� >���>OYm?r��>z�>��s?� >d;>�z?d;>� >��s?z�>���>OYm?r��>���>OYm?r��>� >��s?z�>���=��g?{�>�^|>#�b?sh�>�^|>#�b?sh�>���=��g?{�>B"�=��V?.;?� l>l�R?�?� l>l�R?�?B"�=��V?.;?;��=D�@?�$&?�3b>Na=?��"?�3b>Na=?��"?;��=D�@?�$&?;��=�$&?U�@?�3b>��"?Na=?�3b>��"?Na=?;��=�$&?U�@?�!�=.;?��V?� l>�?l�R?� l>�?l�R?�!�=.;?��V?J��=��>��g?�^|>sh�>#�b?�^|>sh�>#�b?J��=��>��g?� >z�>��s?r��>���>OYm?� >z�>��s?d;>�;>�z?z�>� >��s?r��>���>OYm?r��>���>OYm?z�>� >��s?��>J��=��g?sh�>�^|>#�b?sh�>�^|>#�b?��>J��=��g?.;?B"�=��V?�?� l>l�R?�?� l>l�R?.;?B"�=��V?�$&?;��=U�@?��"?�3b>Na=?��"?�3b>Na=?�$&?;��=U�@?U�@?;��=�$&?Na=?�3b>��"?Na=?�3b>��"?U�@?;��=�$&?��V?B"�=.;?l�R?� l>�?l�R?� l>�?��V?B"�=.;?��g?J��=��>#�b?�^|>sh�>#�b?�^|>sh�>��g?J��=��>��s?� >z�>OYm?r��>���>#�b?�^|>sh�>OYm?r��>���>#�b?sh�>�^|>��Y?�=�>�=�>��Y?�=�>�=�>#�b?sh�>�^|>l�R?�?� l>rL?��>ǯ>rL?��>ǯ>l�R?�?� l>Na=?��"?�3b>�8?��?W�>�8?��?W�>Na=?��"?�3b>��"?Na=?�3b>��?�8?5�>��?�8?5�>��"?Na=?�3b>�?l�R?� l>��>rL?�Ư>��>rL?�Ư>�?l�R?� l>sh�>#�b?�^|>�=�>��Y?�=�>sh�>#�b?�^|>���>OYm?r��>�^|>#�b?sh�>�=�>��Y?�=�>�=�>��Y?�=�>�^|>#�b?sh�>� l>l�R?�?�Ư>rL?��>�Ư>rL?��>� l>l�R?�?�3b>Na=?��"?W�>�8?��?W�>�8?��?�3b>Na=?��"?�3b>��"?Na=?5�>��?�8?5�>��?�8?�3b>��"?Na=?� l>�?l�R?�Ư>��>rL?�Ư>��>rL?� l>�?l�R?�^|>sh�>#�b?�=�>�=�>��Y?�^|>sh�>#�b?r��>���>OYm?sh�>�^|>#�b?�=�>�=�>��Y?�=�>�=�>��Y?sh�>�^|>#�b?�?� l>l�R?��>�Ư>*rL?��>�Ư>*rL?�?� l>l�R?��"?�3b>Na=?��?5�>�8?��?5�>�8?��"?�3b>Na=?Na=?�3b>��"?�8?5�>��?�8?5�>��?Na=?�3b>��"?l�R?� l>�?rL?�Ư>��>rL?�Ư>��>l�R?� l>�?#�b?�^|>sh�>��Y?�=�>�=�>rL?�Ư>��>��Y?�=�>�=�>rL?��>ǯ>�"B?���>���>�"B?���>���>rL?��>ǯ>�8?��?W�>-z/?x?��>-z/?x?��>�8?��?W�>��?�8?5�>-x?-z/?��>-x?-z/?��>��?�8?5�>��>rL?�Ư>���>�"B?���>��>rL?�Ư>�=�>��Y?�=�>�Ư>rL?��>���>�"B?���>���>�"B?���>�Ư>rL?��>W�>�8?��?��>-z/?x?��>-z/?x?W�>�8?��?5�>��?�8?��>x?-z/?��>x?-z/?5�>��?�8?�Ư>��>rL?���>���>�"B?�Ư>��>rL?�=�>�=�>��Y?��>�Ư>*rL?���>���>�"B?���>���>�"B?��>�Ư>*rL?��?5�>�8?x?��>-z/?x?��>-z/?��?5�>�8?�8?5�>��?-z/?��>x?-z/?��>x?�8?5�>��?rL?�Ư>��>�"B?���>���>-z/?��>x?�"B?���>���>-z/?x?��>�%? +? +?�%? +? +?-z/?x?��>-x?-z/?��>- +?�%? +?-x?-z/?��>���>�"B?���>��>-z/?x?- +?�%? +?- +?�%? +?��>-z/?x?��>x?-z/?- +? +?�%?��>x?-z/?���>���>�"B?x?��>-z/?- +? +?�%?- +? +?�%?x?��>-z/?-z/?��>x?�%? +? +?�%? +? +?- +?�%? +?- +? +?�%?���Ϡ>,e}������;~������;,e}�d;��;>�z�d;��;>�z�����;,e}�v��6v�;��u��y��� >��s��y��� >��s�v��6v�;��u���Ծk;��h��оJ��=��g��оJ��=��g���Ծk;��h��\ +�SM;�bW�.;�B"�=��V�.;�B"�=��V��\ +�SM;�bW���'��L?;B{A��$&�;��=U�@��$&�;��=U�@���'��L?;B{A�B{A��L?;��'�U�@�;��=�$&�U�@�;��=�$&�B{A��L?;��'��bW�SM;�\ +���V�B"�=.;���V�B"�=.;��bW�SM;�\ +���h�k;��Ծ��g�J��=�о��g�J��=�о��h�k;��Ծ��u�6v�;v����s�� >z����s�� >z����u�6v�;v��,e}���;Ϡ��z�d;>�;�,e}���;Ϡ�~����;���,e}�Ϡ>����z�d;>�;��z�d;>�;�,e}�Ϡ>�����u�v�>6v����s��y�>� ���s��y�>� ���u�v�>6v����h����>k���g�{�>J�����g�{�>J�����h����>k��bW��\ +?SM���V�.;?B"����V�.;?B"���bW��\ +?SM�B{A���'?�L?�U�@��$&?;��U�@��$&?;��B{A���'?�L?�¡'�1{A?�L?��$&�D�@?;���$&�D�@?;��¡'�1{A?�L?��\ +��bW?SM�.;���V?�"��.;���V?�"���\ +��bW?SM���Ծ��h?k�{о��g?����{о��g?������Ծ��h?k�U����u?6v��z����s?� �z����s?� �U����u?6v��Ϡ�,e}?���d;��z?d;�Ϡ�,e}?������~�?������,e}?Ϡ�d;��z?d;�d;��z?d;����,e}?Ϡ�6v����u?U��� ���s?z��� ���s?z��6v����u?U��k���h?��Ծ������g?{о������g?{оk���h?��ԾSM��bW?�\ +�B"����V?.;�B"����V?.;�SM��bW?�\ +��L?�1{A?¡'�;��D�@?�$&�;��D�@?�$&��L?�1{A?¡'��L?���'?B{A�;���$&?U�@�;���$&?U�@��L?���'?B{A�SM��\ +?�bW��!��.;?��V��!��.;?��V�SM��\ +?�bW�k����>��h�J�����>��g�J�����>��g�k����>��h�6v��v�>��u�� �z�>��s�� �z�>��s�6v��v�>��u����Ϡ>,e}�d;��;>�z�� �z�>��s�d;��;>�z��y��� >��s�r������>OYm�r������>OYm��y��� >��s��оJ��=��g�shɾ�^|>#�b�shɾ�^|>#�b��оJ��=��g�.;�B"�=��V���� l>l�R���� l>l�R�.;�B"�=��V��$&�;��=U�@���"��3b>Na=���"��3b>Na=��$&�;��=U�@�U�@�;��=�$&�Na=��3b>��"�Na=��3b>��"�U�@�;��=�$&���V�B"�=.;�l�R�� l>��l�R�� l>����V�B"�=.;���g�J��=�о#�b��^|>shɾ#�b��^|>shɾ��g�J��=�о��s�� >z��OYm�r��>������s�� >z���z�d;>�;���s��y�>� �OYm�r��>����OYm�r��>������s��y�>� ���g�{�>J���#�b�sh�>�^|�#�b�sh�>�^|���g�{�>J�����V�.;?B"��l�R��?� l�l�R��?� l���V�.;?B"��U�@��$&?;��Na=���"?�3b�Na=���"?�3b�U�@��$&?;���$&�D�@?;�彷�"�Na=?�3b���"�Na=?�3b��$&�D�@?;��.;���V?�"����l�R?� l���l�R?� l�.;���V?�"��{о��g?����shɾ#�b?�^|�shɾ#�b?�^|�{о��g?����z����s?� �����OYm?r���z����s?� �d;��z?d;�� ���s?z������OYm?r�������OYm?r���� ���s?z��������g?{о�^|�#�b?shɾ�^|�#�b?shɾ������g?{оB"����V?.;�� l�l�R?��� l�l�R?��B"����V?.;�;��D�@?�$&��3b�Na=?��"��3b�Na=?��"�;��D�@?�$&�;���$&?U�@��3b���"?Na=��3b���"?Na=�;���$&?U�@��!��.;?��V�� l��?l�R�� l��?l�R��!��.;?��V�J�����>��g��^|�sh�>#�b��^|�sh�>#�b�J�����>��g�� �z�>��s�r������>OYm��^|�sh�>#�b�r������>OYm�shɾ�^|>#�b��=���=�>��Y��=���=�>��Y�shɾ�^|>#�b���� l>l�R�����Ư>rL�����Ư>rL���� l>l�R���"��3b>Na=����W�>�8����W�>�8���"��3b>Na=�Na=��3b>��"��8�5�>����8�5�>���Na=��3b>��"�l�R�� l>��*rL��Ư>���*rL��Ư>���l�R�� l>��#�b��^|>shɾ��Y��=�>�=��#�b��^|>shɾOYm�r��>����#�b�sh�>�^|���Y��=�>�=����Y��=�>�=��#�b�sh�>�^|�l�R��?� l�rL���>ǯ�rL���>ǯ�l�R��?� l�Na=���"?�3b��8���?W짾�8���?W짾Na=���"?�3b���"�Na=?�3b�����8?5짾����8?5짾��"�Na=?�3b���l�R?� l����rL?�Ư����rL?�Ư���l�R?� l�shɾ#�b?�^|��=����Y?�=��shɾ#�b?�^|�����OYm?r����^|�#�b?shɾ�=����Y?�=���=����Y?�=���^|�#�b?shɾ� l�l�R?���Ư�rL?����Ư�rL?���� l�l�R?���3b�Na=?��"�W짾�8?���W짾�8?����3b�Na=?��"��3b���"?Na=�5짾��?�8�5짾��?�8��3b���"?Na=�� l��?l�R��Ư���>*rL��Ư���>*rL�� l��?l�R��^|�sh�>#�b��=���=�>��Y��Ư���>*rL��=���=�>��Y�����Ư>rL���뾋��>�"B���뾋��>�"B�����Ư>rL����W�>�8�x���>-z/�x���>-z/����W�>�8��8�5�>���-z/���>x�-z/���>x��8�5�>���*rL��Ư>����"B����>���*rL��Ư>�����Y��=�>�=��rL���>ǯ��"B����>��뾒"B����>���rL���>ǯ��8���?W짾-z/�x?�޾-z/�x?�޾�8���?W짾����8?5짾-x�-z/?�޾-x�-z/?�޾����8?5짾���rL?�Ư���뾒"B?��뾹��rL?�Ư��=����Y?�=���Ư�rL?�����뾒"B?��뾋�뾒"B?����Ư�rL?���W짾�8?����޾-z/?x��޾-z/?x�W짾�8?���5짾��?�8��޾x?-z/��޾x?-z/�5짾��?�8��Ư���>*rL���뾋��>�"B��޾x?-z/���뾋��>�"B�x���>-z/�- +� +?�%�- +� +?�%�x���>-z/�-z/���>x��%�- +?- +�-z/���>x��"B����>���-z/�x?�޾�%�- +?- +��%�- +?- +�-z/�x?�޾-x�-z/?�޾- +��%? +�-x�-z/?�޾��뾒"B?����޾-z/?x�- +��%? +�- +��%? +��޾-z/?x��޾x?-z/�- +� +?�%�- +� +?�%��%�- +?- +�- +��%? +�,e}?Ϡ>���~�?��;���,e}?��;Ϡ��z?d;>�;��z?d;>�;�,e}?��;Ϡ���u?6v�;v����s?� >z����s?� >z����u?6v�;v����h?k;��Ծ��g?J��=�о��g?J��=�о��h?k;��Ծ�bW?SM;�\ +���V?B"�=.;���V?B"�=.;��bW?SM;�\ +�B{A?�L?;��'�U�@?;��=�$&�U�@?;��=�$&�B{A?�L?;��'���'?�L?;B{A��$&?;��=U�@��$&?;��=U�@���'?�L?;B{A��\ +?SM;�bW�?;?B"�=��V�?;?B"�=��V��\ +?SM;�bW����>k;��h���>J��=��g���>J��=��g����>k;��h�v�>6v�;��u��y�>� >��s��y�>� >��s�v�>6v�;��u��>��;,e}�d;>�;>�z��>��;,e}���;��;~����;Ϡ>,e}�d;>�;>�z�d;>�;>�z���;Ϡ>,e}�6v�;v�>��u�� >z�>��s�� >z�>��s�6v�;v�>��u�k;���>��h�J��={�>��g�J��={�>��g�k;���>��h�SM;�\ +?�bW��!�=.;?��V��!�=.;?��V�SM;�\ +?�bW��L?;��'?B{A�;��=�$&?U�@�;��=�$&?U�@��L?;��'?B{A��L?;1{A?¡'�;��=U�@?�$&�;��=U�@?�$&��L?;1{A?¡'�SM;�bW?�\ +�B"�=��V?.;�B"�=��V?.;�SM;�bW?�\ +�k;��h?��Ծ���=��g?{о���=��g?{оk;��h?��Ծ6v�;��u?U��� >��s?z��� >��s?z��6v�;��u?U����;,e}?Ϡ�d;>�z?d;���;,e}?Ϡ���;~�?���Ϡ>,e}?���d;>�z?d;�d;>�z?d;�Ϡ>,e}?���U�>��u?6v��z�>��s?� �z�>��s?� �U�>��u?6v�����>��h?k�{�>��g?J���{�>��g?J������>��h?k��\ +?�bW?SM�.;?��V?�"��.;?��V?�"���\ +?�bW?SM�¡'?1{A?�L?��$&?D�@?;���$&?D�@?;��¡'?1{A?�L?�B{A?��'?�L?�U�@?�$&?;��U�@?�$&?;��B{A?��'?�L?��bW?�\ +?SM���V?.;?B"����V?.;?B"���bW?�\ +?SM���h?���>k���g?{�>J�����g?{�>J�����h?���>k���u?v�>6v����s?z�>� ���s?z�>� ���u?v�>6v��,e}?Ϡ>����z?d;>�;���s?z�>� ��z?d;>�;���s?� >z��OYm?r��>����OYm?r��>������s?� >z����g?J��=�о#�b?�^|>shɾ#�b?�^|>shɾ��g?J��=�о��V?B"�=.;�l�R?� l>��l�R?� l>����V?B"�=.;�U�@?;��=�$&�Na=?�3b>��"�Na=?�3b>��"�U�@?;��=�$&��$&?;��=U�@���"?�3b>Na=���"?�3b>Na=��$&?;��=U�@�?;?B"�=��V��?� l>l�R��?� l>l�R�?;?B"�=��V���>J��=��g�sh�>�^|>#�b�sh�>�^|>#�b���>J��=��g��y�>� >��s�r��>���>OYm��y�>� >��s�d;>�;>�z�� >z�>��s�r��>���>OYm�r��>���>OYm�� >z�>��s�J��={�>��g��^|>sh�>#�b��^|>sh�>#�b�J��={�>��g��!�=.;?��V�� l>�?l�R�� l>�?l�R��!�=.;?��V�;��=�$&?U�@��3b>��"?Na=��3b>��"?Na=�;��=�$&?U�@�;��=U�@?�$&��3b>Na=?��"��3b>Na=?��"�;��=U�@?�$&�B"�=��V?.;�� l>l�R?��� l>l�R?��B"�=��V?.;����=��g?{о�^|>#�b?shɾ�^|>#�b?shɾ���=��g?{о� >��s?z�����>OYm?r���� >��s?z��d;>�z?d;�z�>��s?� ����>OYm?r������>OYm?r���z�>��s?� �{�>��g?J���sh�>#�b?�^|�sh�>#�b?�^|�{�>��g?J���.;?��V?�"���?l�R?� l��?l�R?� l�.;?��V?�"���$&?D�@?;�彷�"?Na=?�3b���"?Na=?�3b��$&?D�@?;��U�@?�$&?;��Na=?��"?�3b�Na=?��"?�3b�U�@?�$&?;�彖�V?.;?B"��l�R?�?� l�l�R?�?� l���V?.;?B"����g?{�>J���#�b?sh�>�^|�#�b?sh�>�^|���g?{�>J�����s?z�>� �OYm?r��>����#�b?sh�>�^|�OYm?r��>����#�b?�^|>shɾ��Y?�=�>�=����Y?�=�>�=��#�b?�^|>shɾl�R?� l>��rL?�Ư>���rL?�Ư>���l�R?� l>��Na=?�3b>��"��8?5�>����8?5�>���Na=?�3b>��"���"?�3b>Na=���?5�>�8���?5�>�8���"?�3b>Na=��?� l>l�R���>ǯ>rL���>ǯ>rL��?� l>l�R�sh�>�^|>#�b��=�>�=�>��Y�sh�>�^|>#�b�r��>���>OYm��^|>sh�>#�b��=�>�=�>��Y��=�>�=�>��Y��^|>sh�>#�b�� l>�?l�R�ǯ>��>rL�ǯ>��>rL�� l>�?l�R��3b>��"?Na=�5�>��?�8�5�>��?�8��3b>��"?Na=��3b>Na=?��"�W�>�8?���W�>�8?����3b>Na=?��"�� l>l�R?��ǯ>rL?���ǯ>rL?���� l>l�R?���^|>#�b?shɾ�=�>��Y?�=���^|>#�b?shɾ���>OYm?r���sh�>#�b?�^|��=�>��Y?�=���=�>��Y?�=��sh�>#�b?�^|��?l�R?� l���>rL?ǯ���>rL?ǯ��?l�R?� l���"?Na=?�3b���?�8?5짾��?�8?5짾��"?Na=?�3b�Na=?��"?�3b��8?��?W짾�8?��?W짾Na=?��"?�3b�l�R?�?� l�rL?��>ǯ�rL?��>ǯ�l�R?�?� l�#�b?sh�>�^|���Y?�=�>�=��rL?��>ǯ���Y?�=�>�=��rL?�Ư>����"B?���>��뾒"B?���>���rL?�Ư>����8?5�>���-z/?���>-x�-z/?���>-x��8?5�>�����?5�>�8�x?��>-z/�x?��>-z/���?5�>�8���>ǯ>rL����>���>�"B���>ǯ>rL��=�>�=�>��Y�ǯ>��>rL����>���>�"B����>���>�"B�ǯ>��>rL�5�>��?�8���>-x?-z/���>-x?-z/�5�>��?�8�W�>�8?�����>-z/?x���>-z/?x�W�>�8?���ǯ>rL?������>�"B?���ǯ>rL?����=�>��Y?�=����>rL?ǯ����>�"B?��뾋��>�"B?��뾹�>rL?ǯ���?�8?5짾-x?-z/?�޾-x?-z/?�޾��?�8?5짾�8?��?W짾-z/?x?�޾-z/?x?�޾�8?��?W짾rL?��>ǯ��"B?���>���-z/?x?�޾�"B?���>���-z/?���>-x��%?- +?- +��%?- +?- +�-z/?���>-x�x?��>-z/�- +?- +?�%�x?��>-z/����>���>�"B���>-x?-z/�- +?- +?�%�- +?- +?�%���>-x?-z/���>-z/?x� +?�%?- +���>-z/?x����>�"B?���-x?-z/?�޾ +?�%?- +� +?�%?- +�-x?-z/?�޾-z/?x?�޾�%?- +?- +��%?- +?- +�- +?- +?�%� +?�%?- +����,e}�Ϡ����~�����Ϡ�,e}�����;��z�d;��;��z�d;�Ϡ�,e}����v����u�6v��z����s�� �z����s�� �v����u�6v��ʋԾ��h�k��о��g�J����о��g�J���ʋԾ��h�k��\ +��bW�SM�.;���V�B"��.;���V�B"���\ +��bW�SM���'�B{A��L?��$&�U�@�;���$&�U�@�;�彲�'�B{A��L?�B{A���'��L?�U�@��$&�;��U�@��$&�;��B{A���'��L?��bW��\ +�SM���V�.;�B"����V�.;�B"���bW��\ +�SM���h���Ծk���g�{оJ�����g�{оJ�����h���Ծk���u�v��6v����s�z��� ���s�z��� ���u�v��6v��,e}�Ϡ�����z�d;�d;�,e}�Ϡ����~��������,e}����Ϡ��z�d;�d;��z�d;�d;�,e}����Ϡ���u�6v��v����s�� �z����s�� �z����u�6v��v����h�k���Ծ��g�J����о��g�J����о��h�k���Ծ�bW�SM��\ +���V�B"��.;���V�B"��.;��bW�SM��\ +�B{A��L?���'�U�@�;���$&�U�@�;���$&�B{A��L?���'���'��L?�B{A��$&�;��U�@��$&�;��U�@���'��L?�B{A��\ +�SM��bW�.;�B"����V�.;�B"����V��\ +�SM��bW���Ծk���h��оJ�����g��оJ�����g���Ծk���h�v��6v����u�z��� ���s�z��� ���s�v��6v����u������,e}�d;��;��z������,e}�������~�����Ϡ�,e}�d;��;��z�d;��;��z����Ϡ�,e}�6v��v����u�� �z����s�� �z����s�6v��v����u�k���Ծ��h�J����о��g�J����о��g�k���Ծ��h�SM��\ +��bW�B"��.;���V�B"��.;���V�SM��\ +��bW��L?���'�B{A�;���$&�U�@�;���$&�U�@��L?���'�B{A��L?�B{A���'�;��U�@��$&�;��U�@��$&��L?�B{A���'�SM��bW��\ +�B"����V�.;�B"����V�.;�SM��bW��\ +�k���h���ԾJ�����g�{оJ�����g�{оk���h���Ծ6v����u�v��� ���s�z��� ���s�z��6v����u�v�����,e}�Ϡ��;��z�d;�� ���s�z���;��z�d;�z����s�� �����OYm�r�������OYm�r���z����s�� ��о��g�J���shɾ#�b��^|�shɾ#�b��^|��о��g�J���.;���V�B"����l�R�� l���l�R�� l�.;���V�B"���$&�U�@�;�彷�"�Na=��3b���"�Na=��3b��$&�U�@�;��U�@��$&�;��Na=���"��3b�Na=���"��3b�U�@��$&�;�彖�V�.;�B"��l�R���� l�l�R���� l���V�.;�B"����g�{оJ���#�b�shɾ�^|�#�b�shɾ�^|���g�{оJ�����s�z��� �OYm�r���������s�z��� ��z�d;�d;���s�� �z��OYm�r�������OYm�r���������s�� �z����g�J����о#�b��^|�shɾ#�b��^|�shɾ��g�J����о��V�B"��.;�l�R�� l���l�R�� l�����V�B"��.;�U�@�;���$&�Na=��3b���"�Na=��3b���"�U�@�;���$&��$&�;��U�@���"��3b�Na=���"��3b�Na=��$&�;��U�@�.;�B"����V���� l�l�R���� l�l�R�.;�B"����V��оJ�����g�shɾ�^|�#�b�shɾ�^|�#�b��оJ�����g�z��� ���s�r�������OYm�z��� ���s�d;��;��z�� �z����s�r�������OYm�r�������OYm�� �z����s�J����о��g��^|�shɾ#�b��^|�shɾ#�b�J����о��g�B"��.;���V�� l���l�R�� l���l�R�B"��.;���V�;���$&�U�@��3b���"�Na=��3b���"�Na=�;���$&�U�@�;��U�@��$&��3b�Na=���"��3b�Na=���"�;��U�@��$&�B"����V�.;�� l�l�R���� l�l�R���B"����V�.;�J�����g�{о�^|�#�b�shɾ�^|�#�b�shɾJ�����g�{о� ���s�z������OYm�r����^|�#�b�shɾ����OYm�r���shɾ#�b��^|��=����Y��=���=����Y��=��shɾ#�b��^|���l�R�� l����rL��Ư����rL��Ư���l�R�� l���"�Na=��3b�����8�5짾����8�5짾��"�Na=��3b�Na=���"��3b��8����W짾�8����W짾Na=���"��3b�l�R���� l�rL����ǯ�rL����ǯ�l�R���� l�#�b�shɾ�^|���Y��=���=��#�b�shɾ�^|�OYm�r�������#�b��^|�shɾ��Y��=���=����Y��=���=��#�b��^|�shɾl�R�� l���rL�ǯ����rL�ǯ����l�R�� l���Na=��3b���"��8�5짾����8�5짾���Na=��3b���"���"��3b�Na=����W짾�8����W짾�8���"��3b�Na=���� l�l�R����ǯ�rL����ǯ�rL���� l�l�R�shɾ�^|�#�b��=���=����Y�shɾ�^|�#�b�r�������OYm��^|�shɾ#�b��=���=����Y��=���=����Y��^|�shɾ#�b�� l���l�R�ǯ����rL�ǯ����rL�� l���l�R��3b���"�Na=�5짾����8�5짾����8��3b���"�Na=��3b�Na=���"�W짾�8����W짾�8�����3b�Na=���"�� l�l�R���ǯ�rL����ǯ�rL����� l�l�R����^|�#�b�shɾ�=����Y��=��ǯ�rL�����=����Y��=�����rL��Ư���뾒"B���뾋�뾒"B���뾹��rL��Ư�����8�5짾-x�-z/��޾-x�-z/��޾����8�5짾�8����W짾-z/�x��޾-z/�x��޾�8����W짾rL����ǯ��"B���뾋��rL����ǯ���Y��=���=��rL�ǯ�����"B���뾋�뾒"B���뾋��rL�ǯ�����8�5짾���-z/��޾-x�-z/��޾-x��8�5짾������W짾�8�x��޾-z/�x��޾-z/����W짾�8����ǯ�rL���뾋�뾒"B����ǯ�rL��=���=����Y�ǯ����rL���뾋�뾒"B���뾋�뾒"B�ǯ����rL�5짾����8��޾-x�-z/��޾-x�-z/�5짾����8�W짾�8�����޾-z/�x��޾-z/�x�W짾�8����ǯ�rL������뾒"B�����޾-z/�x���뾒"B����-x�-z/��޾ +��%�- +� +��%�- +�-x�-z/��޾-z/�x��޾�%�- +� +�-z/�x��޾�"B���뾋��-z/��޾-x��%�- +� +��%�- +� +�-z/��޾-x�x��޾-z/�- +� +��%�x��޾-z/���뾋�뾒"B��޾-x�-z/�- +� +��%�- +� +��%��޾-x�-z/��޾-z/�x� +��%�- +� +��%�- +��%�- +� +�- +� +��%�,e}?���Ϡ�~�?������,e}?Ϡ�����z?d;��;��z?d;��;�,e}?Ϡ������u?v��6v����s?�y��� ���s?�y��� ���u?v��6v����h?��Ծk���g?{оJ�����g?{оJ�����h?��Ծk��bW?�\ +�SM���V??;�B"����V??;�B"���bW?�\ +�SM�B{A?��'��L?�U�@?�$&�;��U�@?�$&�;��B{A?��'��L?���'?B{A��L?��$&?U�@�;���$&?U�@�;�彲�'?B{A��L?��\ +?�bW�SM�.;?��V�B"��.;?��V�B"���\ +?�bW�SM�ʋ�>��h�k���>��g�J�����>��g�J���ʋ�>��h�k�v�>��u�6v��z�>��s�� �z�>��s�� �v�>��u�6v��Ϡ>,e}�����;>�z�d;�Ϡ>,e}������;~�������;,e}�Ϡ��;>�z�d;��;>�z�d;���;,e}�Ϡ�6v�;��u�v��� >��s�z��� >��s�z��6v�;��u�v��k;��h���ԾJ��=��g�{оJ��=��g�{оk;��h���ԾSM;�bW��\ +�B"�=��V�.;�B"�=��V�.;�SM;�bW��\ +��L?;B{A���'�;��=U�@��$&�;��=U�@��$&��L?;B{A���'��L?;��'�B{A�;��=�$&�U�@�;��=�$&�U�@��L?;��'�B{A�SM;�\ +��bW�B"�=.;���V�B"�=.;���V�SM;�\ +��bW�k;��Ծ��h�J��=�о��g�J��=�о��g�k;��Ծ��h�6v�;v����u�� >z����s�� >z����s�6v�;v����u���;Ϡ�,e}�d;>�;��z���;Ϡ�,e}���;���~���>���,e}�d;>�;��z�d;>�;��z��>���,e}�v�>6v����u�z�>� ���s�z�>� ���s�v�>6v����u����>k���h���>J�����g���>J�����g����>k���h��\ +?SM��bW�.;?B"����V�.;?B"����V��\ +?SM��bW���'?�L?�B{A��$&?;��U�@��$&?;��U�@���'?�L?�B{A�B{A?�L?���'�U�@?;���$&�U�@?;���$&�B{A?�L?���'��bW?SM��\ +���V?B"��.;���V?B"��.;��bW?SM��\ +���h?k���Ծ��g?J����о��g?J����о��h?k���Ծ��u?6v��v����s?� �z����s?� �z����u?6v��v��,e}?���Ϡ��z?d;��;���s?� �z���z?d;��;���s?�y��� �OYm?r�������OYm?r���������s?�y��� ���g?{оJ���#�b?shɾ�^|�#�b?shɾ�^|���g?{оJ�����V??;�B"��l�R?��� l�l�R?��� l���V??;�B"��U�@?�$&�;��Na=?��"��3b�Na=?��"��3b�U�@?�$&�;���$&?U�@�;�彷�"?Na=��3b���"?Na=��3b��$&?U�@�;��.;?��V�B"���?l�R�� l��?l�R�� l�.;?��V�B"����>��g�J���sh�>#�b��^|�sh�>#�b��^|���>��g�J���z�>��s�� ����>OYm�r���z�>��s�� ��;>�z�d;�� >��s�z�����>OYm�r������>OYm�r���� >��s�z��J��=��g�{о�^|>#�b�shɾ�^|>#�b�shɾJ��=��g�{оB"�=��V�.;�� l>l�R���� l>l�R���B"�=��V�.;�;��=U�@��$&��3b>Na=���"��3b>Na=���"�;��=U�@��$&�;��=�$&�U�@��3b>��"�Na=��3b>��"�Na=�;��=�$&�U�@�B"�=.;���V�� l>��l�R�� l>��l�R�B"�=.;���V�J��=�о��g��^|>shɾ#�b��^|>shɾ#�b�J��=�о��g�� >z����s�r��>����>Ym�� >z����s�d;>�;��z�z�>� ���s�r��>����>Ym�r��>����>Ym�z�>� ���s���>J�����g�sh�>�^|�#�b�sh�>�^|�#�b���>J�����g�.;?B"����V��?� l�l�R��?� l�l�R�.;?B"����V��$&?;��U�@���"?�3b�Na=���"?�3b�Na=��$&?;��U�@�U�@?;���$&�Na=?�3b���"�Na=?�3b���"�U�@?;���$&���V?B"��.;�l�R?� l���l�R?� l�����V?B"��.;���g?J����о#�b?�^|�shɾ#�b?�^|�shɾ��g?J����о��s?� �z��OYm?r�������#�b?�^|�shɾOYm?r�������#�b?shɾ�^|���Y?�=���=����Y?�=���=��#�b?shɾ�^|�l�R?��� l�rL?����Ư�rL?����Ư�l�R?��� l�Na=?��"��3b��8?���W짾�8?���W짾Na=?��"��3b���"?Na=��3b���?�8�5짾��?�8�5짾��"?Na=��3b��?l�R�� l���>rL��Ư���>rL��Ư��?l�R�� l�sh�>#�b��^|��=�>��Y��=��sh�>#�b��^|����>OYm�r����^|>#�b�shɾ�=�>��Y��=���=�>��Y��=���^|>#�b�shɾ� l>l�R����Ư>rL�����Ư>rL����� l>l�R����3b>Na=���"�W�>�8����W�>�8�����3b>Na=���"��3b>��"�Na=�5�>����8�5�>����8��3b>��"�Na=�� l>��l�R�ǯ>���rL�ǯ>���rL�� l>��l�R��^|>shɾ#�b��=�>�=����Y��^|>shɾ#�b�r��>����>Ym�sh�>�^|�#�b��=�>�=����Y��=�>�=����Y�sh�>�^|�#�b��?� l�l�R���>�Ư�rL���>�Ư�rL��?� l�l�R���"?�3b�Na=���?W짾�8���?W짾�8���"?�3b�Na=�Na=?�3b���"��8?5짾����8?5짾���Na=?�3b���"�l�R?� l���rL?�Ư����rL?�Ư����l�R?� l���#�b?�^|�shɾ��Y?�=���=��rL?�Ư������Y?�=���=��rL?����Ư��"B?��뾋�뾒"B?��뾋��rL?����Ư��8?���W짾-z/?x��޾-z/?x��޾�8?���W짾��?�8�5짾x?-z/��޾x?-z/��޾��?�8�5짾��>rL��Ư����>�"B���뾹�>rL��Ư��=�>��Y��=���Ư>rL�������>�"B���뾋��>�"B�����Ư>rL����W�>�8������>-z/�x���>-z/�x�W�>�8����5�>����8���>x�-z/���>x�-z/�5�>����8�ǯ>���rL����>��뾒"B�ǯ>���rL��=�>�=����Y���>�Ư�rL����>��뾒"B����>��뾒"B���>�Ư�rL���?W짾�8�x?�޾-z/�x?�޾-z/���?W짾�8��8?5짾���-z/?�޾-x�-z/?�޾-x��8?5짾���rL?�Ư�����"B?��뾋��-z/?�޾-x��"B?��뾋��-z/?x��޾�%? +� +��%? +� +�-z/?x��޾x?-z/��޾ +? �%� +�x?-z/��޾���>�"B������>-z/�x� +? �%� +� +? �%� +���>-z/�x���>x�-z/� +? +��%���>x�-z/����>��뾒"B�x?�޾-z/� +? +��%� +? +��%�x?�޾-z/�-z/?�޾-x��%? +� +��%? +� +� +? �%� +� +? +��%� \ No newline at end of file diff --git a/jme3-plugins/src/test/resources/gltf/lights/MODEL_ROUNDED_CUBE_PART_1/positions.bin b/jme3-plugins/src/test/resources/gltf/lights/MODEL_ROUNDED_CUBE_PART_1/positions.bin new file mode 100644 index 0000000000000000000000000000000000000000..96c2a4e1b9e5fca51bcea8827f274d33230769ef GIT binary patch literal 41472 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 literal 0 HcmV?d00001 diff --git a/jme3-plugins/src/test/resources/gltf/lights/lights.gltf b/jme3-plugins/src/test/resources/gltf/lights/lights.gltf new file mode 100644 index 0000000000..1fb7ee2ba8 --- /dev/null +++ b/jme3-plugins/src/test/resources/gltf/lights/lights.gltf @@ -0,0 +1,226 @@ +{ + "extensionsUsed": [ + "KHR_lights_punctual" + ], + "extensions": { + "KHR_lights_punctual": { + "lights": [ + { + "color": [ + 1.0, + 0.9, + 0.7 + ], + "name": "Directional", + "intensity": 3.0, + "type": "directional" + }, + { + "color": [ + 1.0, + 0.0, + 0.0 + ], + "name": "Point", + "intensity": 20.0, + "type": "point" + }, + { + "color": [ + 0.3, + 0.7, + 1.0 + ], + "name": "Spot", + "intensity": 40.0, + "type": "spot", + "spot": { + "innerConeAngle": 0.785398163397448, + "outerConeAngle": 1.57079632679 + } + } + ] + } + }, + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5126, + "count": 3456, + "max": [ + 10, + 19.949111938476562, + 10 + ], + "min": [ + -10, + -0.050886999815702438, + -10 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5126, + "count": 3456, + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 0, + "componentType": 5125, + "count": 5172, + "max": [ + 3455 + ], + "min": [ + 0 + ], + "type": "SCALAR" + } + ], + "asset": { + "copyright": "2017 (c) Adobe Corp", + "minVersion": "2.0", + "version": "2.0" + }, + "bufferViews": [ + { + "buffer": 0, + "byteLength": 41472, + "byteOffset": 0 + }, + { + "buffer": 1, + "byteLength": 41472, + "byteOffset": 0 + }, + { + "buffer": 2, + "byteLength": 20688, + "byteOffset": 0, + "target": 34963 + } + ], + "buffers": [ + { + "byteLength": 41472, + "uri": "MODEL_ROUNDED_CUBE_PART_1/positions.bin" + }, + { + "byteLength": 41472, + "uri": "MODEL_ROUNDED_CUBE_PART_1/normals.bin" + }, + { + "byteLength": 20688, + "uri": "MODEL_ROUNDED_CUBE_PART_1/indices.bin" + } + ], + "cameras": [ + { + "name": "render_camera", + "perspective": { + "aspectRatio": 1.3333333730697632, + "yfov": 0.58904862403869629, + "zfar": 100, + "znear": 9.9999997473787516e-05 + }, + "type": "perspective" + }, + { + "name": "render_camera2", + "perspective": { + "aspectRatio": 1.3333333730697632, + "yfov": 0.58904862403869629, + "zfar": 100, + "znear": 9.9999997473787516e-05 + }, + "type": "perspective" + } + ], + "materials": [ + { + "doubleSided": true, + "name": "Rounded Cube Material", + "pbrMetallicRoughness": { + "baseColorFactor": [ + 0.63075679540634155, + 0.63075679540634155, + 0.63075679540634155, + 1 + ], + "metallicFactor": 0, + "roughnessFactor": 0.50300002098083496 + } + } + ], + "meshes": [ + { + "name": "MODEL_ROUNDED_CUBE_PART_1", + "primitives": [ + { + "attributes": { + "NORMAL": 1, + "POSITION": 0 + }, + "indices": 2, + "material": 0, + "mode": 4 + } + ] + } + ], + "nodes": [ + { + "extensions": { + "KHR_lights_punctual": { + "light": 1 + } + }, + "matrix": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 22, + 0, + 1 + ], + "name": "point_light" + }, + { + "name": "directional_light", + "extensions": { + "KHR_lights_punctual": { + "light": 0 + } + } + }, + { + "mesh": 0, + "name": "MODEL_ROUNDED_CUBE_PART_1model_N3D" + } + ], + "scene": 0, + "scenes": [ + { + "name": "scene", + "nodes": [ + 0, + 1, + 2 + ] + } + ] +} \ No newline at end of file From e2ea80eb69de0c608eb578d3ada014f7ffe8d222 Mon Sep 17 00:00:00 2001 From: Trevor Flynn Date: Sun, 20 Dec 2020 16:00:36 -0900 Subject: [PATCH 02/11] Initial implementation of light intensity --- .../gltf/LightsPunctualExtensionLoader.java | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java index 63706fefc9..0859a6108b 100644 --- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java @@ -121,9 +121,9 @@ private SpotLight buildSpotLight(JsonObject obj) { //Get properties String name = obj.has("name") ? obj.get("name").getAsString() : ""; - //TODO: How do we incorporate intensity float intensity = obj.has("intensity") ? obj.get("intensity").getAsFloat() : 1.0f; ColorRGBA color = obj.has("color") ? GltfUtils.getAsColor(obj, "color") : new ColorRGBA(ColorRGBA.White); + color = lumensToColor(color, intensity); float range = obj.has("range") ? obj.get("range").getAsFloat() : Float.POSITIVE_INFINITY; //Spot specific @@ -155,9 +155,9 @@ private DirectionalLight buildDirectionalLight(JsonObject obj) { //Get properties String name = obj.has("name") ? obj.get("name").getAsString() : ""; - //TODO: How do we incorporate intensity float intensity = obj.has("intensity") ? obj.get("intensity").getAsFloat() : 1.0f; ColorRGBA color = obj.has("color") ? GltfUtils.getAsColor(obj, "color") : new ColorRGBA(ColorRGBA.White); + color = lumensToColor(color, intensity); DirectionalLight directionalLight = new DirectionalLight(); directionalLight.setName(name); @@ -171,9 +171,9 @@ private PointLight buildPointLight(JsonObject obj) { //Get properties String name = obj.has("name") ? obj.get("name").getAsString() : ""; - //TODO: How do we incorporate intensity float intensity = obj.has("intensity") ? obj.get("intensity").getAsFloat() : 1.0f; ColorRGBA color = obj.has("color") ? GltfUtils.getAsColor(obj, "color") : new ColorRGBA(ColorRGBA.White); + color = lumensToColor(color, intensity); float range = obj.has("range") ? obj.get("range").getAsFloat() : Float.POSITIVE_INFINITY; PointLight pointLight = new PointLight(); @@ -192,6 +192,34 @@ private void addLight(Node node, int light) { } } + private ColorRGBA lumensToColor(ColorRGBA color, float lumens) { + ColorRGBA brightnessModifier = lumensToColor(lumens); + return color.mult(brightnessModifier); + } + + private ColorRGBA lumensToColor(float lumens) { + /* + Taken from /Common/ShaderLib/Hdr.glsllib + vec4 HDR_EncodeLum(in float lum){ + float Le = 2.0 * log2(lum + epsilon) + 127.0; + vec4 result = vec4(0.0); + result.a = fract(Le); + result.rgb = vec3((Le - (floor(result.a * 255.0)) / 255.0) / 255.0); + return result; + */ + float epsilon = 0.0001f; + + double Le = 2f * Math.log(lumens * epsilon) / Math.log(2); + ColorRGBA color = new ColorRGBA(); + color.a = (float) (Le - Math.floor(Le)); //Get fractional part + float val = (float) ((Le - (Math.floor(color.a * 255.0)) / 255.0) / 255.0); + color.r = val; + color.g = val; + color.b = val; + + return color; + } + private class NodeNeedingLight { private Node node; private int lightIndex; From 6cdd5e6b24feef32e99cbcbf0bb8fb2b8617bd83 Mon Sep 17 00:00:00 2001 From: Trevor Flynn Date: Wed, 13 Jan 2021 17:15:00 -0900 Subject: [PATCH 03/11] Add light to model root and add control to light node --- .../gltf/LightsPunctualExtensionLoader.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java index 0859a6108b..e1f2810497 100644 --- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java @@ -44,6 +44,7 @@ import com.jme3.math.FastMath; import com.jme3.math.Vector3f; import com.jme3.scene.Node; +import com.jme3.scene.control.LightControl; import java.io.IOException; import java.util.HashMap; @@ -73,7 +74,7 @@ public Object handleExtension(GltfLoader loader, String parentName, JsonElement if (!lightDefinitions.containsKey(index)) { pendingNodes.add(new NodeNeedingLight((Node) input, index)); } else { - addLight((Node) input, index); + addLight((Node) input, (Node) input, index); } } else if (jsonObject.has("lights")) { //This will get run last //Process the light definitions @@ -104,7 +105,7 @@ public Object handleExtension(GltfLoader loader, String parentName, JsonElement //Build any lights that are pending now that we have definitions for (NodeNeedingLight nodeInNeed : pendingNodes) { - addLight(nodeInNeed.getNode(), nodeInNeed.getLightIndex()); + addLight((Node) input, nodeInNeed.getNode(), nodeInNeed.getLightIndex()); } pendingNodes.clear(); } else { @@ -184,11 +185,14 @@ private PointLight buildPointLight(JsonObject obj) { return pointLight; } - private void addLight(Node node, int light) { - if (lightDefinitions.containsKey(light)) { - node.addLight(lightDefinitions.get(light)); + private void addLight(Node parent, Node node, int lightIndex) { + if (lightDefinitions.containsKey(lightIndex)) { + Light light = lightDefinitions.get(lightIndex); + parent.addLight(light); + LightControl control = new LightControl(light); + node.addControl(control); } else { - throw new AssetLoadException("KHR_lights_punctual extension accessed undefined light at index " + light); + throw new AssetLoadException("KHR_lights_punctual extension accessed undefined light at index " + lightIndex); } } From 7f07f798e59d768791fa6301c0e8485d4c968459 Mon Sep 17 00:00:00 2001 From: Trevor Flynn Date: Wed, 13 Jan 2021 17:34:53 -0900 Subject: [PATCH 04/11] Fix adding lights when model only has one scene --- .../src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java index eec5e8da32..57db0eb208 100644 --- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java @@ -171,6 +171,9 @@ protected Object loadFromStream(AssetInfo assetInfo, InputStream stream) throws //only one scene let's not return the root. if (rootNode.getChildren().size() == 1) { + Node child = (Node) rootNode.getChild(0); + //Migrate lights that were in the parent to the child. + rootNode.getLocalLightList().forEach(child::addLight); rootNode = (Node) rootNode.getChild(0); } //no name for the scene... let's set the file name. From 8981aa9c8cf59debe81ad2c9136fe1d4ca30cb01 Mon Sep 17 00:00:00 2001 From: Trevor Flynn Date: Wed, 13 Jan 2021 17:35:59 -0900 Subject: [PATCH 05/11] Minor optimization --- .../src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java index 57db0eb208..28c82221ff 100644 --- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java @@ -174,7 +174,7 @@ protected Object loadFromStream(AssetInfo assetInfo, InputStream stream) throws Node child = (Node) rootNode.getChild(0); //Migrate lights that were in the parent to the child. rootNode.getLocalLightList().forEach(child::addLight); - rootNode = (Node) rootNode.getChild(0); + rootNode = child; } //no name for the scene... let's set the file name. if (rootNode.getName() == null) { From 70c5a469e80c044099cead89cef2f38cbdb0ce2d Mon Sep 17 00:00:00 2001 From: Trevor Flynn Date: Sat, 16 Jan 2021 10:06:29 -0900 Subject: [PATCH 06/11] Fix for intensity calc --- .../scene/plugins/gltf/LightsPunctualExtensionLoader.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java index e1f2810497..885266a88f 100644 --- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2020 jMonkeyEngine + * Copyright (c) 2009-2021 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -213,7 +213,7 @@ vec4 HDR_EncodeLum(in float lum){ */ float epsilon = 0.0001f; - double Le = 2f * Math.log(lumens * epsilon) / Math.log(2); + double Le = 2f * Math.log(lumens * epsilon) / Math.log(2) + 127.0; ColorRGBA color = new ColorRGBA(); color.a = (float) (Le - Math.floor(Le)); //Get fractional part float val = (float) ((Le - (Math.floor(color.a * 255.0)) / 255.0) / 255.0); From 45ade5c814d0c5389d2643b2fb1d21f6e8c025e2 Mon Sep 17 00:00:00 2001 From: Trevor Flynn Date: Sun, 17 Jan 2021 11:24:40 -0900 Subject: [PATCH 07/11] Custom light control for GLTF -Z oriented lights --- .../scene/plugins/gltf/GltfLightControl.java | 109 ++++++++++++++++++ .../gltf/LightsPunctualExtensionLoader.java | 2 +- 2 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLightControl.java diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLightControl.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLightControl.java new file mode 100644 index 0000000000..a68ac9ad2c --- /dev/null +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLightControl.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2009-2021 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.scene.plugins.gltf; + +import com.jme3.light.DirectionalLight; +import com.jme3.light.Light; +import com.jme3.light.PointLight; +import com.jme3.light.SpotLight; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; +import com.jme3.scene.control.LightControl; +import com.jme3.util.TempVars; + +/** + * This Control maintains a reference to a Camera, + * which will be synced with the position (worldTranslation) + * of the current spatial. Rotations are relative to the + * negative Z direction. + * + * @author Trevor Flynn + */ +public class GltfLightControl extends LightControl { + + public GltfLightControl() { + + } + + public GltfLightControl(Light light) { + this.setLight(light); + } + + @Override + protected void controlUpdate(float tpf) { + if (spatial != null && this.getLight() != null) { + switch (this.getControlDir()) { + case SpatialToLight: + spatialToLight(this.getLight()); + break; + case LightToSpatial: + lightToSpatial(this.getLight()); + break; + } + } + } + + private void spatialToLight(Light light) { + + final Vector3f worldTranslation = spatial.getWorldTranslation(); + + if (light instanceof PointLight) { + ((PointLight) light).setPosition(worldTranslation); + } else if (light instanceof DirectionalLight) { + ((DirectionalLight) light).setDirection(spatial.getLocalRotation().multLocal(new Vector3f(1f, -1f, 0f))); + } else if (light instanceof SpotLight) { + final SpotLight spotLight = (SpotLight) light; + spotLight.setPosition(worldTranslation); + spotLight.setDirection(spatial.getLocalRotation().multLocal(new Vector3f(1f, -1f, 0f))); + } + } + + private void lightToSpatial(Light light) { + TempVars vars = TempVars.get(); + if (light instanceof PointLight) { + + PointLight pLight = (PointLight) light; + + Vector3f vecDiff = vars.vect1.set(pLight.getPosition()).subtractLocal(spatial.getWorldTranslation()); + spatial.setLocalTranslation(vecDiff.addLocal(spatial.getLocalTranslation())); + } + + if (light instanceof DirectionalLight) { + DirectionalLight dLight = (DirectionalLight) light; + vars.vect1.set(dLight.getDirection()).multLocal(-1.0f); + Vector3f vecDiff = vars.vect1.subtractLocal(spatial.getWorldTranslation()); + spatial.setLocalTranslation(vecDiff.addLocal(spatial.getLocalTranslation())); + } + vars.release(); + //TODO add code for Spot light here when it's done + } +} diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java index 885266a88f..8619cf9d3e 100644 --- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java @@ -189,7 +189,7 @@ private void addLight(Node parent, Node node, int lightIndex) { if (lightDefinitions.containsKey(lightIndex)) { Light light = lightDefinitions.get(lightIndex); parent.addLight(light); - LightControl control = new LightControl(light); + LightControl control = new GltfLightControl(light); node.addControl(control); } else { throw new AssetLoadException("KHR_lights_punctual extension accessed undefined light at index " + lightIndex); From 9e140196bfde78f3953f55b7e62c07e5e4fb4015 Mon Sep 17 00:00:00 2001 From: Trevor Flynn Date: Sun, 17 Jan 2021 16:24:06 -0900 Subject: [PATCH 08/11] Update dumpScene to give more detailed information about lights --- .../scene/plugins/gltf/GltfLoaderTest.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/jme3-plugins/src/test/java/com/jme3/scene/plugins/gltf/GltfLoaderTest.java b/jme3-plugins/src/test/java/com/jme3/scene/plugins/gltf/GltfLoaderTest.java index 25156ae33a..0f54084392 100644 --- a/jme3-plugins/src/test/java/com/jme3/scene/plugins/gltf/GltfLoaderTest.java +++ b/jme3-plugins/src/test/java/com/jme3/scene/plugins/gltf/GltfLoaderTest.java @@ -2,8 +2,12 @@ import com.jme3.asset.AssetLoadException; import com.jme3.asset.AssetManager; +import com.jme3.light.DirectionalLight; import com.jme3.light.Light; +import com.jme3.light.PointLight; +import com.jme3.light.SpotLight; import com.jme3.material.plugin.TestMaterialWrite; +import com.jme3.math.Vector3f; import com.jme3.scene.Node; import com.jme3.scene.Spatial; import com.jme3.system.JmeSystem; @@ -64,7 +68,20 @@ private void dumpScene(Spatial s, int indent) { s.getLocalTransform().getRotation().toString() + ", " + s.getLocalTransform().getScale().toString()); for (Light light : s.getLocalLightList()) { - System.err.println(indentString.substring(0, indent + 1) + " (" + light.getClass().getSimpleName() + ")" ); + System.err.print(indentString.substring(0, indent + 1) + " (" + light.getClass().getSimpleName() + ")"); + if (light instanceof SpotLight) { + Vector3f pos = ((SpotLight) light).getPosition(); + Vector3f dir = ((SpotLight) light).getDirection(); + System.err.println(" " + pos.toString() + ", " + dir.toString()); + } else if (light instanceof PointLight) { + Vector3f pos = ((PointLight) light).getPosition(); + System.err.println(" " + pos.toString()); + } else if (light instanceof DirectionalLight) { + Vector3f dir = ((DirectionalLight) light).getDirection(); + System.err.println(" " + dir.toString()); + } else { + System.err.println(); + } } if (s instanceof Node) { Node n = (Node) s; From 9798ebf7299b07cea0eda669eb9af63a5cde56a1 Mon Sep 17 00:00:00 2001 From: Trevor Flynn Date: Tue, 23 Mar 2021 14:23:49 -0800 Subject: [PATCH 09/11] Updated to use built-in LightControl --- .../scene/plugins/gltf/GltfLightControl.java | 109 ------------------ .../gltf/LightsPunctualExtensionLoader.java | 2 +- .../scene/plugins/gltf/GltfLoaderTest.java | 10 +- 3 files changed, 6 insertions(+), 115 deletions(-) delete mode 100644 jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLightControl.java diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLightControl.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLightControl.java deleted file mode 100644 index a68ac9ad2c..0000000000 --- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLightControl.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2009-2021 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.scene.plugins.gltf; - -import com.jme3.light.DirectionalLight; -import com.jme3.light.Light; -import com.jme3.light.PointLight; -import com.jme3.light.SpotLight; -import com.jme3.math.Quaternion; -import com.jme3.math.Vector3f; -import com.jme3.scene.control.LightControl; -import com.jme3.util.TempVars; - -/** - * This Control maintains a reference to a Camera, - * which will be synced with the position (worldTranslation) - * of the current spatial. Rotations are relative to the - * negative Z direction. - * - * @author Trevor Flynn - */ -public class GltfLightControl extends LightControl { - - public GltfLightControl() { - - } - - public GltfLightControl(Light light) { - this.setLight(light); - } - - @Override - protected void controlUpdate(float tpf) { - if (spatial != null && this.getLight() != null) { - switch (this.getControlDir()) { - case SpatialToLight: - spatialToLight(this.getLight()); - break; - case LightToSpatial: - lightToSpatial(this.getLight()); - break; - } - } - } - - private void spatialToLight(Light light) { - - final Vector3f worldTranslation = spatial.getWorldTranslation(); - - if (light instanceof PointLight) { - ((PointLight) light).setPosition(worldTranslation); - } else if (light instanceof DirectionalLight) { - ((DirectionalLight) light).setDirection(spatial.getLocalRotation().multLocal(new Vector3f(1f, -1f, 0f))); - } else if (light instanceof SpotLight) { - final SpotLight spotLight = (SpotLight) light; - spotLight.setPosition(worldTranslation); - spotLight.setDirection(spatial.getLocalRotation().multLocal(new Vector3f(1f, -1f, 0f))); - } - } - - private void lightToSpatial(Light light) { - TempVars vars = TempVars.get(); - if (light instanceof PointLight) { - - PointLight pLight = (PointLight) light; - - Vector3f vecDiff = vars.vect1.set(pLight.getPosition()).subtractLocal(spatial.getWorldTranslation()); - spatial.setLocalTranslation(vecDiff.addLocal(spatial.getLocalTranslation())); - } - - if (light instanceof DirectionalLight) { - DirectionalLight dLight = (DirectionalLight) light; - vars.vect1.set(dLight.getDirection()).multLocal(-1.0f); - Vector3f vecDiff = vars.vect1.subtractLocal(spatial.getWorldTranslation()); - spatial.setLocalTranslation(vecDiff.addLocal(spatial.getLocalTranslation())); - } - vars.release(); - //TODO add code for Spot light here when it's done - } -} diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java index 8619cf9d3e..885266a88f 100644 --- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java @@ -189,7 +189,7 @@ private void addLight(Node parent, Node node, int lightIndex) { if (lightDefinitions.containsKey(lightIndex)) { Light light = lightDefinitions.get(lightIndex); parent.addLight(light); - LightControl control = new GltfLightControl(light); + LightControl control = new LightControl(light); node.addControl(control); } else { throw new AssetLoadException("KHR_lights_punctual extension accessed undefined light at index " + lightIndex); diff --git a/jme3-plugins/src/test/java/com/jme3/scene/plugins/gltf/GltfLoaderTest.java b/jme3-plugins/src/test/java/com/jme3/scene/plugins/gltf/GltfLoaderTest.java index 1734f77736..d9b873afa9 100644 --- a/jme3-plugins/src/test/java/com/jme3/scene/plugins/gltf/GltfLoaderTest.java +++ b/jme3-plugins/src/test/java/com/jme3/scene/plugins/gltf/GltfLoaderTest.java @@ -100,6 +100,10 @@ private void dumpScene(Spatial s, int indent) { s.getLocalTransform().getTranslation().toString() + ", " + s.getLocalTransform().getRotation().toString() + ", " + s.getLocalTransform().getScale().toString()); + if (s instanceof Geometry) { + System.err.print(" / " + ((Geometry) s).getMaterial()); + } + System.err.println(); for (Light light : s.getLocalLightList()) { System.err.print(indentString.substring(0, indent + 1) + " (" + light.getClass().getSimpleName() + ")"); if (light instanceof SpotLight) { @@ -116,11 +120,7 @@ private void dumpScene(Spatial s, int indent) { System.err.println(); } } - if (s instanceof Geometry) - { - System.err.print(" / " + ((Geometry) s).getMaterial()); - } - System.err.println(); + if (s instanceof Node) { Node n = (Node) s; for (Spatial spatial : n.getChildren()) { From 98c493af7b767cc4c3e70ec26feea6cea72d007e Mon Sep 17 00:00:00 2001 From: Trevor Flynn Date: Tue, 23 Mar 2021 14:47:50 -0800 Subject: [PATCH 10/11] Update javadocs --- .../gltf/LightsPunctualExtensionLoader.java | 57 ++++++++++++++++--- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java index 885266a88f..19c8eef6a5 100644 --- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java @@ -55,16 +55,19 @@ /** * Extension loader for KHR_lights_punctual extension which allows - * for lights to be added to the node from the gltf model - * Created by Trevor Flynn - 12/12/2020 + * for lights to be added to the node from the gltf model. + * + * Supports directional, point, and spot lights. + * + * Created by Trevor Flynn - 3/23/2021 */ public class LightsPunctualExtensionLoader implements ExtensionLoader { - private HashSet pendingNodes = new HashSet<>(); - private HashMap lightDefinitions = new HashMap<>(); + private final HashSet pendingNodes = new HashSet<>(); + private final HashMap lightDefinitions = new HashMap<>(); @Override - public Object handleExtension(GltfLoader loader, String parentName, JsonElement parent, JsonElement extension, Object input) throws IOException { + public Object handleExtension(GltfLoader loader, String parentName, JsonElement parent, JsonElement extension, Object input) { if (input instanceof Node) { //We are processing a node JsonObject jsonObject = extension.getAsJsonObject(); if (jsonObject.has("light")) { //These will get run first when loading the gltf file @@ -118,6 +121,11 @@ public Object handleExtension(GltfLoader loader, String parentName, JsonElement } } + /** + * Build a spot light from gltf json. + * @param obj The gltf json object for the spot light + * @return A spot light representation of the gltf object + */ private SpotLight buildSpotLight(JsonObject obj) { //Get properties String name = obj.has("name") ? obj.get("name").getAsString() : ""; @@ -135,7 +143,7 @@ private SpotLight buildSpotLight(JsonObject obj) { /* Correct floating point error on half PI, GLTF spec says that the outerConeAngle can be less or equal to PI/2, but JME requires less than PI/2. - We will being the angle within PI/2 if it is equal or larger than PI/2 + We will bring the angle within PI/2 if it is equal or larger than PI/2 */ if (outerConeAngle >= FastMath.HALF_PI) { outerConeAngle = FastMath.HALF_PI - 0.000001f; @@ -152,6 +160,11 @@ private SpotLight buildSpotLight(JsonObject obj) { return spotLight; } + /** + * Build a directional light from gltf json. + * @param obj The gltf json object for the directional light + * @return A directional light representation of the gltf object + */ private DirectionalLight buildDirectionalLight(JsonObject obj) { //Get properties String name = obj.has("name") ? obj.get("name").getAsString() : ""; @@ -168,6 +181,11 @@ private DirectionalLight buildDirectionalLight(JsonObject obj) { return directionalLight; } + /** + * Build a point light from gltf json. + * @param obj The gltf json object for the point light + * @return A point light representation of the gltf object + */ private PointLight buildPointLight(JsonObject obj) { //Get properties String name = obj.has("name") ? obj.get("name").getAsString() : ""; @@ -185,6 +203,13 @@ private PointLight buildPointLight(JsonObject obj) { return pointLight; } + /** + * Attach a light at the given index to the given parent node, + * and the control for the light to the given node. + * @param parent The node to attach the light to + * @param node The node to attach the light control to + * @param lightIndex The index of the light + */ private void addLight(Node parent, Node node, int lightIndex) { if (lightDefinitions.containsKey(lightIndex)) { Light light = lightDefinitions.get(lightIndex); @@ -196,11 +221,26 @@ private void addLight(Node parent, Node node, int lightIndex) { } } + /** + * Convert a floating point lumens value into a color that + * represents both color and brightness of the light. + * + * @param color The base color of the light + * @param lumens The lumnes value to convert to a color + * @return A color representing the intensity of the given lumens encoded into the given color + */ private ColorRGBA lumensToColor(ColorRGBA color, float lumens) { ColorRGBA brightnessModifier = lumensToColor(lumens); return color.mult(brightnessModifier); } + /** + * Convert a floating point lumens value into a grayscale color that + * represents a brightness. + * + * @param lumens The lumnes value to convert to a color + * @return A color representing the intensity of the given lumens + */ private ColorRGBA lumensToColor(float lumens) { /* Taken from /Common/ShaderLib/Hdr.glsllib @@ -224,7 +264,10 @@ vec4 HDR_EncodeLum(in float lum){ return color; } - private class NodeNeedingLight { + /** + * A bean to contain the relation between a node and a light index + */ + private static class NodeNeedingLight { private Node node; private int lightIndex; From e4d5817ae460f8e66f30f5d04760524bb345a189 Mon Sep 17 00:00:00 2001 From: Trevor Flynn Date: Tue, 23 Mar 2021 15:08:41 -0800 Subject: [PATCH 11/11] Make public members of private class private --- .../plugins/gltf/LightsPunctualExtensionLoader.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java index 19c8eef6a5..a98c500fa7 100644 --- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/LightsPunctualExtensionLoader.java @@ -271,24 +271,24 @@ private static class NodeNeedingLight { private Node node; private int lightIndex; - public NodeNeedingLight(Node node, int lightIndex) { + private NodeNeedingLight(Node node, int lightIndex) { this.node = node; this.lightIndex = lightIndex; } - public Node getNode() { + private Node getNode() { return node; } - public void setNode(Node node) { + private void setNode(Node node) { this.node = node; } - public int getLightIndex() { + private int getLightIndex() { return lightIndex; } - public void setLightIndex(int lightIndex) { + private void setLightIndex(int lightIndex) { this.lightIndex = lightIndex; } }