davidfig / pixi-cull

a library to visibly cull objects designed to work with pixi.js
MIT License
109 stars 15 forks source link

TypeError: Cannot read property 'x' of undefined #7

Closed zhouccccc closed 4 years ago

zhouccccc commented 4 years ago

Version: pixi-cull: 0.6.0 pixi-viewport: 4.9.2 pixi.js: 5.2.1

Code

const cull = new Cull.Simple({ calculatePIXI: true });
cull.addList(viewport.children);
cull.cull(viewport.getVisibleBounds());

Error Stack

TypeError: Cannot read property 'x' of undefined
    at Simple.cull (simple.js?081c:154)
    at callRender (pixi-initialization.js?e625:78)
    at centerView (pixi-initialization.js?e625:128)
    at eval (Simulator.vue?96ba:972)
    at eval (service.js?67cf:86)
davidfig commented 4 years ago

What's inside your viewport.children?

zhouccccc commented 4 years ago

It's the empty Array because it's in the initialization phase. I created function for init PIXI render:

export const initPixiRender = () => {
  document.getElementById("map").appendChild(SimulatorPIXI.view);
  SimulatorPIXI.stage.addChild(viewport);
  viewport
    .drag()
    .pinch()
    .wheel()
    .decelerate();
};
// Used in Vue mounted function

I'm not sure if the problem caused by the way I used happened.

davidfig commented 4 years ago

Weird. Hmm...if the viewport.children is empty then it should skip the array until it has children. Can you debug and see what line it's crashing on in simple.js, and what object it's trying to read.

zhouccccc commented 4 years ago

image This line crashed.

image Cannot find 'AABB' in this object so the box is undefined

davidfig commented 4 years ago

Thanks for the info, but I'm not sure why it's looping at all if there are no objects in viewport.children. Here's the code:

    cull(bounds, skipUpdate)
    {
        if (this.calculatePIXI && !skipUpdate)
        {
            this.updateObjects()
        }
        for (let list of this.lists)
        {
            for (let object of list)
            {
                const box = object[this.AABB]
                object[this.visible] =
                    box.x + box.width > bounds.x && box.x < bounds.x + bounds.width &&
                    box.y + box.height > bounds.y && box.y < bounds.y + bounds.height
            }
        }
    }

It should never step past the for (let object list) line because the list is empty. Can you check what object is and where it comes from?

zhouccccc commented 4 years ago

Sorry, something wrong per my previous description. It will not step past the for (let object list) line. I set two breakpoints at source code. image

When I refresh the browser, the console will log: image

Here object is my custom entity, but there is no 'AABB' prop in it

davidfig commented 4 years ago

Oops. Try settings options.dirtyTest = false when you instantiate the Cull. That should fix your problem. (I should really make this the default.)

Cull is set up to require a Cell.dirty = true flag before recalculating its bounding box (since it's an expensive operation). Since you added an array, I don't track old vs. new objects so I don't know what's been initialized. I guess I could diff each frame, but that would be expensive too.

The SpatialHash allows you to add PIXI.Containers, which fire events when a child is added, so it can perform the initialization. I don't remember why I didn't add it to Simple as well. Probably laziness.

zhouccccc commented 4 years ago

Cooooooooooooooool !! It's working, Great thanks!!

AdrienLemaire commented 3 years ago

Oops. Try settings options.dirtyTest = false when you instantiate the Cull. That should fix your problem. (I should really make this the default.)

I got bitten by this as well. const cull = new Cull.Simple({ dirtyTest: false }); solved it.