Help loading CSV

I’m newer to using javascript. I’m trying to load a .csv file like this:

        var positionData;
        var fileName = "models/test.csv";
        BABYLON.Tools.LoadFile(fileName, (data) => {
            positionData = data;
            console.log(data)
        });
       console.log(positionData);

data prints as it should but positionData is undefined. Why is this? How can I prevent it?

I’m trying to use Papa.parse(data) as well but it only prints ‘output’ to my console. Any help is appreciated.

Hi @Strix and welcome to the forum. You are printing positionData before the data has loaded.

BABYLON.Tools.LoadFile(fileName, (data) => {
        // Everying in this block happens after the data has loaded.
        // Any code that needs executing after the data has loaded needs to be in this block.
        // While this block is loading code outside the block is still executed.
});
console.log(positionData); //This code is executed while and therefore before the data has loaded and so it is undefined

Hi @JohnK that makes (some) sense. (This is probably more basic javascript than Babylon so I do appreciate the help).

I’d like to be able to load and render various images via a slider bar- I have this working. But how do I call
BABYLON.Tools.LoadFile from my sliderbar to get it to load?

Right now I instantiate and control the sideBar like this:

    var rotateGroup = new BABYLON.GUI.SliderGroup("Phase Viewer", "S");
    rotateGroup.addSlider("cardiac phases", orientateY, "%", 0, 19, 10, displayValue)

Then here I determine what to render:

    var orientateY = function (value) {
        var fileName = "models/test.csv";
        var positionData;
        BABYLON.Tools.LoadFile(fileName, (data) => {
        ///Bunch of irrelevant code...
          

          });
     };

This works but is ugly! Is there a better way where I can pass in the data or reference it with a pointer or something?

Thanks!
~Shane

BABYLON.Tools.LoadFile is an asynchronous function. The onSuccess callback will only be called after the url has been loaded. Doing this in the addSlider callback is probably not what you want to do, since that will try to load the url every time the slider moves. What you probably should do is call LoadFile early (maybe during page load) and save the data somewhere so that you can use it for your slider.

Thanks for getting back to me I’ll try this.

I have about 60 files (20 models consisting of a file for points,vertices and color). Each are about <= 4Mb. If I load all these files initially will there be any other performance related issues?

Thanks again,
~Shane

Since they are CSVs, I’m guessing they zip very well so the transfer size should be significantly smaller. In terms of performance, if you download the files asynchronously, it should not affect your rendering (assuming you are rendering something when loading). You can also continue to do other work in the foreground while the download is going. If you can explain your scenario, there may be other things you can do to avoid the perception of a long download.

As @bghgary suggests if it is at all possible to pre-load your files this is the best way to do it.

Using flags it is possible to do it for each change of the slider and not load the file for every change. The following PG shows a (less than perfect) structure for doing this using meshes rather than csv files but the methodology would be basically the same. You can see the breaks that occur when the file is first loaded. Pre-loading would avoid these.

https://www.babylonjs-playground.com/#BXMTCD#15

Thanks for your help. For completeness here’s what I ended up doing:

assetsManager.onFinish = function (tasks) {
start();
};

        var LoadEntity = function(url, positionFile, indicesFile, faceFile, colorFile, manager, meshArray, indicesArray, faceArray, colorArray, entity_number, props) {
            fileIndicesName = url + indicesFile;
            var textIndicesTask = manager.addTextFileTask("textIndicestask", fileIndicesName);
            textIndicesTask.onSuccess = function (task) {
                indicesArray[entity_number] = task.text.split(',');
            }

            fileColorName = url + colorFile;
            var textColorTask = manager.addTextFileTask("textColorTask", fileColorName);
            textColorTask.onSuccess = function (task) {
                colorArray[entity_number] = task.text.split(',');
            }

            filePositionName = url + positionFile;
            var textPositionsTask = manager.addTextFileTask("textPositionTask", filePositionName);
            textPositionsTask.onSuccess = function (task) {
                meshArray[entity_number] = task.text.split(',');
            }

            fileFaceName = url + faceFile;
            var textFaceTask = manager.addTextFileTask("textFaceTask", fileFaceName);
            textFaceTask.onSuccess = function (task) {
                faceArray[entity_number] = task.text.split(',');
            }

        }                

        var start = function () {                
            //BABYLON.VertexData.ComputeNormals(positionArray[0], indicesArray[0], normals);
            vertexData.positions = positionArray[0];
            vertexData.indices = indicesArray[0];
            vertexData.colors = colorArray[0]; //Assignment of colors to vertexData
            vertexData.normals = faceArray[0]; //Assignment of normal to vertexData added
            vertexData.applyToMesh(customMesh);

            console.log(vertexData.positions[0]);
            console.log(vertexData.indices[0]);
            console.log(vertexData.colors[0] );
            console.log(vertexData.normals[0]);
        };

I think this will work but not for what I’m trying to do. I need to color each face of my mesh and this isn’t rendering the mesh correctly. I have a .stl of the same mesh I need to render. I think I’m going to try to color the faces of this mesh instead of building it.

1 Like