Giter VIP home page Giter VIP logo

jgltf's Introduction

JglTF - Java libraries for glTF

Note: These libraries are still subject to change.

What is glTF?

The following image gives an overview of glTF:

gltfOverview-2.0.0-small.png

A larger version of this image, as well as PDF versions, can be found on the glTF overview releases page.


A note about glTF 2.0 support:

The libraries that are available here mostly support glTF 1.0 and glTF 2.0. Some special features that have been introduced in glTF 2.0 are not fully supported yet. This mainly refers to rendering glTF 2.0 assets in the jgltf-viewer, particularly the support of PBR (physically based rendering) and certain animation interpolation types. Support for these features will be implemented soon.


The libraries currently available here are

  • jgltf-impl-v1 and jgltf-impl-v2 : A very simple set of classes that represent glTF 1.0 and 2.0 data, auto-generated from the glTF JSON schema

  • jgltf-model : A library built on top of jgltf-impl-v1 and jgltf-impl-v2 that offers functionality for reading glTF data and accessing the associated data in a form that is more convenient for the use in Java. It serves as a thin abstraction layer around the auto-generated classes.

  • jgltf-obj : A library/application for loading OBJ files and converting them into glTF 1.0 or 2.0 assets.

  • jgltf-browser : A simple standalone application that combines functionalities of the JglTF libraries: It allows loading glTF 1.0 or 2.0 from files or URLs via drag-and-drop, offers a basic functionality for browsing through the glTF structure, showing the images, shader code and accessor data in a structured form, importing OBJ files as glTF, and saving glTF as standard, embedded or binary glTF files.

  • jgltf-viewer : A base library for glTF viewers

  • jgltf-impl-v2-technique-webgl : Auto-generated classes for the glTF 2.0 KHR_technique_webgl extension

  • jgltf-validator : A simple glTF validator, only intended for internal use

jgltf's People

Contributors

dependabot[bot] avatar javagl avatar yvesboyadjian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jgltf's Issues

Potential thread safety issue with V2 writeBinary

Hello,

We have a web service (spring boot) that produces GLB files on demand, recently it started to return "corrupted" files as more an more requests started to happen in parallel

The corruption seems inconsistent. But has some commonalities, the JSON and binary parts seems to be there and valid, but frequently the header would be wrong, or the BIN / JSON chunk type ASCII headers would be appear twice or missing entirely

Swapping to writeEmbedded resolved the issue immediately, and withstood an extreme load test I did (which writeBinary failed 1/100 files). So I'm assuming there's some issue buried within writeBinary

I haven't been able to track down the issue, but I thought I would raise the bug report either way incase your aware of something lurking in the code that might cause this

We are using 2.0.1 creating GLB v2 files

Transparent background for 3d model scene

Hi,
Thanks for making such an awesome library. I am using this library in android and trying to render a 3d model. The model is getting rendered correctly but the camera preview is getting obfuscated by a black screen. I have used the camera's view and projection matrix, how can I use the camera image data as the scene background or is it possible to make the scene background transparent?

Building jgltf-browser on MacOS

There has been a report about problems when building the jgltf-browser on MacOS in KhronosGroup/glTF#685 (comment)

I just tried it again, with a fresh clone of the repository:

  1. Create a directory for the test
  2. Run git clone https://github.com/javagl/JglTF.git to create the clone
  3. cd JglTF
  4. mvn clean install
  5. cd jgltf-browser (maybe you forgot this?)
  6. mvn clean compile assembly:single

The result should be a file
JglTF\jgltf-browser\target\jgltf-browser-0.0.0-SNAPSHOT-jar-with-dependencies.jar
that can directly be executed.


The handling of native libraries is always difficult. For JOGL, the natives are automatically loaded from the JAR. For LWJGL, they usually have to handled manually. Therefore, I just created a new preview release that has been repackaged with JarSplice, according to the recommendation for Distributing Your LWJGL Application on the LWJGL wiki.

The new preview release can be downloaded here:
https://github.com/javagl/JglTF/releases/tag/v0.0.0-alpha03

Hopefully, either the JOGL-based renderer or the LWJGL-based renderer will work. If there are problems or error messages, they can be reported here or in a dedicated issue.

Component Type 5125 (UNSIGNED_INT) for V1

JglTF\jgltf-impl-v1\src\main\java\de\javagl\jgltf\impl\v1\Accessor.java line 204

    public void setComponentType(Integer componentType) {
        if (componentType == null) {
            throw new NullPointerException((("Invalid value for componentType: "+ componentType)+", may not be null"));
        }
        if (((((componentType!= 5120)&&(componentType!= 5121))&&(componentType!= 5122))&&(componentType!= 5123))&&(componentType!= 5126)) {
            throw new IllegalArgumentException((("Invalid value for componentType: "+ componentType)+", valid: [5120, 5121, 5122, 5123, 5126]"));
        }
        this.componentType = componentType;
    }

This check doesn't have component type 5125 in the list of allowed types. I have V1 files that I need to convert to V2. Those V1 files work fine with three.js. I don't now it the type 5125 was added in V2 or already valid in V1?

Best regards,

Jan

P.S.: Thanks for the great lib.

jgltf-browser preview release 4 is not support glTF 1.1?

It seems that it becomes an error when reading the following sample.
https://cdn.rawgit.com/javagl/gltfTutorialModels/master/SimpleTexture/glTF/SimpleTexture.gltf

Errors (1)
  Message: The value is null when looking up key [exampleTexture]
  Context: glTF -> scenes[scene0] -> nodes[node0] -> meshes[mesh0] -> meshPrimitives[0] -> materials[textureMaterial] -> techniques[textureTechnique] -> uniform u_diffuse -> technique.parameters[diffuseParameter] -> textures[[exampleTexture]]
Warnings (1)
  Message: The value of techniqueParameters diffuseParameter is ArrayList, but should be String
  Context: glTF -> scenes[scene0] -> nodes[node0] -> meshes[mesh0] -> meshPrimitives[0] -> materials[textureMaterial] -> techniques[textureTechnique] -> uniform u_diffuse -> technique.parameters[diffuseParameter]

I want latest gltf-browser jar...

Make sure that semi-opaque objects are rendered correctly

(EDIT: Updated to fix a bug in the sample and the images)

Most of the information about how semi-opaque (or semi-transparent) objects should be rendered is encoded directly in the glTF asset. This information is contained in the technique.states and technique.states.functions. For example, the technique.states contains information about whether GL_BLEND is enabled or not. And technique.sates.functions contains information about the blend equation and blend functions.

(The only information that is not contained in the asset explicitly is the order in which the objects have to be rendered. Determining this order is far from trivial, and Order-Independent Transparency is an active research topic. For the simplest case, one has to make sure that opaque objects are rendered before semi-opaque objects are rendered. For the tests that are related to this issue, I implemented this locally in the jgltf-viewer, but these changes are not yet committed until this issue is resolved)

At the bottom of this issue, there is a glTF asset intended for testing the opacity handling.

The red triangle is rendered fully opaque, using the "opaqueTechnique".

The five blue triangles are rendered with different materials that use the "semiOpaqueTechnique":

  • "semiOpaqueMaterial0" with an opacity of 0.0 (fully transparent)
  • "semiOpaqueMaterial25" with an opacity of 0.25
  • "semiOpaqueMaterial50" with an opacity of 0.5
  • "semiOpaqueMaterial75" with an opacity of 0.75
  • "semiOpaqueMaterial100" with an opacity of 1.0 (fully opaque)

By default, the technique.states.functions of the semiOpaqueTechnique contain the following settings:

"blendEquationSeparate": [ 32774, 32774 ],  // GL_FUNC_ADD, GL_FUNC_ADD
"blendFuncSeparate": [ 1, 771, 1, 771 ], // GL_ONE, GL_ONE_MINUS_SRC_ALPHA (2x)

The result is shown in this image:

opacity_with_1_771

The materials are ordered from upper left to lower right. So the upper left blue triangle is supposed to be fully transparent. Obviously, the result is utterly wrong.

Intuitively, I'd expect the values for the blend function to be

"blendFuncSeparate": [ 770, 771, 770, 771 ], // GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA (2x)

Because the pixels should be written with the source alpha, and the existing background pixels should be "blended out" or "overwritten" depending on the source alpha. The result looks correct for me:

opacity_with_770_771

I could now start trying different values for the RGB- and the alpha part, but I'm not sure whether "trial and error" will help here. The tool at http://www.andersriggelsen.dk/glblendfunc.php might be helpful to try things out, but I'm not sure how to systematically figure out the right settings, because I'm not entirely sure what the result is supposed to look like at all...


The glTF asset used for testing. The buffer data is embedded. The shaders are given below.

{
  "scenes" : {
    "scene0" : {
      "nodes" : [ "node0", "node1", "node2", "node3", "node4", "node5" ]
    }
  },
  "nodes" : {
    "node0" : {
      "translation" : [ -0.5, -0.5, -1.0 ],
      "meshes" : [ "meshWithOpaqueMaterial" ]
    },
    "node1" : {
      "translation" : [ -0.5, -0.1, -0.99 ],
      "meshes" : [ "meshWithSemiOpaqueMaterial0" ]
    },
    "node2" : {
      "translation" : [ -0.4, -0.2, -0.98 ],
      "meshes" : [ "meshWithSemiOpaqueMaterial25" ]
    },
    "node3" : {
      "translation" : [ -0.3, -0.3, -0.97 ],
      "meshes" : [ "meshWithSemiOpaqueMaterial50" ]
    },
    "node4" : {
      "translation" : [ -0.2, -0.4, -0.96 ],
      "meshes" : [ "meshWithSemiOpaqueMaterial75" ]
    },
    "node5" : {
      "translation" : [ -0.1, -0.5, -0.95 ],
      "meshes" : [ "meshWithSemiOpaqueMaterial100" ]
    }
  },
  
  "meshes" : {
    "meshWithOpaqueMaterial" : {
      "primitives" : [ {
        "attributes" : {
          "POSITION" : "positionsAccessor",
          "NORMAL" : "normalsAccessor",
          "TEXCOORD_0" : "texCoordsAccessor"
        },
        "indices" : "indicesAccessor",
        "material" : "opaqueMaterial"
      } ]
    },
    "meshWithSemiOpaqueMaterial0" : {
      "primitives" : [ {
        "attributes" : {
          "POSITION" : "positionsAccessor",
          "NORMAL" : "normalsAccessor",
          "TEXCOORD_0" : "texCoordsAccessor"
        },
        "indices" : "indicesAccessor",
        "material" : "semiOpaqueMaterial0"
      } ]
    },
    "meshWithSemiOpaqueMaterial25" : {
      "primitives" : [ {
        "attributes" : {
          "POSITION" : "positionsAccessor",
          "NORMAL" : "normalsAccessor",
          "TEXCOORD_0" : "texCoordsAccessor"
        },
        "indices" : "indicesAccessor",
        "material" : "semiOpaqueMaterial25"
      } ]
    },
    "meshWithSemiOpaqueMaterial50" : {
      "primitives" : [ {
        "attributes" : {
          "POSITION" : "positionsAccessor",
          "NORMAL" : "normalsAccessor",
          "TEXCOORD_0" : "texCoordsAccessor"
        },
        "indices" : "indicesAccessor",
        "material" : "semiOpaqueMaterial50"
      } ]
    },
    "meshWithSemiOpaqueMaterial75" : {
      "primitives" : [ {
        "attributes" : {
          "POSITION" : "positionsAccessor",
          "NORMAL" : "normalsAccessor",
          "TEXCOORD_0" : "texCoordsAccessor"
        },
        "indices" : "indicesAccessor",
        "material" : "semiOpaqueMaterial75"
      } ]
    },
    "meshWithSemiOpaqueMaterial100" : {
      "primitives" : [ {
        "attributes" : {
          "POSITION" : "positionsAccessor",
          "NORMAL" : "normalsAccessor",
          "TEXCOORD_0" : "texCoordsAccessor"
        },
        "indices" : "indicesAccessor",
        "material" : "semiOpaqueMaterial100"
      } ]
    }
  },

  "materials" : {
    "opaqueMaterial" : {
      "technique" : "opaqueTechnique",
      "values": {
        "diffuseParameter": [ 1.0, 0.0, 0.0, 1.0 ]
      }
    },
    "semiOpaqueMaterial0" : {
      "technique" : "semiOpaqueTechnique",
      "values": {
        "opacityParameter" : [ 0.0 ],
        "diffuseParameter": [ 0.0, 0.0, 1.0, 1.0 ]
      }
    },
    "semiOpaqueMaterial25" : {
      "technique" : "semiOpaqueTechnique",
      "values": {
        "opacityParameter" : [ 0.25 ],
        "diffuseParameter": [ 0.0, 0.0, 1.0, 1.0 ]
      }
    },
    "semiOpaqueMaterial50" : {
      "technique" : "semiOpaqueTechnique",
      "values": {
        "opacityParameter" : [ 0.50 ],
        "diffuseParameter": [ 0.0, 0.0, 1.0, 1.0 ]
      }
    },
    "semiOpaqueMaterial75" : {
      "technique" : "semiOpaqueTechnique",
      "values": {
        "opacityParameter" : [ 0.75 ],
        "diffuseParameter": [ 0.0, 0.0, 1.0, 1.0 ]
      }
    },
    "semiOpaqueMaterial100" : {
      "technique" : "semiOpaqueTechnique",
      "values": {
        "opacityParameter" : [ 1.0 ],
        "diffuseParameter": [ 0.0, 0.0, 1.0, 1.0 ]
      }
    }
  },
  "techniques": {
  
    "opaqueTechnique": {
      "program": "opacityProgram",
      "attributes": {
        "a_position": "positionParameter",
        "a_normal": "normalParameter"
      },
      "uniforms": {
        "u_modelViewMatrix": "modelViewMatrixParameter",
        "u_normalMatrix": "normalMatrixParameter",
        "u_projectionMatrix": "projectionMatrixParameter",
        "u_ambient": "ambientParameter",
        "u_diffuse": "diffuseParameter",
        "u_specular": "specularParameter",
        "u_shininess": "shininessParameter",
        "u_opacity": "opacityParameter"
      },
      "parameters": {
        "positionParameter" : {
          "type": 35665,
          "semantic": "POSITION"
        },
        "normalParameter" : {
          "type": 35665,
          "semantic": "NORMAL"
        },
        "modelViewMatrixParameter": {
          "type": 35676,
          "semantic": "MODELVIEW"
        },
        "normalMatrixParameter": {
          "type": 35675,
          "semantic": "MODELVIEWINVERSETRANSPOSE"
        },
        "projectionMatrixParameter": {
          "type": 35676,
          "semantic": "PROJECTION"
        },
        "ambientParameter": {
          "type": 35666,
          "value": [ 0.1, 0.1, 0.1, 1.0 ]
        },
        "diffuseParameter": {
          "type": 35666,
          "value": [ 1.0, 1.0, 1.0, 1.0 ]
        },
        "specularParameter": {
          "type": 35666,
          "value": [ 1.0, 1.0, 1.0, 1.0 ]
        },
        "shininessParameter": {
          "type": 5126,
          "value": [ 100.0 ]
        },
        "opacityParameter": {
          "type": 5126,
          "value": [ 1.0 ]
        }
      },
      "states": {
        "enable": [ 2929 ]
      }
    },
    
    "semiOpaqueTechnique": {
      "program": "opacityProgram",
      "attributes": {
        "a_position": "positionParameter",
        "a_normal": "normalParameter"
      },
      "uniforms": {
        "u_modelViewMatrix": "modelViewMatrixParameter",
        "u_normalMatrix": "normalMatrixParameter",
        "u_projectionMatrix": "projectionMatrixParameter",
        "u_ambient": "ambientParameter",
        "u_diffuse": "diffuseParameter",
        "u_specular": "specularParameter",
        "u_shininess": "shininessParameter",
        "u_opacity": "opacityParameter"
      },
      "parameters": {
        "positionParameter" : {
          "type": 35665,
          "semantic": "POSITION"
        },
        "normalParameter" : {
          "type": 35665,
          "semantic": "NORMAL"
        },
        "modelViewMatrixParameter": {
          "type": 35676,
          "semantic": "MODELVIEW"
        },
        "normalMatrixParameter": {
          "type": 35675,
          "semantic": "MODELVIEWINVERSETRANSPOSE"
        },
        "projectionMatrixParameter": {
          "type": 35676,
          "semantic": "PROJECTION"
        },
        "ambientParameter": {
          "type": 35666,
          "value": [ 0.1, 0.1, 0.1, 1.0 ]
        },
        "diffuseParameter": {
          "type": 35666,
          "value": [ 1.0, 1.0, 1.0, 1.0 ]
        },
        "specularParameter": {
          "type": 35666,
          "value": [ 1.0, 1.0, 1.0, 1.0 ]
        },
        "shininessParameter": {
          "type": 5126,
          "value": [ 100.0 ]
        },
        "opacityParameter": {
          "type": 5126,
          "value": [ 0.5 ]
        }
      },
      "states": {
        "enable": [ 2929, 3042 ],
        "functions": {
          "blendEquationSeparate": [ 32774, 32774 ],
          "blendFuncSeparate": [ 1, 771, 1, 771],
          "depthMask": [false]
        }
      }
    }
    
  },
  "programs": {
    "opacityProgram": {
      "vertexShader": "opacityVertexShader",
      "fragmentShader": "opacityFragmentShader",
      "attributes": [
        "a_position",
        "a_normal"
      ]
    }
  },
  "shaders": {
    "opacityVertexShader": {
      "type": 35633,
      "uri": "opacity.vert"
    },
    "opacityFragmentShader": {
      "type": 35632,
      "uri": "opacity.frag"
    }
  },

  "buffers" : {
    "buffer0" : {
      "uri" : "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/",
      "byteLength" : 108
    }
  },
  "bufferViews" : {
    "indicesBufferView" : {
      "buffer" : "buffer0",
      "byteOffset" : 0,
      "byteLength" : 6,
      "target" : 34963
    },
    "attributesBufferView" : {
      "buffer" : "buffer0",
      "byteOffset" : 6,
      "byteLength" : 96,
      "target" : 34962
    }
  },
  "accessors" : {
    "indicesAccessor" : {
      "bufferView" : "indicesBufferView",
      "byteOffset" : 0,
      "componentType" : 5123,
      "count" : 3,
      "type" : "SCALAR",
      "max" : [ 2.0 ],
      "min" : [ 0.0 ]
    },
    "positionsAccessor" : {
      "bufferView" : "attributesBufferView",
      "byteOffset" : 0,
      "componentType" : 5126,
      "count" : 3,
      "type" : "VEC3",
      "max" : [ 1.0, 1.0, 0.0 ],
      "min" : [ 0.0, 0.0, 0.0 ]
    },
    "normalsAccessor" : {
      "bufferView" : "attributesBufferView",
      "byteOffset" : 36,
      "componentType" : 5126,
      "count" : 3,
      "type" : "VEC3",
      "max" : [ 0.0, 0.0, 1.0 ],
      "min" : [ 0.0, 0.0, 1.0 ]
    },
    "texCoordsAccessor" : {
      "bufferView" : "attributesBufferView",
      "byteOffset" : 72,
      "componentType" : 5126,
      "count" : 3,
      "type" : "VEC2",
      "max" : [ 1.0, 1.0 ],
      "min" : [ 0.0, 0.0 ]
    }
  },
  "asset" : {
    "version" : "1.1"
  }
}

The opacity.vert vertex shader:

#ifdef GL_ES
    precision highp float;
#endif

attribute vec3 a_position;
attribute vec3 a_normal;

uniform mat3 u_normalMatrix;
uniform mat4 u_modelViewMatrix;
uniform mat4 u_projectionMatrix;

varying vec3 v_position;
varying vec3 v_normal;

varying vec3 v_light0Direction;

void main(void) 
{
    vec4 pos = u_modelViewMatrix * vec4(a_position, 1.0);
    v_normal = u_normalMatrix * a_normal;
    v_position = pos.xyz;
    v_light0Direction = mat3(u_modelViewMatrix) * vec3(1.0, 1.0, 1.0);
    gl_Position = u_projectionMatrix * pos;
}

The opacity.frag fragment shader:

#ifdef GL_ES
    precision highp float;
#endif

varying vec3 v_position;
varying vec3 v_normal;

uniform vec4 u_ambient;
uniform vec4 u_diffuse;
uniform vec4 u_specular;
uniform float u_shininess;
uniform float u_opacity;

varying vec3 v_light0Direction;

void main(void) 
{
    vec3 normal = normalize(v_normal);
    vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
    vec3 diffuseLight = vec3(0.0, 0.0, 0.0);
    vec3 lightColor = vec3(1.0, 1.0, 1.0);
    vec4 ambient = u_ambient;
    vec4 diffuse = u_diffuse;
    vec4 specular = u_specular;

    vec3 specularLight = vec3(0.0, 0.0, 0.0);
    {
        float specularIntensity = 0.0;
        float attenuation = 1.0;
        vec3 l = normalize(v_light0Direction);
        vec3 viewDir = -normalize(v_position);
        vec3 h = normalize(l+viewDir);
        specularIntensity = max(0.0, pow(max(dot(normal,h), 0.0) , u_shininess)) * attenuation;
        specularLight += lightColor * specularIntensity;
        diffuseLight += lightColor * max(dot(normal,l), 0.0) * attenuation;
    }
    specular.xyz *= specularLight;
    diffuse.xyz *= diffuseLight;
    color.xyz += ambient.xyz;
    color.xyz += diffuse.xyz;
    color.xyz += specular.xyz;
    color = vec4(color.rgb * diffuse.a, diffuse.a * u_opacity);
    gl_FragColor = color;
}

Unsupported textures file formats: DDS

Hello,
I emailed Marco Hutter, the JavaGL author with a question about the DDS format support, since I needed it in my tool. Maybe someone reading this would find it helpful. Next time I will just open an issue initially - this is my first :)

What is .dds file format?

Issue: DDS is unsupported, jgltf-model version 2.0.1

  • [Context] - Theย javagl/JglTFย library of yours, could be pricelessly useful in my non-profit small-scope project. Projectโ€™s main goal is to convert 3D models OBJ files to GLB format automatically as a part of website functionality. Your tool is the best possible choice for this task - it works perfectly for PNG and JPEG textures. Although many computer games use DDS format files. The DDS makes it possible to reduce the amount of memory that textures use by lowering the quality a little.
    t file takes less space than actual โ€œEMBEDDEDโ€ option. The following error stack trace is being printed:

  • [Error] - java.lang.IllegalArgumentException: Invalid value for mimeType: image/dds, valid: ["image/jpeg", "image/png"]
    at de.javagl.jgltf.impl.v2.Image.setMimeType(Image.java:81)
    at de.javagl.jgltf.model.io.v2.BinaryAssetCreatorV2.create(BinaryAssetCreatorV2.java:169)
    at de.javagl.jgltf.model.io.v2.GltfModelWriterV2.writeBinary(GltfModelWriterV2.java:88)
    at de.javagl.jgltf.model.io.GltfModelWriter.writeBinary(GltfModelWriter.java:148)
    at de.javagl.jgltf.model.io.GltfModelWriter.writeBinary(GltfModelWriter.java:120)

  • [Conclusion] - It looks like the class โ€œMimeTypesโ€ does not support the DDS format, as well as all dependency classes, such as โ€œBinaryAssetCreatorV2โ€.
    Is there anything you could do in order to add the DDS format support to yourย https://github.com/javagl/JglTFย library?
    I will be happy to provide more details and help you in any further process โ€” feel free to ask if there is anything you would like to know about the issue.

Marcos (JavaGL/JglTF author) response in short:

  • "... I'm aware of the problem that you described. ..."
  • "...And in fact, I already removed this check a few months ago: commit . So in the version of JglTF that can currently be found in the repository, the problem should already be solved. ..."
  • "... The updated version is NOT yet published in Maven Central.ย ..."

@javagl Thank you for your fast and professional response. If possible, please also let us know when the version 2.0.2 of jgltf-model dependency is published to Maven repo.

No vertex skinning when default material is used

The spec is (or was) silent on this point. The naive implementation of the "default material" (which should be used when no material was given) consists of a fragment shader that just emits the gray color, and a vertex shader that does the usual GL transforms.

However, this "default vertex shader" does not support skinning, because it does not have joint- and weight attributes.

This is not a big issue for now, especially considering the transition to glTF 2.0, but mentioned here so that it does not get lost.

Add support for other LWJGL- and OpenGL versions

Based on the discussion in #11 (comment) there are two tasks that would help to increase the number of supported platforms:

  1. Adding support for LWJGL3. As a replacement of the AWTGLCanvas that was removed in LWJGL3, the https://github.com/httpdigest/lwjgl3-awt could be used. A pressing reasons for an update to LWJGL3 (or rather: for an additional viewer implementation based on LWJGL3) could be when someone wants to use the viewer in his own "standalone" progam that is already based on LWJGL3
  2. Retrofit the existing viewer implementations so that they only need OpenGL 2.0. This should be easy, because except for vertex array objects, all the functionalities that are currently used have already been available in OpenGL 2.0.

Replace the sampleModels.config with the sample models index file

The https://github.com/javagl/JglTF/blob/master/jgltf-browser/src/main/resources/sampleModels.config is used for automatically building the Menu hierarchy for loading the sample models in the browser. Updating this file obviously is a hassle.

If there one day is an index file (as in KhronosGroup/glTF-Sample-Models#77 ), this index file could be used instead. (Iff this file still offers the option to redirect to local directories etc.)

Some fixable bugs and improvements that can be applied

Recently I just finish porting your work to Minecraft, almost every feature from glTF spec works great and fine.
During development, I discover some issues and potential improvements in JglTF, but these are quite easy to fix and add.

1. MeshModel#getWeights() should pass reference like NodeModel#getWeights()

* Returns a copy of the default morph target weights, or <code>null</code>

* Returns a <b>reference</b> to the morph target weights,

private Runnable createAttributeUpdateCommand(

The System$arraycopy is already been used in attributes update command, there is no need to clone array before aquire it.

2. AbstractAccessorData#getByteIndex(int elementIndex, int componentIndex) return wrong index if componentType were byte and short, and elementType was not a matrix.

This was discovered when writting my own attributes unindexer for Mikk tangent generator and flat normal generator.

protected final int getByteIndex(int elementIndex, int componentIndex)

It seem like you forget to add else clause if elementType is not a matrix.

https://github.com/TimLee9024/MCglTF/blob/83a8578aae849dd5cf3f31e2adbd9399719ba377/src/main/java/de/javagl/jgltf/model/AbstractAccessorData.java#L147

3. Binary data of .glb should be allocated as direct ByteBuffer

Since I can not find anywhere in your code that convert loaded binary data to direct ByteBuffer before GltfModel is created for OpenGL use. I decide to convert them in RawBinaryGltfDataReader V1 and V2.

TimLee9024/MCglTF@cff5cde

4. Add an abstract getFloat method in AccessorData interface, and return float value from normalized result in AccessorByteData, AccessorShortData, and AccessorIntData.

In glTF spec, attributes like TEXCOORD_n and COLOR_n can be byte normalized and short normalized, but you will need to convert them to float before processing with Mikk tangent generator and creating attributes update command.
The algorithm for converting integer to float is described as Normalized Integer in OpenGL wiki and the following is the implemetation that can be in your code.

AccessorData

float getFloat(int elementIndex, int componentIndex);

AccessorByteData

public float getFloat(int elementIndex, int componentIndex) {
	byte value = get(elementIndex, componentIndex);
	return unsigned ? Byte.toUnsignedInt(value) / (Byte.MAX_VALUE - Byte.MIN_VALUE) : Math.max(value / Byte.MAX_VALUE, -1.0F);
}

AccessorShortData

public float getFloat(int elementIndex, int componentIndex) {
	short value = get(elementIndex, componentIndex);
	return unsigned ? Short.toUnsignedInt(value) / (Short.MAX_VALUE - Short.MIN_VALUE) : Math.max(value / Short.MAX_VALUE, -1.0F);
}

AccessorIntData

public float getFloat(int elementIndex, int componentIndex) {
	int value = get(elementIndex, componentIndex);
	return unsigned ? Integer.toUnsignedLong(value) / (Integer.MAX_VALUE - Integer.MIN_VALUE) : Math.max(value / Integer.MAX_VALUE, -1.0F);
}

AccessorFloatData

public float getFloat(int elementIndex, int componentIndex) {
	return get(elementIndex, componentIndex);
}

Need help on GLB/gITF parser

Hi,

I'm learning about 3D glTF and GLB format. I would like to build feature to parse meta-data of these file in Java.
Do we have GLB parser to parse meta-data or detect glb, get dimension and others?
I see we have gltf validator in java. Can we convert glb to gltf in java?

Thank you !

Best,
Khanh

jgltf-model not portable to Android

The jgltf-model implementation uses JDK 1.8 language constructs that are not portable to Android yet. It would be nice if this was a cross-platform implementation.

Is there still exist GltfDataReader in the new JglTF version?

Hi,

Is there still exist GltfDataReader in the new JglTF package? @javagl

With the jgltf-model-0.0.0-SNAPSHOT.jar package I can use the code below to get and convert glTF1.0 file to glb.

    GltfDataReader r = new GltfDataReader();
    GltfData gltfData = r.readGltfData(gltfuri);
    gltfData = new GltfDataToBinaryConverter().convert(gltfData);
    BinaryGltfDataWriter w = new BinaryGltfDataWriter();
    w.writeBinaryGltfData(gltfData, glburi);

Recently, I want to use GltfDataReader to get glTF2.0 file and convert it to glb. But in the new new JglTF package, I can't find GltfDataReader, gltfData, GltfDataToBinaryConverter() and BinaryGltfDataWriter.

Sincerely,
Frank-Chan

Improve handling of optional properties and default values

This issue summarizes several (closely related) design choices, and some first thoughts about possible solutions.

Feel free to add feedback and comments here.

The jgltf-impl classes are automatically generated from the schema. In order to handle the "optional" properties, the fields of the resulting objects may be null to indicate that the property was not set in the JSON input. As a result, the handling of these classes is rather inconvenient.


Issue: Optional dictionaries

The maps ("dictionaries") are usually optional, and thus, they may be null. Therefore, e.g. adding a Buffer to a given GlTF requires several lines of code:

Map<String, Buffer> oldBuffers = gltf.getBuffers();
Map<String, Buffer> newBuffers = new LinkedHashMap<String, Buffer>();
if (oldBuffers != null) {
    newBuffers.putAll(oldBuffers);
}
newBuffers.put("buffer", buffer);
gltf.setBuffers(newBuffers);

(this assumes that the maps may not always be mutable)

Possible solution: Automatic bookkeeping for dictionaries

For the case of maps ("dictionaries"), the bookeeping that is sketched in the first code snippet could be automated. This could be achieved by adding methods for adding/removing elements:

void addBuffer(String key, Buffer value) {
    // Create new Map if it was "null" until now, and add the given mapping
    ...
}
void removeBuffer(String key) {
    // Remove the given mapping, and set the map to "null" if it is empty now
    ....
}

Issue: Traversal with optional values

Traversing the object hierarchy is tedious, because the treatment of possible nulls is not always clear:

Map<String, String> uniforms = technique.getUniforms();
if (uniforms == null) handleThis(); // Have to check this
String techniqueParameterId = uniforms.get(uniformName);
if (techniqueParameterId == null) handleThis(); // Have to check this
Map<String, TechniqueParameters> parameters = technique.getParameters();
if (parameters == null) handleThis(); // Have to check this
TechniqueParameters techniqueParameters = parameters.get(techniqueParameterId);
if (techniqueParameters == null) handleThis(); // Have to check this

It is difficult to distinguish the cases where a value is optional, in the sense of the JSON schema, and where a value is expected in the sense of the specification.

Possible solution: Use of Java Optional

The traversing could be simplified with the use of the Java 8 Optional class. It will likely not make sense to use this directly as the properties in the jgltf-impl classes. Instead, it could be used in the convenience functions of the jgltf-model classes. But there, it would help to avoid many cases where now a null has to be returned or a GltfException has to be thrown.


Issue: Unknown default values

The optional properties in glTF have default values. These default values are currently only given in the JavaDoc of the respective properties. This may lead to code like

Integer target = bufferView.getTarget();
if (target == null) target = GL.GL_ARRAY_BUFFER; // Insert default value here

where the default value has to be inserted manually.

Possible solution: Dedicated methods for obtaining default values

For the automatic JSON serialization/deserialization, the current implementation of properties with set/get methods and null values is convenient. However, in order to simplify the handling of default values, one could add dedicated methods to obtain a value that is guaranteed to never be null, and in doubt just returns the default value. For example:

class BufferView {
    private Integer target = null;

    // The usual set/get pair
    public void setTarget(Integer target) { ...  this.target = target;   }
    public Integer getTarget() { return this.target; }

    // Additional method that never returns null:
    public Integer getTargetOrDefault() { 
        return this.target != null ? this.target : GL.GL_ARRAY_BUFFER:
    }
}

Feel free to add feedback and comments here.

Add an option to fit the external camera to the scene

For large scenes, and particularly for scenes with a large translation in the root node (as in KhronosGroup/glTF#781 ) it is essential to have an option to fit the camera to the whole scene.

Parts of the implementation may later be moved to https://github.com/javagl/Rendering/tree/master/rendering-core/src/main/java/de/javagl/rendering/core/view , but the computation of the bounding volumes of the (transformed) geometry has to be done in the glTF model classes.

While resolving this issue, consider adding an option to let the external camera "match" one of the cameras in the glTF, so that the viewer may start with the predefined view configurations, but still navigate through the scene.

Accessing mesh names from jgltf-model

It seems like mesh names are not available when accessing a scene using the jgltf-model. It seems like they are available in jgltf-impl-v2.
Is this by design or is there a way to find them that I have overlooked?

Using Macbook pro, gltf file not getting rendered.

Java code

public static void main(String[] args) throws Exception
{
    String uriString = 
        "https://raw.githubusercontent.com/KhronosGroup/" + 
        "glTF-Sample-Models/master/2.0/Duck/glTF/Duck.gltf";
    GltfModelReader r = new GltfModelReader();
    GltfModel gltfModel = r.read(new URI(uriString));
    SwingUtilities.invokeLater(() -> createAndShowGui(gltfModel));
}

private static void createAndShowGui(GltfModel gltfModel)
{
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    // Create a viewer based on JOGL or LWJGL:
    GltfViewer<Component> gltfViewer = new GltfViewerJogl();
    //GltfViewer<Component> gltfViewer = new GltfViewerLwjgl();
    
    gltfViewer.addGltfModel(gltfModel);
    f.getContentPane().add(gltfViewer.getRenderComponent());
    f.setSize(500,500);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
}

Getting below issue,

Mar 01, 2019 5:50:00 PM de.javagl.jgltf.viewer.AbstractGltfViewer createRenderedGltf
INFO: Creating rendered glTF
Mar 01, 2019 5:50:00 PM de.javagl.jgltf.viewer.jogl.GlContextJogl printShaderLogInfo
WARNING: shader log:
ERROR: 0:2: '' : #version required and missing.
ERROR: 0:2: 'attribute' : syntax error: syntax error๏ฟฝ
Mar 01, 2019 5:50:00 PM de.javagl.jgltf.viewer.jogl.GlContextJogl createGlShader
WARNING: glShader :::::null
Mar 01, 2019 5:50:00 PM de.javagl.jgltf.viewer.jogl.GlContextJogl createGlShader
WARNING: Inserting GLSL version specifier "#version 120" in shader code
Mar 01, 2019 5:50:00 PM de.javagl.jgltf.viewer.jogl.GlContextJogl printShaderLogInfo
WARNING: shader log:
ERROR: 0:1: '' : version '120' is not supported
ERROR: 0:2: '' : #version required and missing.
ERROR: 0:3: 'attribute' : syntax error: syntax error๏ฟฝ
Mar 01, 2019 5:50:00 PM de.javagl.jgltf.viewer.jogl.GlContextJogl createGlProgram
WARNING: Creating vertex shader FAILED
Mar 01, 2019 5:50:00 PM de.javagl.jgltf.viewer.GltfRenderData createGlProgram
WARNING: Creating GL program for de.javagl.jgltf.model.gl.impl.DefaultProgramModel@60a32057 FAILED
Mar 01, 2019 5:50:00 PM de.javagl.jgltf.viewer.DefaultRenderedGltfModel processMeshPrimitiveModel
WARNING: No GL program found for program de.javagl.jgltf.model.gl.impl.DefaultProgramModel@60a32057 in technique de.javagl.jgltf.model.gl.impl.DefaultTechniqueModel@3af72daf

Writing/Reading a mesh format that defines a color/texture per triangle instead of per vertex

I'm looking for the best possible option to convert a custom mesh format to glTF (and vice versa) that defines solid colors and textures per triangle.

In case this helps, here's an overview of my format:

  • Vertices array (Vec3f)
  • Indices array (Vec3f)
  • Triangle/Face colors array (Integer, 24-bit RGB values) - This is per triangle
  • Texture Ids array (Integer) - This is per triangle
  • Triangle Flags array(Integer, determines whether to use a color from the colors or textures array) - This is per triangle
  • Texture coordinate arrays (float[][] uCoordinates, float[][] vCoordinates) - Per triangle, accessed like this:
// length 3, stores u/v coordinates for each vertex of that triangle
float[] u = uCoordinates[triangleIndex]
float[] v = vCoordinates[triangleIndex]

My ideas so far:

  1. Possibly the worst one: From the glTF specification i found that you can specify a vertex color, so my idea was to simply specify for each triangle the same vertex color, that did not work out well as blender seems to be interpolating vertex colors even if normals are not defined(unless i did something wrong myself)
  2. Convert all of the solid colors and textures that the mesh uses into one single texture and compute appropriate texture coordinates (this process should also be reversible however the main problem i have with it is that ideally i'd want to define per face colors/textures so that individual faces can be painted with a specific color/texture easily)
  3. Create multiple MeshPrimitive's, group by material (i.e for each unique material in the mesh create a MeshPrimitive) however that'd still limit editing individual faces i believe.
  4. another possibly bad solution: Create one mesh primitive per triangle

My goal is to export the custom mesh format to glTF, then import that in blender for easy editing (the geometry, the materials in a way that allows u to edit them per face) and i also want to be able to take the mesh edited in blender(exported as glTF) and convert that back to the custom format.
Any suggestions would be greatly appreciated (if i didn't clarify some parts well enough, please let me know)

Note: I have done this before usong different formats (MQO and OBJ) where i defined the data for each triangle like this(MQO example):

// faces followed by the number of faces/triangles in the mesh
faces 153 {
  // component count of vertex(it's a triangle so it's 3 here), The vertex indices (in the vertex array, defined earlier in the file) Material index (defined earlier in the file), Texture coordinates for that triangle
  3 V(18 13 12) M(256) UV(0.078947365 -0.045834996 0.05263158 0.4348346 0.18421052 -0.023515346)
  etc
}

but now i need to somehow achieve this with glTF (as the other formats i've used so far don't support skeletal animation) and I picked glTF because it has really good specification/documentation and there's this great library for it to deal with glTF reading/writing in java

Consider exposing the camera parameters from the CameraModel

The CameraModel currently offers the functions that are required for using the camera for rendering, namely the view- and projection matrices.

This is an abstraction over several aspects:

  • Whether the asset is a glTF 1.0 or a glTF 2.0 asset
  • Whether the camera is a perspective or orthographic camera

(The actual computation of the matrices is hidden in an internal class that is structurally not so nice, but an implementation detail for now)

In order to allow clients to set up the matrices on their own, the type of the camera (orthographic vs. perspective) and the related parameters (like the FOV) might be exposed via the model in one form or the other.

Obj2Gltf doesn't always convert materials

I've spent some time trying to get this library to use the proper materials in the glTF files it creates, without success. I decided to do a sanity check and attempt to use Obj2Gltf to convert a .obj created with this library to glTF and see if materials were imported. To my surprise, they were not.

Every OBJ viewer I have tried loads the materials properly. The materials, in this case, are just some colors, and not any textures. The materials are stored in a .mtl file with the same basename and path as the .obj file.

If you would like the files I am using, please let me know.

Using Jgltf-model under Android API level 24

Hi,

I am currently working on a project that tries to use Jgltf-model to extract data from glTF model. However, I noticed that Jgltf-model doesn't work below Android API level 24 because of the usage of java.util.function. I got the majority of the model rendered on Android over API level 24 and want to make it also work below API level 24. I am pretty new to Android programming and wondering if there are any suggestions on replacing the classes in java.util.function and get it to work below API level 24.

Thanks in advance.

Develop a concept for glTF version handling

The jgltf-impl classes are currently auto-generated from the schema. Fortunately, the changes between glTF 1.0 and 1.1 are "backward compatible" in the sense that the generated classes can still be used to read a glTF asset with version 1.1 using the classes that had actually been generated for version 1.0.

But this might no longer be the case for future versions.

The question of how incompatible version changes are handled using the auto-generated classes (or whether auto-generation is still feasible at all in the future) has to be tackled.

This also refers to the version handling in the jgltf-validator, although it is still incomplete and in a very early state.

is extra field implemented in jgltf-model?

Hi, I need to use the 'extra' field in GlTFProperty.java but i don't see this field in GLTModel objects.

Could be the right way to access this field using private final GlTF gltf object inside GltfModel?

It seems that the binary format output by jgltf-browser 2.0 is incorrect

I tried saving glTF file in binary format using jgltf-browser 2.0.
The following is the procedure I tried.

  1. [Samples] - [Khronos Sample, v2.0] - [Duck] - [glTF (https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Duck/glTF/Duck.gltf)]
  2. [File] - [Save as binary...] - [Duck.glb]
  3. [File] - [Open file...] - [Duck.glb]

The following error is displayed.

Loading error: java.io.IOException: Could not load glTF asset
java.util.concurrent.ExecutionException: java.io.IOException: Could not load glTF asset
	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at javax.swing.SwingWorker.get(SwingWorker.java:602)
	at de.javagl.swing.tasks.SwingTask.get(SwingTask.java:435)
	at de.javagl.jgltf.browser.GltfLoadingWorker.done(GltfLoadingWorker.java:170)
	at de.javagl.swing.tasks.SwingTask.callDone(SwingTask.java:473)
	at de.javagl.swing.tasks.SwingTask.access$200(SwingTask.java:74)
	at de.javagl.swing.tasks.SwingTask$SwingTaskWorker.done(SwingTask.java:108)
	at javax.swing.SwingWorker$5.run(SwingWorker.java:737)
	at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(SwingWorker.java:832)
	at sun.swing.AccumulativeRunnable.run(AccumulativeRunnable.java:112)
	at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionPerformed(SwingWorker.java:842)
	at javax.swing.Timer.fireActionPerformed(Timer.java:313)
	at javax.swing.Timer$DoPostEvent.run(Timer.java:245)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
	at java.awt.EventQueue.access$500(EventQueue.java:97)
	at java.awt.EventQueue$3.run(EventQueue.java:709)
	at java.awt.EventQueue$3.run(EventQueue.java:703)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:109)
	at java.awt.WaitDispatchSupport$2.run(WaitDispatchSupport.java:184)
	at java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:229)
	at java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:227)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.awt.WaitDispatchSupport.enter(WaitDispatchSupport.java:227)
	at java.awt.Dialog.show(Dialog.java:1084)
	at java.awt.Component.show(Component.java:1671)
	at java.awt.Component.setVisible(Component.java:1623)
	at java.awt.Window.setVisible(Window.java:1014)
	at java.awt.Dialog.setVisible(Dialog.java:1005)
	at de.javagl.swing.tasks.DefaultSwingTaskView.show(DefaultSwingTaskView.java:70)
	at de.javagl.swing.tasks.SwingTaskExecutor.doExecute(SwingTaskExecutor.java:360)
	at de.javagl.swing.tasks.SwingTaskExecutor.execute(SwingTaskExecutor.java:318)
	at de.javagl.jgltf.browser.GltfLoadingWorker.load(GltfLoadingWorker.java:125)
	at de.javagl.jgltf.browser.GltfBrowserApplication.openUriInBackground(GltfBrowserApplication.java:559)
	at de.javagl.jgltf.browser.GltfBrowserApplication.openFile(GltfBrowserApplication.java:500)
	at de.javagl.jgltf.browser.GltfBrowserApplication.access$000(GltfBrowserApplication.java:76)
	at de.javagl.jgltf.browser.GltfBrowserApplication$1.actionPerformed(GltfBrowserApplication.java:106)
	at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
	at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
	at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
	at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
	at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
	at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:833)
	at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:877)
	at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289)
	at java.awt.Component.processMouseEvent(Component.java:6533)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
	at java.awt.Component.processEvent(Component.java:6298)
	at java.awt.Container.processEvent(Container.java:2236)
	at java.awt.Component.dispatchEventImpl(Component.java:4889)
	at java.awt.Container.dispatchEventImpl(Container.java:2294)
	at java.awt.Component.dispatchEvent(Component.java:4711)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
	at java.awt.Container.dispatchEventImpl(Container.java:2280)
	at java.awt.Window.dispatchEventImpl(Window.java:2746)
	at java.awt.Component.dispatchEvent(Component.java:4711)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
	at java.awt.EventQueue.access$500(EventQueue.java:97)
	at java.awt.EventQueue$3.run(EventQueue.java:709)
	at java.awt.EventQueue$3.run(EventQueue.java:703)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
	at java.awt.EventQueue$4.run(EventQueue.java:731)
	at java.awt.EventQueue$4.run(EventQueue.java:729)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Caused by: java.io.IOException: Could not load glTF asset
	at de.javagl.jgltf.browser.GltfAssetReaderThreaded.readGltfAsset(GltfAssetReaderThreaded.java:288)
	at de.javagl.jgltf.browser.GltfLoadingWorker.doInBackground(GltfLoadingWorker.java:162)
	at de.javagl.jgltf.browser.GltfLoadingWorker.doInBackground(GltfLoadingWorker.java:59)
	at de.javagl.swing.tasks.SwingTask.doTaskInBackground(SwingTask.java:335)
	at de.javagl.swing.tasks.SwingTask.access$000(SwingTask.java:74)
	at de.javagl.swing.tasks.SwingTask$SwingTaskWorker.doInBackground(SwingTask.java:84)
	at javax.swing.SwingWorker$1.call(SwingWorker.java:295)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at javax.swing.SwingWorker.run(SwingWorker.java:334)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

Submit a new release

Hello,

Thanks for this nice tool. I am trying to use it in a maven project but the last release is from 2 years ago and you added more work since then. Would it be possible to publish a new release please ?
I could import it by installing the jar but it gets more complicated when debugging the source code of my project using it ๐Ÿ˜„

Thanks

jgltf-browser is not support glTF Materials Common?

I tried to display the glTF Materials Common file using jgltf-browser preview release 5.

However, it was all displayed in gray. Is gltf-browser unsupported by glTF-MaterialsCommon?

glTF-MaterialsCommon/Duck.gltf
image

glTF-MaterialsCommon/Box.gltf
image

Reading a glTF file

Hi, i have written a glTF exporter for my custom model format using this library and it was really simple to do as the library did most of the work for me, for example writing the joints and weights just took about 25 lines total as all i had to do was create the 2 buffers, create an accessor model for each, add the 2 attributes(JOINTS_0 and WEIGHTS_0) and create a buffer view model which was extremely easy due to the 'helper' classes like BufferStructureBuilder

Now i am not sure about importing a glTF file and extracting data from it, are there any helper methods that make it simpler?
For example if i wanted to read the weights of a mesh primitive, this is what i do right now:

        GltfReaderV2 reader = new GltfReaderV2();
        GlTF gltf = reader.read(new ByteArrayInputStream(Files.readAllBytes(filePath)));
        Mesh mesh = gltf.getMeshes().get(0); // the gltf file only has 1 mesh
        MeshPrimitive primitive = mesh.getPrimitives().get(0); // the mesh only has 1 mesh primitive(for now)
        int weightsIndex = primitive.getAttributes().get("WEIGHTS_0");
        Accessor weightsAccessor = gltf.getAccessors().get(weightsIndex);
        BufferView weightsBufferView = gltf.getBufferViews().get(weightsAccessor.getBufferView());
        Buffer gltfBuffer = gltf.getBuffers().get(weightsBufferView.getBuffer());
        String base64 = gltfBuffer.getUri().substring(gltfBuffer.getUri().indexOf("base64") + "base64, ".length());
        byte[] bytes = Base64.getDecoder().decode(base64.getBytes(StandardCharsets.UTF_8));
        int byteOffset = weightsBufferView.getByteOffset();
        int byteLength = weightsBufferView.getByteLength();
        //TODO create float buffer and start reading weights

This isn't very tedious to do, but im still curious if there are perhaps simpler ways.
Any advice is appreciated.

Offer more control for the binary/embedded conversions

There is some sort of ambiguity in what exactly constitutes a "binary", "embedded" or "default" glTF model.

Technically, it is possible to create a binary glTF that 1. contains references to external files in its JSON part, and 2. contains resources embedded as data URIs in its JSON part. This may or may not be desired.

Right now, the GltfAsset structures are a "low-level"-representation of the assets, and as such, allow "mixed type assets". When writing a GltfAsset, it is written as-it-is, without doing any conversions. For example, when a GltfAsset that contains embedded resources (as data URIs) is written as a binary glTF, then the JSON part of the binary glTF will still contain the data URIs.

In contrast to that, the GltfModel classes serve as an abstraction layer that does no longer differentiate between these types. When a GltfModel is written, then all its resources are written in the desired format (default, embedded or binary).

Internally, the GltfModel is converted into a GltfAsset before it is written, and this GltfAsset will contain resources only in the desired target type. But there should be an API that allows a fine-grained control over the conversion. For example, such an API could/should offer options to convert resources into binary/embedded based on their type (i.e.: "Write all images as binary, but all buffers as embedded"), or to convert them individually (i.e.: "Write the first image as embedded, and the second as binary").

GlTF (v2) image data and GltfModel camera details (fov, aspect...)

Hi,

I am using Assimp with bindings provided by LWJGL to render a scene at the moment.
I want to switch to JglTF for model reading if i can manage.

I have a simple GLB file, exported from Blender, it has;

  • a camera
  • 2 lights
  • couple of boxes
  • a material
  • a texture with a small image

If i use de.javagl.jgltf.impl.v2.GlTF class;

  • I can get the camera details like fov, aspect, near, far.
  • But i cant get the image data that is embedded inside GLB file.
import de.javagl.jgltf.impl.v2.*;

public Test() throws Exception {
    FileInputStream fileInputStream = new FileInputStream("models/scene.glb");
    GltfAssetReader gltfAssetReader = new GltfAssetReader();
    GltfAsset gltfAsset = gltfAssetReader.readWithoutReferences(fileInputStream);
    GlTF gltf = (GlTF) gltfAsset.getGltf();

    for (Camera camera : gltf.getCameras()) {
        Float aspectRatio = camera.getPerspective().getAspectRatio();
        Float yfov = camera.getPerspective().getYfov();
        // i can get the camera details
    }
            
    for (Image image : gltf.getImages()) {
        Integer bufferViewIndex = image.getBufferView();
        BufferView bufferView = gltf.getBufferViews().get(bufferViewIndex);
        Integer bufferIndex = bufferView.getBuffer();
        Buffer buffer = gltf.getBuffers().get(bufferIndex);
        // cant reach the image data here
        // buffer.getImageData() ??
    }
}

If i use de.javagl.jgltf.model.GltfModel ;

  • I cant get the camera details.
  • But i can get the image data.
public Test() throws Exception {
    FileInputStream fileInputStream = new FileInputStream("models/scene.glb");
    GltfAssetReader gltfAssetReader = new GltfAssetReader();
    GltfAsset gltfAsset = gltfAssetReader.readWithoutReferences(fileInputStream);
    GltfModel gltfModel = GltfModels.create(gltfAsset);

    for (CameraModel cameraModel : gltfModel.getCameraModels()) {
        // cant get fov, aspect vs..
        // cameraModel.getPerspective() ??
    }

    for (ImageModel imageModel : gltfModel.getImageModels()) {
        ByteBuffer imageData = imageModel.getImageData();
        // i can get the image data
    }
}

Am i doing this wrong?
Or am i supposed to use both classes together?
Or is this not how this library supposed to be used?

Thanks for your hard work on this library, it is really neat.

Support multiple binary chunks

According to the specification, there may be multiple binary chunks in a binary glTF asset. The first one is supposed to be the main binary buffer data. Others are implementation-defined.

Right now, the classes like GltfAsset* usually store all the binary data as a single ByteBuffer binaryData. This has to be generalized to handle multiple chunks, like a List<ByteBuffer> binaryDataChunks.

Fix GL profile handling for JOGL

JOGL has an infrastructure for selecting the "GL profile" that should be used. This is built around the GLProfile class (see https://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/com/jogamp/opengl/GLProfile.html ).

Right now, the selection of the profile is done as follows in the GltfViewerJogl class:

    GLProfile profile = GLProfile.getMaxProgrammable(true);
    logger.config("GLProfile: " + profile);
    
    GLCapabilities capabilities = new GLCapabilities(profile);
    capabilities.setNumSamples(2);
    capabilities.setSampleBuffers(true);
    
    glComponent = new GLCanvas(capabilities);

So I'm using the highest programmable profile. This will usually be a GL3 or GL4 profile on modern PCs.

The crucial point is:

If the returned profile is only a core profile, and not a "backward compatibility" profile like GL3bc, then the attempt to compile a shader that does not contain any #version information may easily cause an error during the compilation.

This was the reason for opening KhronosGroup/glTF#587 , caused problems in #11 (comment) and has already been reported elsewhere.

I never had this problem on the PCs that I tested it with, but I'm rather limited to NVIDIA/Windows right now: It seems to be related to combinations of the graphics card, driver version and operating system, but I don't have more specific information here.

In any case, I have to find a solution for that.

When this problem was reported the first time, I made the helpless attempt to solve it by inserting the following:

    if (!vertexShaderCode.contains("#version"))
    {
        logger.warning(
            "Inserting GLSL version specifier in vertex shader code");
        vertexShaderCode = "#version 120\n" + vertexShaderCode;
    }

Of course, this looks like a crude hack, but it could solve the issue - at least until KhronosGroup/glTF#587 is addressed.

The less hacky but possibly more difficult option could be to select the GLProfile manually: I could obtain all available GLProfile values, and pick the highest one for which a ...bc (backward compatibility) version exists. But even then: What if there simply is no such profile? I'm afraid that the hack of inserting the #version will be necessary at least as a last resort...


Considering that the version number is still 0.0.0, and the releases are still "alpha" releases, I will insert this workaround for the next release, and hope that it resolves this issue.

Where are we on GlTF v 2.0?

I was checking the 2.0 branch, but It does not build.
There are impl-v1 and impl-v2, but model still refers to impl-v1.
Am I missing something?

jgltf-model tests do not pass

Cloning a fresh copy of this repo produces errors when running mvn compile package due to test failures in jgltf-model. The buffers of the generated models do not match the expected values, it seems. Replicated on two machines with completely different configurations.

I don't know enough about this code, yet, to know what is actually causing this.

Using Java 10 on one machine and Java 9 on another.

output.txt

Few simple features required

Hi, Thanks for a great framework. It will be great if the below features are provided.

  1. An utility method to export model's screenshot as an Image.
  2. An utility method to export model as a 360 degree image (panorama) centering a given 3D point.
  3. Ability to achieve the above two things in a server application (without using JFrame).

Thank you

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.