vtkXMLPolyDataReader Texture Coordinates

(Donny Zimmerman) #1

I am reading a .vtp file using HttpDataAccessHelper and vtkXMLPolyDataReader, but the texture coordinates don’t appear to be in the polydata. I am able to open the .vtp and add the texture in Paraview so I know the texture coordinates are there. I have attached the .vtp and .bmp texture files. Here is my code:

function buildGlobeRenderer() {

let url = '**HIDDEN**/rendercontent/conus.vtp';

const progressCallback = (progressEvent) => {
    if (progressEvent.lengthComputable) {
        const percent = Math.floor(
            (100 * progressEvent.loaded) / progressEvent.total
        );
        //progressContainer.innerHTML = `Loading ${percent}%`;
    } else {
        /*progressContainer.innerHTML = macro.formatBytesToProperUnit(
            progressEvent.loaded
        );*/
    }
};

HttpDataAccessHelper.fetchBinary(url, {
    progressCallback,
}).then((binary) => {
    createGlobe(binary);
});

}

function createGlobe(fileContents) {

const vtpReader = vtkXMLPolyDataReader.newInstance();
vtpReader.parseAsArrayBuffer(fileContents);

const img = new Image();
img.onload = function textureLoaded() {
    const globeTexture = vtkTexture.newInstance();
    //globeTexture.setInterpolate(true);
    globeTexture.setImage(img);
    globeMapper.setInputConnection(vtpReader.getOutputPort());
    globeActor.setMapper(globeMapper);
    globeActor.addTexture(globeTexture);
    globeActor.getProperty().setLighting(false);

    globeRenderer.setLayer(0);
    globeRenderer.addActor(globeActor);         

    globeRenderer.resetCamera(); 

    renderWindow.render();
};
img.src = '**HIDDEN**/rendercontent/48USAcolshade-grey.bmp';

}48USAcolshade-grey.bmp (1.3 MB)
conus.vtp (387.5 KB)

(Sebastien Jourdain) #2

I believe the array get loaded but they are not detected or marked as texture coordinate. Please report a bug on vtk.js.

Thanks,

Seb

(Donny Zimmerman) #3

Done.

(Sebastien Jourdain) #4

Thanks!

(Donny Zimmerman) #5

Seb,
On another renderer where I am creating the texture coordinates manually I use the “polydata.getPointData.setTCoords” function successfully to set the texture coordinates. I did some digging into the XMLReader code and it looks like it is just setting the arrays, similar to “polydata.getPointData.addArray”. Not sure if setting the array will work or if setTCoords must explicitly be called to successfully add texture coordinates. Just a thought.

(Sebastien Jourdain) #6

That was my guess that we are just missing the handling of the custom arrays like Scalars/Normals/TCoords/Vectors…

In your code you should be able to call something like

const ds = reader.getOutputData();
const pd = ds.getPointData();
pd.setTCoords(pd.getArray(0));
(Donny Zimmerman) #7

Seb,
I tried your workaround, but it still doesn’t map the texture. Any ideas?
My code is below:

function createGlobe(fileContents) {

const vtpReader = vtkXMLPolyDataReader.newInstance();
vtpReader.parseAsArrayBuffer(fileContents);

const img = new Image();
img.onload = function textureLoaded() {
    const globeTexture = vtkTexture.newInstance();
    //globeTexture.setInterpolate(true);
    globeTexture.setImage(img);
    const ds = vtpReader.getOutputData();
    const pd = ds.getPointData();
    pd.setTCoords(pd.getArrayByName("TCoords_"));
    globeMapper.setInputData(ds);
    globeActor.setMapper(globeMapper);
    globeActor.addTexture(globeTexture);
    globeActor.getProperty().setLighting(false);

    globeRenderer.setLayer(0);
    globeRenderer.addActor(globeActor);

    let erm = 6356750.0;

    let sitelat = product.LatitudeOfRadar / 1000.0;
    let sitelon = product.LongitudeOfRadar / 1000.0;

    let radwp = computeGlobePoint(sitelon, sitelat, erm);

    renderCamera.setViewUp(radwp[0], radwp[1], radwp[2]);

    let positionVector = vec3.create();
    positionVector[0] = radwp[0];
    positionVector[1] = radwp[1];
    positionVector[2] = radwp[2];

    vtkMath.multiplyScalar(positionVector, 1.15);
    renderCamera.setPosition(positionVector[0], positionVector[1], positionVector[2] - 1000.0);

    renderCamera.setFocalPoint(radwp[0], radwp[1], radwp[2]);

    //globeRenderer.resetCamera(); 

    renderWindow.render();

    buildMapRenderer();
};
img.src = 'http://zmanvortex-001-site2.atempurl.com/rendercontent/48USAcolshade-grey.png';
//img.src = 'http://zmanvortex-001-site2.atempurl.com/rendercontent/opmap.png';

}

(Donny Zimmerman) #8

Seb,
After examining the UV data I discovered a lot of negative values. After setting the following in code the texture renders correctly.

globeTexture.setEdgeClamp(true);
globeTexture.setRepeat(true);

Thanks for the workaround!

(Sebastien Jourdain) #9

I’m glad it is working and thanks for sharing the final touch that make your code works.

(Donny Zimmerman) #10

After I thought about it, I realized that maybe the issue the whole time was with the texture setRepeat setting. I did not need the setEdgeClamp setting to make it render correctly. I removed the workaround from Seb and set the mapper directly to the vtkXMLPolyDataReader output and it works correctly. The only recommendation I have is that the default value for vtkTexture repeat property is set to true so it matches the way standard VTK and Paraview operate. Should I close the issue in github or leave it open with the above recommendation?

Thanks to Seb for helping me through this.

(Sebastien Jourdain) #11

Even better…

I guess you can submit a PR changing the default value of the texture flag to match the C++ implementation.

And I guess you can close the issue.