Skip to content

Commit ca9ec4c

Browse files
riccardoblCopilot
andcommitted
webp
Co-authored-by: Copilot <copilot@github.com>
1 parent ccfa164 commit ca9ec4c

9 files changed

Lines changed: 145 additions & 8 deletions

File tree

gradle/libs.versions.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ nifty-style-black = { module = "com.github.nifty-gui:nifty-style-black",
4848
spotbugs-gradle-plugin = "com.github.spotbugs.snom:spotbugs-gradle-plugin:6.4.8"
4949
vecmath = "javax.vecmath:vecmath:1.5.2"
5050

51-
stb-image = "org.ngengine:stb-image:2.30.3"
51+
stb-image = "org.ngengine:stb-image:2.30.4"
52+
imagewebp = "org.ngengine:image-webp-decoder:1.3.0"
5253

5354
[bundles]
5455

jme3-android/src/main/resources/com/jme3/asset/Android.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ INCLUDE com/jme3/asset/General.cfg
33
# Android specific locators
44
LOCATOR / com.jme3.asset.plugins.AndroidLocator
55

6-
LOADER com.jme3.texture.plugins.AndroidBufferImageLoader : webp, heic, heif
6+
LOADER com.jme3.texture.plugins.AndroidBufferImageLoader : heic, heif

jme3-core/src/main/resources/com/jme3/asset/General.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ LOADER com.jme3.scene.plugins.gltf.BinLoader : bin
2323
LOADER com.jme3.scene.plugins.gltf.GlbLoader : glb
2424
LOADER com.jme3.texture.plugins.StbImageLoader : jpg, bmp, gif, png, jpeg, tga, psd, hdr
2525
LOADER com.jme3.audio.plugins.OGGLoader : ogg
26+
LOADER com.jme3.texture.plugins.WebpImageLoader : webp

jme3-examples/src/main/java/jme3test/model/TestGltfLoading.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ public void simpleInitApp() {
118118
// loadModelSample("Lantern", "glb");
119119
// loadModelSample("RiggedFigure", "glb");
120120
// loadModelSample("SciFiHelmet", "gltf");
121-
loadModelSample("DamagedHelmet", "gltf");
121+
// loadModelSample("DamagedHelmet", "gltf");
122122
// loadModelSample("AnimatedCube", "gltf");
123123
// loadModelSample("AntiqueCamera", "glb");
124124
// loadModelSample("AnimatedMorphCube", "glb");
@@ -150,13 +150,13 @@ public void simpleInitApp() {
150150
// Test for normalized texture coordinates in draco
151151
//loadModelFromPath("Models/gltf/unitSquare11x11_unsignedShortTexCoords-draco.glb");
152152

153-
// Uses EXT_texture_webp - not supported yet
154-
//loadModelSample("SunglassesKhronos", "draco");
153+
// Uses EXT_texture_webp
154+
// loadModelSample("SunglassesKhronos", "draco");
155+
// loadModelSample("CarConcept", "webp");
155156

156157
// Probably invalid model
157158
// See https://github.com/KhronosGroup/glTF-Sample-Assets/issues/264
158159
// loadModelSample("VirtualCity", "draco");
159-
160160
probeNode.attachChild(assets.get(0));
161161

162162
inputManager.addMapping("autorotate", new KeyTrigger(KeyInput.KEY_SPACE));
@@ -213,10 +213,15 @@ private void loadModelSample(String name, String type) {
213213
path += "/glTF-Binary/";
214214
ext = "glb";
215215
break;
216+
case "webp":
217+
path += "/glTF-WEBP/";
218+
ext = "gltf";
219+
break;
216220
default:
217221
path += "/glTF/";
218222
ext = "gltf";
219223
break;
224+
220225
}
221226
path += name + "." + ext;
222227
loadModelFromPath(path);

jme3-plugins/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ dependencies {
1515
implementation project(':jme3-plugins-json')
1616
implementation project(':jme3-plugins-json-gson')
1717
implementation libs.stb.image
18+
implementation libs.imagewebp
1819

1920
testRuntimeOnly project(':jme3-desktop')
2021
}

jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ public class CustomContentManager {
7373
defaultExtensionLoaders.put("KHR_texture_transform", TextureTransformExtensionLoader.class);
7474
defaultExtensionLoaders.put("KHR_materials_emissive_strength", PBREmissiveStrengthExtensionLoader.class);
7575
defaultExtensionLoaders.put("KHR_draco_mesh_compression", DracoMeshCompressionExtensionLoader.class);
76+
defaultExtensionLoaders.put("EXT_texture_webp", TextureWebpExtensionLoader.class);
7677
}
7778

7879
/**

jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -940,8 +940,9 @@ public Texture2D readTexture(JsonObject texture, boolean flip) throws IOExceptio
940940
}
941941

942942
JsonObject textureData = textures.get(textureIndex).getAsJsonObject();
943-
Integer sourceIndex = getAsInteger(textureData, "source");
943+
Integer sourceIndex = TextureWebpExtensionLoader.getTextureSourceIndex(textureData);
944944
Integer samplerIndex = getAsInteger(textureData, "sampler");
945+
assertNotNull(sourceIndex, "Texture has no source");
945946

946947
texture2d = readImage(sourceIndex, flip);
947948

@@ -1708,4 +1709,4 @@ public static void registerDefaultExtrasLoader(Class<? extends ExtrasLoader> loa
17081709
public static void unregisterDefaultExtrasLoader() {
17091710
CustomContentManager.defaultExtraLoaderClass = UserDataLoader.class;
17101711
}
1711-
}
1712+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright (c) 2009-2024 jMonkeyEngine
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are
7+
* met:
8+
*
9+
* * Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
*
12+
* * Redistributions in binary form must reproduce the above copyright
13+
* notice, this list of conditions and the following disclaimer in the
14+
* documentation and/or other materials provided with the distribution.
15+
*
16+
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17+
* may be used to endorse or promote products derived from this software
18+
* without specific prior written permission.
19+
*
20+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22+
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28+
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+
*/
32+
package com.jme3.scene.plugins.gltf;
33+
34+
import static com.jme3.scene.plugins.gltf.GltfUtils.assertNotNull;
35+
import static com.jme3.scene.plugins.gltf.GltfUtils.getAsInteger;
36+
37+
import com.jme3.plugins.json.JsonElement;
38+
import com.jme3.plugins.json.JsonObject;
39+
import java.io.IOException;
40+
41+
/**
42+
* Handles EXT_texture_webp texture source selection.
43+
*/
44+
public class TextureWebpExtensionLoader implements ExtensionLoader {
45+
46+
static final String EXTENSION_NAME = "EXT_texture_webp";
47+
48+
static Integer getTextureSourceIndex(JsonObject textureData) {
49+
Integer sourceIndex = getAsInteger(textureData, "source");
50+
51+
JsonObject extensions = textureData.getAsJsonObject("extensions");
52+
if (extensions == null) {
53+
return sourceIndex;
54+
}
55+
56+
JsonObject webpExtension = extensions.getAsJsonObject(EXTENSION_NAME);
57+
if (webpExtension == null) {
58+
return sourceIndex;
59+
}
60+
61+
Integer webpSourceIndex = getAsInteger(webpExtension, "source");
62+
assertNotNull(webpSourceIndex, EXTENSION_NAME + " extension has no source");
63+
return webpSourceIndex;
64+
}
65+
66+
@Override
67+
public Object handleExtension(GltfLoader loader, String parentName, JsonElement parent, JsonElement extension,
68+
Object input) throws IOException {
69+
return input;
70+
}
71+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.jme3.texture.plugins;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
import java.nio.ByteBuffer;
6+
7+
import org.ngengine.webp.decoder.DecodedWebP;
8+
import org.ngengine.webp.decoder.WebPDecoder;
9+
10+
import com.jme3.asset.AssetInfo;
11+
import com.jme3.asset.AssetKey;
12+
import com.jme3.asset.AssetLoader;
13+
import com.jme3.asset.TextureKey;
14+
import com.jme3.export.binary.ByteUtils;
15+
import com.jme3.texture.Image;
16+
import com.jme3.texture.image.ColorSpace;
17+
import com.jme3.util.BufferUtils;
18+
19+
public class WebpImageLoader implements AssetLoader{
20+
21+
@Override
22+
public Object load(AssetInfo assetInfo) throws IOException {
23+
try{
24+
AssetKey<?> key = assetInfo.getKey();
25+
TextureKey textureKey = null;
26+
if(key instanceof TextureKey){
27+
textureKey = (TextureKey) key;
28+
}
29+
boolean flip = textureKey != null && textureKey.isFlipY();
30+
try(InputStream is = assetInfo.openStream()) {
31+
byte[] data = ByteUtils.getByteContent(is);
32+
DecodedWebP decoded = WebPDecoder.decode(data, BufferUtils::createByteBuffer);
33+
int w = decoded.width;
34+
int h = decoded.height;
35+
ByteBuffer rgba = decoded.rgba;
36+
if(flip){
37+
ByteBuffer flipped = BufferUtils.createByteBuffer(rgba.capacity());
38+
for(int y = h - 1; y >= 0; y--){
39+
int rowStart = y * w * 4;
40+
for(int x = 0; x < w * 4; x++){
41+
flipped.put(rgba.get(rowStart + x));
42+
}
43+
}
44+
flipped.flip();
45+
rgba = flipped;
46+
}
47+
Image jmeImage = new Image(Image.Format.RGBA8, w, h, rgba, ColorSpace.sRGB);
48+
return jmeImage;
49+
}
50+
}catch(Exception e){
51+
throw new IOException("Failed to load WebP image", e);
52+
}
53+
54+
}
55+
56+
}

0 commit comments

Comments
 (0)