treblereel / three4g

Three.js for GWT
Apache License 2.0
25 stars 6 forks source link

GLTFLoader ClassCastException #158

Open tugalsan opened 4 years ago

tugalsan commented 4 years ago

Hello,

First, Thank you for the big work on creating three4g. If I can able to use 3D in web using java, It will open me a new playground to freely live in :P

I am reading from threejs documentations that i should focus on gltf loader, not others. For that reason...

I am trying to load a gltf file, for a month long. Whatever file i use, i am getting the same error. Is it possible that there is an error in library?

Console-With Error Message:

THREE.WebGLRenderer 102
PROGRESS.loadGLTF: true/4964/4964
ONLOAD.loadGLTF.o: [object Object]
app-0.js:216 ONLOAD.loadGLTF.o is not Object3D
app-0.js:216 ONLOAD.loadGLTF.mileStone1
app-0.js:216 ERROR.loadGLTF: Error: java.lang.ClassCastException

Simple Debug Function

    public static native void d(String text) /*-{
    console.log(text);
}-*/;

Simple GLTF loader function:

    public void loadGLTF(Scene scene, String url) {
        OnLoadCallback olc = new OnLoadCallback() {
            @Override
            public void onLoad(Object o) {
                d("ONLOAD.loadGLTF.o: " + o);
                if (!(o instanceof Object3D)) {
                    d("ONLOAD.loadGLTF.o is not Object3D");
                }
                d("ONLOAD.loadGLTF.mileStone1");
                Object3D o3d = (Object3D) o;
                d("ONLOAD.loadGLTF.mileStone2");
                Scene obj = o3d.getProperty("scene");
                d("ONLOAD.loadGLTF.mileStone3");
                scene.add(obj);
                d("ONLOAD.loadGLTF.mileStone4");
            }
        };
        OnProgressCallback opc = new OnProgressCallback() {
            @Override
            public void onProgress(OnProgressEvent ope) {
                d("PROGRESS.loadGLTF: " + ope.lengthComputable + "/" + ope.loaded + "/" + ope.total);
            }
        };
        OnErrorCallback oec = new OnErrorCallback() {
            @Override
            public void onError(PropertyHolder e) {
                d("ERROR.loadGLTF: " + e.toString());
            }
        };
        GLTFLoader loader = new GLTFLoader();
        loader.load(url, olc, opc, oec);
    }
    final public static String URL_GLTF_Box = "http://localhost:8080/three4g-demo-0.102/models/gltf/JME/box/box.gltf";
    final public static String URL_GLTF_Duck = "http://localhost:8080/three4g-demo-0.102/models/gltf/JME/duck/Duck.gltf";
    final public static String URL_GLTF_DamagedHelmet = "http://localhost:8080/three4g-demo-0.102/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf";
    final public static String URL_GLTF_Matilda = "http://localhost:8080/three4g-demo-0.102/models/gltf/matilda/scene.gltf";
    final public static String URL_GLB_Horse = "http://localhost:8080/3js/examples/models/gltf/Horse.glb";

pom-client

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.tugalsan</groupId>
        <artifactId>AutoSQLWeb</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>AutoSQLWeb-client</artifactId>
    <packaging>gwt-app</packaging>

    <dependencies>
        <dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>AutoSQLWeb-shared</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>AutoSQLWeb-shared</artifactId>
            <version>${project.version}</version>
            <classifier>sources</classifier>
        </dependency>
        <dependency>
            <groupId>com.google.gwt</groupId>
            <artifactId>gwt-user</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.gwt</groupId>
            <artifactId>gwt-dev</artifactId>
        </dependency>
        <!--  https://mvnrepository.com/artifact/com.google.code/gwt-visualization -->
        <dependency>
            <groupId>com.google.code</groupId>
            <artifactId>gwt-visualization</artifactId>
            <version>1.1.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.googlecode.gwt-charts/gwt-charts 
        <dependency>
            <groupId>com.googlecode.gwt-charts</groupId>
            <artifactId>gwt-charts</artifactId>
            <version>0.9.10</version>
        </dependency>-->

        <!-- https://mvnrepository.com/artifact/com.googlecode.gwtquery/gwtquery -->
        <dependency>
            <groupId>com.googlecode.gwtquery</groupId>
            <artifactId>gwtquery</artifactId>
            <version>1.5-beta1</version>
            <scope>provided</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.goharsha/webgl4j -->
        <dependency>
            <groupId>com.goharsha</groupId>
            <artifactId>webgl4j</artifactId>
            <version>0.2.9</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.joml/joml-gwt -->
        <dependency>
            <groupId>org.joml</groupId>
            <artifactId>joml-gwt</artifactId>
            <version>1.9.20</version>
        </dependency>

        <dependency>
            <groupId>org.treblereel.gwt</groupId>
            <artifactId>three4g</artifactId>
            <version>0.102</version>
        </dependency>
        <dependency>
            <groupId>org.treblereel.gwt</groupId>
            <artifactId>three4g-extensions</artifactId>
            <version>0.102</version>
        </dependency>
        <dependency>
            <groupId>org.treblereel</groupId>
            <artifactId>datgui4g</artifactId>
            <version>0.1-beta4</version>
        </dependency>
        <dependency>
            <groupId>com.google.elemental2</groupId>
            <artifactId>elemental2-dom</artifactId>
            <version>1.0.0-RC1</version><!-- 1.0.0-RC1 vrda sorun çıkarıyor -->
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>net.ltgt.gwt.maven</groupId>
                <artifactId>gwt-maven-plugin</artifactId>
                <configuration>
                    <moduleName>com.tugalsan.autosqlweb.App</moduleName>
                    <moduleShortName>app</moduleShortName>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

pom-main

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tugalsan</groupId>
    <artifactId>AutoSQLWeb</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <repositories>
        <repository>
            <id>java.net</id>
            <url>https://maven.java.net/content/repositories/public/</url>
        </repository>
        <repository>
            <id>google-api-services</id>
            <url>http://google-api-client-libraries.appspot.com/mavenrepo</url>
        </repository>
        <repository>
            <id>redhat-ga-repository</id>
            <url>https://maven.repository.redhat.com/ga/</url>
        </repository>
    </repositories>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.google.gwt</groupId>
                <artifactId>gwt</artifactId>
                <version>2.9.0</version><!--2.8.2-->
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>4.0.1</version><!--3.1.0-->
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <finalName>AutoSQLWeb</finalName>
        <plugins>
            <plugin>
                <groupId>net.ltgt.gwt.maven</groupId>
                <artifactId>gwt-maven-plugin</artifactId>
                <inherited>false</inherited>
                <configuration>
                    <launcherDir>${project.build.directory}/gwt/launcherDir</launcherDir>
                    <style>PRETTY</style>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version><!--2.3.2-->
                <configuration>
                    <showDeprecation>true</showDeprecation>
                    <source>1.8</source>
                    <target>1.8</target>
                    <draftCompile>true</draftCompile>
                </configuration>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version><!-- Do not upgrade past 3.1 to avoid triggering https://issues.apache.org/jira/browse/MSOURCES-95 -->
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.eclipse.jetty</groupId>
                    <artifactId>jetty-maven-plugin</artifactId>
                    <version>9.4.12.v20180830</version><!--9.4.12.RC0-->
                    <configuration>
                        <skip>true</skip>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>net.ltgt.gwt.maven</groupId>
                    <artifactId>gwt-maven-plugin</artifactId>
                    <version>1.0-rc-10</version><!--1.0-rc-9-->
                    <extensions>true</extensions>
                    <configuration>
                        <sourceLevel>1.8</sourceLevel>
                        <failOnError>true</failOnError>
                        <draftCompile>true</draftCompile>
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-source-plugin</artifactId>
                    <version>3.0.1</version><!--3.0.1-->
                    <executions>
                        <execution>
                            <id>attach-sources</id>
                            <phase>package</phase>
                            <goals>
                                <goal>jar-no-fork</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.apache.tomcat.maven</groupId>
                    <artifactId>tomcat7-maven-plugin</artifactId>
                    <version>2.2</version><!--tomcat7 2.2 is buggy!!! use 2.1 if necessary-->
                    <configuration>
                        <packagingExcludes>WEB-INF/web.xml</packagingExcludes>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
    <modules>
        <module>AutoSQLWeb-client</module>
        <module>AutoSQLWeb-shared</module>
        <module>AutoSQLWeb-server</module>
    </modules>
</project>
treblereel commented 4 years ago

@tugalsan i ll take a look next week. you can speedup my work by adding a link to the reproducer Thanks for your feedback.

tugalsan commented 4 years ago

Please reproduce the error with this, when you have free time. AutoSQLWeb.zip

treblereel commented 4 years ago

@tugalsan i am sorry, but i can't run your demo, because of missed deps. Which model are you trying to load ? As i can see you are trying to cast Object to Object3D, but object isn't Object3D (app-0.js:216 ONLOAD.loadGLTF.o is not Object3D)

take a look at https://env-7073819.cloud.unispace.io/#WebglLoaderGltf

please proved me some details

treblereel commented 4 years ago

hmm, i am working on update to 103 and looks like i can reproduce this issue ...

treblereel commented 4 years ago

@tugalsan could you try something like :

        loader.load("models/gltf/LittlestTokyo.glb", object -> {
          Scene scene = Js.uncheckedCast(Js.asPropertyMap(object).get("scene"));

          DomGlobal.console.log("isScene " + scene.isScene);
        });
tugalsan commented 4 years ago

I will do it today... and report back to you

tugalsan commented 4 years ago

@tugalsan could you try something like :

        loader.load("models/gltf/LittlestTokyo.glb", object -> {
          Scene scene = Js.uncheckedCast(Js.asPropertyMap(object).get("scene"));

          DomGlobal.console.log("isScene " + scene.isScene);
        });

@treblereel treblereel Thanks for the fix. I can now load gltf files. Here is the code update AutoSQLWeb.zip

treblereel commented 4 years ago

take a look at updated demos : https://env-7073819.cloud.unispace.io/#WebglLoaderDraco

tugalsan commented 4 years ago

@treblereel. It is true. I mixed up examples to use DracoLoader to load drc files and using DracoLoader to load gltf files.

By looking the example code:

https://github.com/treblereel/three4g-demo/blob/master/src/main/java/org/treblereel/gwt/three4g/demo/client/local/examples/animation/WebglAnimationScene.java

Here is the working source code to load LittlestTokyo.glb with DracoLoader addon.

package com.tugalsan.autosqlweb.client.lang.gl.threeJS;
import jsinterop.base.Js;
import org.treblereel.gwt.three4g.core.PropertyHolder;
import org.treblereel.gwt.three4g.extensions.loaders.DRACOLoader;
import org.treblereel.gwt.three4g.extensions.loaders.DRACOLoaderDecoderConfig;
import org.treblereel.gwt.three4g.extensions.loaders.GLTFLoader;
import org.treblereel.gwt.three4g.extensions.resources.TK_3JSResourceUtils;
import org.treblereel.gwt.three4g.geometries.BoxBufferGeometry;
import org.treblereel.gwt.three4g.helpers.GridHelper;
import org.treblereel.gwt.three4g.loaders.CubeTextureLoader;
import org.treblereel.gwt.three4g.loaders.OnErrorCallback;
import org.treblereel.gwt.three4g.loaders.OnLoadCallback;
import org.treblereel.gwt.three4g.loaders.OnProgressCallback;
import org.treblereel.gwt.three4g.loaders.OnProgressEvent;
import org.treblereel.gwt.three4g.loaders.TextureLoader;
import org.treblereel.gwt.three4g.materials.MeshBasicMaterial;
import org.treblereel.gwt.three4g.math.Color;
import org.treblereel.gwt.three4g.objects.Mesh;
import org.treblereel.gwt.three4g.scenes.Scene;
import org.treblereel.gwt.three4g.textures.CubeTexture;

public class TK_3JSModel {//MODEL LOADERS

    public TK_3JSModel(TK_3JSProgramAbstract program) {

        TK_3JSResourceUtils.addLib(TK_3JSResourceUtils.IMPL.getGLTFLoader());
        {
            TK_3JSResourceUtils.addLib(TK_3JSResourceUtils.IMPL.getDRACOLoader());
            DRACOLoaderDecoderConfig dlc = new DRACOLoaderDecoderConfig();
            dlc.type = "js";
            DRACOLoader.setDecoderConfig(dlc);
        }
    }

    public void d(String s) {
        DomGlobal.console.log(text);
    }

    public void loadGLTF(Scene scene, String url, boolean isLoaderDraco) {
        d("ONLOAD.loadGLTF.url: [" + url + "]");
        OnLoadCallback olc = new OnLoadCallback() {
            @Override
            public void onLoad(Object o) {
                d("ONLOAD.loadGLTF.onLoad.start.url: [" + url + "]");
                Scene sceneGLTF = Js.uncheckedCast(Js.asPropertyMap(o).get("scene"));
                d("isScene " + sceneGLTF.isScene);
                scene.add(sceneGLTF);
                d("ONLOAD.loadGLTF.onLoad.end.url: [" + url + "]");
            }
        };
        OnProgressCallback opc = new OnProgressCallback() {
            @Override
            public void onProgress(OnProgressEvent ope) {
                d("PROGRESS.loadGLTF: " + ope.lengthComputable + "/" + ope.loaded + "/" + ope.total);
            }
        };
        OnErrorCallback oec = new OnErrorCallback() {
            @Override
            public void onError(PropertyHolder e) {
                d("ERROR.loadGLTF: " + e.toString());
            }
        };
        GLTFLoader loader = new GLTFLoader();
        if (isLoaderDraco) {
            DRACOLoader.setDecoderPath("js/libs/draco/gltf/");
            DRACOLoader dl = new DRACOLoader();
            loader.setDRACOLoader(dl);
        }
        loader.load(url, olc, opc, oec);
    }
    final public static String URL_GLTF_LittlestTokyo = "http://localhost:8080/AutoSQLWeb/models/gltf/Three4G/LittlestTokyo.glb";
    final public static String URL_GLTF_Flamingo = "http://localhost:8080/AutoSQLWeb/models/gltf/Three4G/Flamingo.glb";
    final public static String URL_GLTF_Horse = "http://localhost:8080/AutoSQLWeb/models/gltf/Three4G/Horse.glb";
}

(sorry, for some reason I cannot upload the updated project again)

tugalsan commented 4 years ago

To summarize, not to get ClassCastException, until it is fixed, one has to implement a "FIX_ON_LOAD_Object3D".

1) if one wanna set material.envMap, one should fix it like below (this happened when loading https://sketchfab.com/3d-models/matilda-7ddedfb652bd4ea091bc3de27f98fc02):

TK_3JSModel->lazyload()->TraverseCallback tcb_envMap = new TraverseCallback()
                    if (FIX_ON_LOAD_Object3D) {
                        Object oMaterial = Js.asPropertyMap(o3d).get("material");
                        MeshStandardMaterial material = Js.uncheckedCast(oMaterial);
                    } else {
                        MeshStandardMaterial material = o3d.getProperty("material");
                    }

2) if one wanna get Object3D.scene, one should fix it like below (this happens all the time):

TK_3JSModel->lazyload()->OnLoadCallback olc = new OnLoadCallback() 
                Object oScene;
                if (o instanceof Object3D) {
                    Object3D o3d = (Object3D) o;
                    oScene = o3d.getProperty("scene");
                } else if (FIX_ON_LOAD_Object3D) {
                    oScene = Js.asPropertyMap(o).get("scene");
                }
                Scene sniffedScene = Js.uncheckedCast(oScene);

3) if one wanna get Object3D.animations, one should fix it like below (this happens when loading LittlestTokyo.glb):

TK_3JSModel->lazyload()->OnLoadCallback olc = new OnLoadCallback() 
                    if (o instanceof Object3D) {
                        Object3D o3d = (Object3D) o;
                        AnimationClip[] animationClips = o3d.getProperty("animations");
                    } else if (FIX_ON_LOAD_Object3D) {
                        Object oAnimations = Js.asPropertyMap(o).get("animations");
                        AnimationClip[] animationClips = Js.uncheckedCast(oAnimations);
                    }

Here is an example code: (Updated, now animations play with same speed) threeJS (20200711) r3.zip image

treblereel commented 4 years ago

@tugalsan thanks! but the way, whick gwt version are you using and are you going to switch to j2cl ? (which is awesome)

tugalsan commented 4 years ago

@treblereel my gwt version is 2.9.0.

I would love to switch to j2cl. But two steps I have to deal with....

1) Elemental2: It took me litterlly one month to understand how to use elemental2 dom in your demo project. Even once I gave up three4g, and then return back, because there is actually no other rival to this library that I know of. Some how, I did able to combine my gwt project and elemental2 dom side by side.

2) I do not have any experience coding j2cl. I need to study it first. How I wish there is an migration tutorial for it... Actually I should search for it... Or should I wait for GWT3, which will force me to use j2cl anyway....

treblereel commented 4 years ago

@tugalsan i have ported gwt-widgets to j2cl so you can use elemental2 and widgets. there is j2cl-maven-plugin which allow you to compile and run your existing gwt2 code using j2cl and closure compiler, so you can try it. We have a great community at gitter, so you can join it and discuss any topics like j2cl, elemental2 and so on

tugalsan commented 4 years ago

I would love to. I had a dream, to code a simple 3d world editor by my self. Now that I learned clonning things, threeJS looks so juicy.

Are you sure people wanna help me (?). As I cannot even compile the pure "gwt-resources-master" project, I feel so stupid. Issue