mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
102.01k stars 35.33k forks source link

JSON Loader callback is fired before textures are mapped to model #11114

Closed mahmoudsoliman closed 5 years ago

mahmoudsoliman commented 7 years ago

i am using JSONLoader to load 3d models to my scene .. then i stop the rendering loop to avoid cpu overhead while the scene is stand still,

the problem is when i stop the rendering loop the textures are not loaded yet so the model appear without texture,

i viewd some previous simillar issues and it led me to use LoadingManager with json loader and i stop the rendering loop in the LoadingManager callback not the JSONLoader but nothing changes

Three.js version r84

the problem happens with all browsers

i am using windows 7

code sample is attached with a screenshot

screenshot1

issue.txt

Usnul commented 7 years ago

I don't know about you, but I see it as a plus rather than a minus. You can always hook texture load status, or pre-load them. What you are reporting is a feature request and not a "problem".

mahmoudsoliman commented 7 years ago

@Usnul i used the solution in #10287 and it works now when i used JSONLoader.parse instead of JSONLoader.load , i think what we need is a similar callback in JSONLoader.load

mrdoob commented 7 years ago

How come you're using JSONLoader? (Instead of ObjectLoader)

mahmoudsoliman commented 7 years ago

@mrdoob i tried to use ObjectLoader at first but it didn't work with me producing this error : THREE.ObjectLoader: Can't load ../../robot.js. Use THREE.JSONLoader instead. so i used JSONLoader , and that is what is used in most of the tutorials i have seen.

jostschmithals commented 7 years ago

Do you know resp. did you try, which of the three conditions in ObjectLoader (https://github.com/mrdoob/three.js/blob/master/src/loaders/ObjectLoader.js#L95-#L102) causes this error?

looeee commented 7 years ago

How come you're using JSONLoader? (Instead of ObjectLoader)

@mrdoob I think the documentation is currently very unclear as to why these both exist and when to use each. It's something I intended to update when I was going over the docs, however I'm not sure myself the difference between these.

Currently the only thing the docs say about the difference, rather cryptically, is

Unlike the JSONLoader, this one (ObjectLoader) make use of the .type attributes of objects to map them to their original classes.

mahmoudsoliman commented 7 years ago

@jostschmithals i traced the error and i found that metadata.type is undefined however, this is the metadata of my object as exported from 3dmax via threejs exporter : "metadata": { "sourceFile": "robot.max", "generatedBy": "3ds max ThreeJSExporter", "formatVersion": 3.1, "vertices": 2524, "normals": 4598, "colors": 0, "uvs": 3418, "triangles": 4598, "materials": 1 },

jostschmithals commented 7 years ago

@looeee I agree and had already similar thoughts; but there is one additional hint in the line after the one you quoted:

Note that this loader can't load Geometries. Use JSONLoader instead for that.

jostschmithals commented 7 years ago

@mahmoudsoliman For comparison:

In this example a mesh is loaded with the ObjectLoader. (There are some bugs in this demo, but loading works fine). In this demo you can see that the model file contains two different metadata objects:

"metadata":{
    "sourceFile":"marine_anims_core.blend",
    "generator":"io_three",
    "type":"Object",
    "version":4.4
}
"metadata":{
    "uvs":1,
    "version":3,
    "faces":5704,
    "generator":"io_three",
    "normals":5736,
    "bones":57,
    "vertices":5736
}
mahmoudsoliman commented 7 years ago

@jostschmithals and is that a problem with my model or with the 3dmax exporter? and is there a problem if i continued using JSONLoader the way i mentioned above?

jostschmithals commented 7 years ago

Sorry - I can’t answer your questions directly (I am new to three.js and just learning all these things). I only wanted to give some hints for further considerations.

yomotsu commented 7 years ago

I prefer to use JSONLoader too. Its more flexible for me.

@mahmoudsoliman As you know, load callback is only for JSON. But you can also detect texture loaded see: https://github.com/mrdoob/three.js/pull/10829 (still only in dev tho)

Plus, packing all assets in one zip file might be also helpful for you https://yomotsu.github.io/ZipLoader/examples/Alicia.html

jostschmithals commented 7 years ago

@looeee wrote (concerning JSONLoader/ObjectLoader):

@mrdoob I think the documentation is currently very unclear as to why these both exist and when to use each. It's something I intended to update when I was going over the docs, however I'm not sure myself the difference between these.

@looeee In the meantime I have been digging in the source code because I wanted to understand completely how the different loaders/parsers (Objectloader, JSONLoader, BufferGeometryLoader, MaterialLoader, Loader, TextureLoader, ImageLoader, FileLoader) work together, and currently I am preparing an extra page for the docs explaining it (after I realized that several statements in the docs are rather misleading).

Here only a “short” version:

Below is a JSON structure - containing nested Object3D structures - that can be parsed by ObjectLoader (which uses JSONLoader and all the other loaders internally. - Note: a materials property nested in geometries - data is parsed by JSONLoader, but ignored by ObjectLoader).

JSONLoader can only load/parse a single (non buffered) geometry with associated materials - like the part in the middle of the graph, between the === lines (using FileLoader, Loader, MaterialLoader, TextureLoader and ImageLoader).

In this graph there should be all currently supported properties, which of course doesn’t mean that they always have to occur all together in the same JSON file. 😉

{
    ▼ metadata: {
        type
    },
    ▼ object: {
        children: [
            {
                uuid,
                type,
                geometry (uuid),
                material (uuid),
                ....,
                children: [
                    {
                        uuid,
                        type,
                        geometry (uuid),
                        material (uuid),
                        ....
                        children: [
                            {
                            ...
                            }
                        ]
                    }
                ]
            }
        ],
        uuid,
        type,
        geometry (uuid),
        material (uuid),
        matrix,
        position,
        rotation,
        quaternion,
        scale,
        visible,
        castShadow,
        receiveShadow,
        userData,
        background,
        fog: {
            type,
            color,
            near,
            far,
            density
        },
        fov,
        aspect,
        near,
        far,
        focus,
        zoom,
        filmGauge,
        filmOffset,
        view,
        left,
        right,
        top,
        bottom,
        color,
        intensity,
        distance,
        decay,
        width,
        height,
        angle,
        penumbra,
        groundColor,
        shadow: {
            bias,
            radius,
            mapSize,
            camera
        },
        mode
        levels
    },
    ▼ geometries: [
        {
            uuid,
            type,
            data: {
                name,
                index: {
                    type,
                    array
                },
                attributes: {
                    ...: {
                        type,
                        array,
                        itemSize,
                        normalized
                    },
                    ...
                },
                groups: [
                    {
                        start,
                        count,
                        materialIndex
                    },
                    ...
                ],
                boundingSphere: {
                    center,
                    radius
                },
=============================================================================
                metadata: {
                    type
                }
                materials: [
                    {
                        DbgName,
                        blending,
                        colorDiffuse,
                        colorSpecular,
                        colorEmissive,
                        specularCoef,
                        shading,
                        flipSided,
                        doubleSided,
                        transparency,
                        depthTest,
                        depthWrite,
                        colorWrite,
                        opacity,
                        reflectivity,
                        transparent,
                        visible,
                        wireframe,
                        vertexColors,
                        mapDiffuse, (path)
                        mapDiffuseRepeat,
                        mapDiffuseOffset,
                        mapDiffuseWrap,
                        mapDiffuseAnisotropy,
                        mapEmissive, (path)
                        mapEmissiveRepeat,
                        mapEmissiveOffset,
                        mapEmissiveWrap,
                        mapEmissiveAnisotropy,
                        mapLight, (path)
                        mapLightRepeat,
                        mapLightOffset,
                        mapLightWrap,
                        mapLightAnisotropy,
                        mapAO, (path)
                        mapAORepeat,
                        mapAOOffset,
                        mapAOWrap,
                        mapAOAnisotropy,
                        mapBump, (path)
                        mapBumpScale,
                        mapBumpRepeat,
                        mapBumpOffset,
                        mapBumpWrap,
                        mapBumpAnisotropy,
                        mapNormal, (path)
                        mapNormalFactor,
                        mapNormalRepeat,
                        mapNormalOffset,
                        mapNormalWrap,
                        mapNormalAnisotropy,
                        mapSpecular, (path)
                        mapSpecularRepeat,
                        mapSpecularOffset,
                        mapSpecularWrap,
                        mapSpecularAnisotropy,
                        mapMetalness, (path)
                        mapMetalnessRepeat,
                        mapMetalnessOffset,
                        mapMetalnessWrap,
                        mapMetalnessAnisotropy,
                        mapRoughness, (path)
                        mapRoughnessRepeat,
                        mapRoughnessOffset,
                        mapRoughnessWrap,
                        mapRoughnessAnisotropy,
                        mapAlpha, (path)
                        mapAlphaRepeat,
                        mapAlphaOffset,
                        mapAlphaWrap,
                        mapAlphaAnisotropy
                    },
                    ...
                ],
                scale,
                vertices,
                colors,
                uvs: [
                    [...],
                ...
                ],
                normals,
                faces,
                skinWeights,
                skinIndices,
                influencesPerVertex,
                bones: [
                    {
                        name,
                        parent,
                        pos,
                        scl,
                        rotq,
                    },
                    ...
                ],
                animation: {
                    name,
                    length,
                    fps,
                    hierarchy: {
                        parent,
                        keys: {
                            time,
                            pos,
                            scl,
                            rot
                        },
                    },
                },
                animations: [
                    {
                        name,
                        length,
                        fps,
                        hierarchy: {
                            parent,
                            keys: {
                                time,
                                pos,
                                scl,
                                rot
                            },
                        },
                    },
                    ...
                ],
                morphTargets: [
                    {
                        name,
                        vertices
                    },
                    ...
                ],
=============================================================================
            },
            width,
            height,
            widthSegments,
            heightSegments,
            depth,
            depthSegments,
            radius,
            segments,
            thetaStart,
            thetaLength,
            radiusTop,
            radiusBottom,
            radialSegments,
            openEnded,
            phiStart,
            phiLength,
            detail,
            innerRadius,
            outerRadius,
            phiSegments,
            tube,
            tubularSegments,
            p,
            q,
            points
        },
        ...,
    ],
    ▼ materials: [
        {
            type,
            uuid,
            name,
            color,
            roughness,
            metalness,
            emissive,
            specular,
            shininess,
            clearCoat,
            clearCoatRoughness,
            uniforms,
            vertexShader,
            fragmentShader,
            vertexColors,
            fog,
            shading,
            blending,
            side,
            opacity,
            transparent,
            alphaTest,
            depthTest,
            depthWrite,
            colorWrite,
            wireframe,
            wireframeLinewidth,
            wireframeLinecap,
            wireframeLinejoin,
            skinning,
            morphTargets,
            size,
            sizeAttenuation,
            map (uuid),
            alphaMap (uuid),
            bumpMap (uuid),
            bumpScale,
            normalMap (uuid),
            normalScale,
            displacementMap (uuid),
            displacementScale,
            displacementBias,
            roughnessMap (uuid),
            metalnessMap (uuid),
            emissiveMap (uuid),
            emissiveIntensity,
            specularMap (uuid),
            envMap (uuid),
            reflectivity,
            lightMap (uuid),
            lightMapIntensity,
            aoMap (uuid),
            aoMapIntensity,
            gradientMap (uuid)
        },
        ...,
    ],
    ▼ textures: [
        {
            uuid,
            image (uuid),
            name,
            repeat,
            offset,
            wrap,
            anisotropy,
            mapping,
            minFilter,
            magFilter,
            flipY
        },
        ...,
    ],
    ▼ images: [
        {
            uuid,
            name,
            url
        },
        ...,
    ],
    ▼ animations: [
        {
            name,
            tracks,
            fps
        },
        ...,
    ]

}
mrdoob commented 7 years ago

@mrdoob I think the documentation is currently very unclear as to why these both exist and when to use each. It's something I intended to update when I was going over the docs, however I'm not sure myself the difference between these.

JSONLoader was the first format/loader we did. Basically this spec:

https://github.com/mrdoob/three.js/wiki/JSON-Model-format-3

Calling it JSONLoader was definitely a bad decision, GeometryLoader would have been more appropriate, as that what it produced. Then we started adding material properties and became a sort of MeshLoader.

I've been trying to deprecate it for a while but the new loaders lacked features. I think one missing piece was MultiMaterial. JSONLoader was able to handle MultiMaterial better than ObjectLoader. This is something that has been solved in this dev cycle #10931

Mugen87 commented 5 years ago

Closing. JSONLoader has been removed from core, see #15310.