ThreeJs - is render order dependent on object creation order? - javascript

I have an issue with render order in my scene. All objects have transparency. There are multiple child objects for each object in the scene.
Each scenario below uses the same data.
Option 1 below works as intended. But I need option 2 to work since the user of the application should not have to manually add data to the application.
If I manually add a set of objects in a specific order they render properly.
If I load all the objects at once and then add them to the scene in a specific order, the render order is wrong. I thought the documentation said they are rendered based on order added to the scene. I figure this would give the same result as option 1.
If I load all the objects and hard code renderOrder, the order is wrong since child objects have different depths in the scene.
I cannot figure out why option 1 and option 2 give different results. I would prefer to not use option 3.
Is there something else besides order of objects added to the scene that determine render order?
Here are two videos.
Correct Render Order
Incorrect Render Order

If you don't know what order they'll be added to the scene, you can force the render order by using the Object.renderOrder property. You'll probably want to render the background objects first, but this might give you problems when the camera is facing down the opposite direction.
If like you said, all objects have transparency, then you might want to disable depthTest so everything just ignores the depthMap when being rendered.

Related

How to save the open/closed state of an object

I've made a component that visualizes an object where array's and nested objects are collapsible.
It works by looping through all the keys/indexes and using the appropriate render function. Right now the collapse and extend actions are purely CSS class-based.
The issue I have right now is that I need to make it so the collapsed/extended state persists. So basically I need a way to store the collapsed state info. and read it later on. I'm not really sure how to even start.
The state should persist even when the object is modified. So when an new item gets pushed in the middle of the array it should still open the same thing. What data structure should I use for this and how would I read it?
The reason I'm not posting any code is that I don't think it's necessary, I'm purely interested in how the data should be structured for the collapsed/extended state of an array/object so it persists when updates are made to the object/array.
I've tried making some type of "breadcrumbs" that follow the structure of the object but then I realized that it won't persist when changes are made.
Any ideas? Is this even possible without some hardcoded unique ids?
Edit 1: point 4 it's not optimal and can be done better - after you finish rendering the main object to the DOM, loop through the state object and for each path, find the DOM node and expand it.
Edit 2: instead of 'index1.nestedIndex2[1].nestedIndex3' you can do 'index1.nestedIndex2.1.nestedIndex3', makes your code simpler
Edit 3: no need to use lodash (edited point 1)
I hope I understood your scenario correctly.
In order to persist the expanded (or collapsed) state, you have to:
create an object that stores the paths to the indexs that you want expanded, like this {'index1.nestedIndex2[1].nestedIndex3': true}. You can do this when clicking to expand. Of course, this means you should know the current index and it's parents when you click - one way to do this is by having a DOM attribute holding the index, on each element. So when you click a node to go up recursively until you reach the top element, and build that string path
Convert the state object to a string using JSON.stringify and store it in localStorage (https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage). localStorage.set('expandedState', JSON.stringify(stateObject)). If you need to store the state for multiple data objects, you have to use some specific key instead of 'expandedState'
In the code, before rendering the main object, convert the string state from localStorage back to an object using JSON.parse
While rendering your main object, you have to build the path for the currently rendered node and check if it can be found in the state object. If yes, expand it by adding your css class on it. To build back the path, it's more optimal to build it as you render each node rather than using the same method used in point 1, but that would also work (but slower, so for really big objects will be a problem, I think)

How to filter Mapbox Markerclusters?

Since layers are projections of the source, and clusters are basically layers too, filtering the layers have no effect on the clustering, and the filtered out objects will still be visible on the cluster layers
Honestly it gave me a lot of trouble to figure out, and I came to a kind of hacky solution, but it works, and gives your application a lot better performance than manually filtering your GeoJSON features.
The Mapbox devs gave us the possibility to filter sources, but you cannot call .setFilters() on it later, there is basically no proper way to dynamically update it, which would be completely necessary to make a marker filtration function work.
If you use a dynamic filter, updating it will have no effect on your source, however, once you update the source content itself, it will update the filter as well.
So you want to initialize your source with a similar filter:
filter: ['match', ['get', 'layerType'], this.filteredLayers, true, false],
With this filter your GeoJSON features need a layerType field in properties, and if the filteredLayers array has it, it will be displayed.
You have to separately store your source data to be able to update it again the following way (or you can wait for the next iteration if you are using real time data for example).
this.filteredLayers.push('restaurants');
this.map.getSource('places').setData(data);
With this method you don't need a layer filtration logic, you only write filters like this to the source itself, and the clusters will properly display the visible data only too.
Another important thing is here that once you create a new array instance, the whole thing breaks. You must use .push() and .pop() only to filter the data.
You can write a filter removal function by sorting the filters first, and then popping them out one by one.
I've seen many people struggling with this issue and couldn't find this solution online, so I thought I would share.

Assign views randomly using an array - react native

I'm trying to come up with a way of randomly inserting views into a flexbox grid I've made in my app. The app looks like this
I have an array which will have a maximum of 6 elements, however these can change.
I want to insert these elements into the grid at random, however it's proving to be more difficult than I expected.
I grab the array asynchronously, so it needs to update on the fly.
Can anyone recommend any way of doing this? I'd post the code I've tried but it's pretty useless up to now.

Progressive Filtering in Pixi.js

I have an image in Pixi.js, and I want to apply a filter to it. This is simple enough, but I want the filter to actually change the image, so that the next frame, what is rendered is a filtered filtered image, and so on. How do I create a Pixi object that renders to itself every frame?
I found this, which seems to be asking a similar question, but I cannot make sense of the code provided or the responses.
Try using the PIXI.RenderTexture class to create an in-memory image and render to it what you want. The render texture will preserve what you've rendered previously.
Here is an example that does that: http://pixijs.io/examples/#/demos/render-texture-demo.js
Here are the docs: http://pixijs.download/release/docs/PIXI.RenderTexture.html
Note: To preserve contents when rendering to a texture you need to tell PIXI to not to clear the texture before rendering to it. The below line is from the linked example and the false value does just that:
...
app.renderer.render(app.stage, renderTexture2, false);
...

React Redux rerenders whole list on single object attribute change

I've a list (immutable.js) in my store containing multiple objects.
This list is displayed in a component as a table with rows. Those rows are subcomponents displaying one single object. One attribute of those objects should be editable. So onChange() i dispatch an action which should change the attribute of that one specific object. As we should never ever change the state, i return a whole new list with just that single object changed. But because the whole list is a new list object, the table component gets updated every single change. this leads to a really slow working app.
I've just looked at the official todo app example and inspected it with the Perf addon. Realising that they also rerender the whole todos-list on every change (mark as completed, unmark). How am I supposed to fix that?
The biggest factors that will impact your list rendering performance are heavy rendering cycles and expensive DOM mutations. Make sure that your list items are as efficient as possible when they re-render. Done properly, this will make a big difference.
You have a couple of straight forward options.
Break your rows out into their own component (if not already done) and optimize the render and update cycle.
Use a library such as react-virtualized to help with list/table/grid performance.

Categories

Resources