xml3d / xml3d.js

The WebGL/JS implementation of XML3D
Other
75 stars 25 forks source link

Dynamic XML3D objects initialization problem #148

Closed WitoldKosowski closed 8 years ago

WitoldKosowski commented 8 years ago

Hi, I'm having a problem with loading new xml3d objects dynamically. What I am trying to achieve is to use xml3d to visualize a 3d .stl file, which has been uploaded using ajax file upload. Once the file gets uploaded, the server returns a json response containing some html, which is inserted via jquery to a specific container. The document already contains all the necessary xml3d scripts, including xml3d.js, camera.js and the xml3d-stl-pligin.js.

After the html with the xml3d tag gets inserted to the container, the model does not get visualized. The app is an ASP.NET MVC web app, tested it on the current Chrome, Firefox, Opera and IE11 and the model is not getting visualized in any of them.

You can find a snippet below.

Main document's head part: (1)

<head>
<script src="http://xml3d.org/xml3d/scripts/xml3d.js" type="text/javascript"></script>
<script type="text/javascript" src="/Scripts/camera.js"></script>
<script type="text/javascript" src="/Scripts/xml3d-stl-plugin.js"></script>

... other head scripts and styles ...
</head>

Main document's body part: (2)

<div id="VisualizerContainer">
    <div class="row">
        <div class="col-lg-8">
            <div id="uploader-progress" class="visualizer-height" style="display:none">
                <p class="top-info">Your model is being prepared. Please wait...</p>
                <img src="loader.gif" alt="Please wait while your model is being prepared" />
            </div>
            <div id="classic-file-uploader" class="visualizer-height">
                @Html.Partial("_VisualizerFileUpload", Model)
            </div>
        </div>
    </div>
</div>

The after-upload html response part: (3)

<div id="xml3d-viewer" class="visualizer-height">
    <xml3d style="width:676px;height:378px" id="myxml3d">
        <shader id="phongShader" script="urn:xml3d:shader:phong">
            <float3 name="emissionColor" id="shaderemissionColor">1 1 1</float3>
            <float3 name="ambientColor" id="shaderambientColor">1 1 1</float3>
            <float3 name="specularColor" id="shaderspecularColor">1 1 1</float3>
            <float3 name="reflectionColor" id="shaderreflectionColor">1 1 1</float3>
            <float3 name="diffuseColor" id="shaderdiffuseColor">1 0.5 0</float3>
            <float name="shininess" id="shadershininess">0.5</float>
            <float name="ambientIntensity" id="shaderambientIntensity">0.5</float>
        </shader>

        <lightshader id="directionalLight" script="urn:xml3d:lightshader:directional">
            <float3 name="intensity" id="lightIntensity">1 0.5 0</float3>
            <float3 name="position" id="cameraPosition1">-100 -50 -458.801</float3>
            <float3 name="direction" id="cameraDirection1">0 20 -46.827</float3>
            <bool name="castShadow">false</bool>
        </lightshader>

        <light shader="#directionalLight"></light>

        <view position="0 0 200" id="myView"></view>
        <navigation revolvearound="0 0 0" id="myRotation"></navigation>
        <group shader="#phongShader" style="transform: translate3d(0px,-20px,0px)">
            <mesh id="xml3dmesh" src="uploaded/samplestlfile.stl" type="triangles"></mesh>
        </group>
    </xml3d>
</div>

A piece of javascript from the file uploader: (4)

$('#fileupload').fileupload({
        maxNumberOfFiles: 1,
        dataType: 'json',
        start: function (e, data) {
            //show file upload progress
        },
        done: function (e, data) {
            if (data.result.IsError) {
                //an error occurred, show error messages
            }
            else {
                $('#VisualizerContainer').html(data.result.ResponseView); 
// data.result.ResponseView contains the html part with the xml3d object (3)
                //some other javascript (hide overlays, etc)
            }
        },
        progress: function (e, data) {
            //manage progress bar
        },
        dropZone: $('.files-uploader .drop-zone')
    });
csvurt commented 8 years ago

Might have been a quick fix :)

I've just deployed it to the xml3d.js hosted at xml3d.org, could you test your application again and see if it works properly now?

WitoldKosowski commented 8 years ago

After the fix it does visualize the model so that's great.

However what is still not ok, is that the camera.js doesn't work. I can't rotate, zoom or pan the visualized model.

csvurt commented 8 years ago

I think you'll need to initialize the camera after the XML3D element has been initialized. I would use a framedrawn listener on the XML3D element after you insert it into the DOM:

$('#VisualizerContainer').html(data.result.ResponseView); 

$("#myxml3d").on("framedrawn", function() {
    var cam = new XML3D.Xml3dSceneController($("#myxml3d")[0]);
});
WitoldKosowski commented 8 years ago

Yes, that did the trick, although I had to use the load event instead of framedrawn, because the model got very crazy after I zoomed in/out or panned the view.

So I used:

$('#VisualizerContainer').html(data.result.ResponseView); 

$("#myxml3d").on("load", function () {
    var cam = new XML3D.Xml3dSceneController($("#myxml3d")[0]);
});

So this solved my problem completely and I think this issue can be closed. :)

csvurt commented 8 years ago

You're right the load event is a better choice, if you don't remove the framedrawn listener after the first frame it re-initializes the camera every frame :o

Thanks for the example code! I'm glad we could finally squash this bug.