Suggested change to TriangleMesh API

Alexander Kouznetsov alexander.kouznetsov at oracle.com
Fri Apr 12 19:26:47 PDT 2013


This is tracked with https://javafx-jira.kenai.com/browse/RT-29696

Best regards,
Alexander Kouznetsov
(408) 276-0387

On 10 апр 2013 17:05, Jasper Potts wrote:
> Hi all,
>
> The current API for TriangleMesh doesn't feel like it fits with the 
> style of all other JavaFX API. The suggestion to to move to 4 
> ObservableLists for Points, Texture Coords, Faces and Smoothing 
> Groups. The problem is for memory usage and performance we don't want 
> to move from primitive "float/int" to "Float/Integer" so we need to 
> add a Observable List type for "float" and "int".
>
> package javafx.scene.shape;
>
> public class TriangleMesh {
> ObservableFloatList getPoints();
> ObservableFloatList getTextureCoords();
> ObservableIntList getFaces();
> ObservableIntList getSmoothingGroups();
> }
>
> Now this is where the problem is, there are 3 options I can think of:
>
> *OPTION 1*
>
> Add 2 new interfaces that extend ObservableList<Float> and adds 
> primitive float methods. Then we can add float[] implementations
>
> package javafx.collections;
>
> public interface ObservableFloatList extends ObservableList<Float> {
> public void addAll(float… elements);
> public void setAll(float... elements);
> float[] toArray(float[] a)
> public float getFloat(int index)
> public void setFloat(int index, float value)
> public void addFloat(float value)
> public void addFloat(int index, float value)
> }
>
> public interface ObservableIntegerList extends ObservableList<Integer> {
> public void addAll(int… elements);
> public void setAll(int... elements);
> int[] toArray(int[] a)
> public int getInt(int index)
> public void setInt(int index, int value)
> public void addInt(int value)
> public void addInt(int index, int value)
> }
>
> add to FXCollections {
> ...
> ObservableFloatList observableFloatList()
> ObservableFloatList observableFloatList(float[] values)
> ObservableIntegerList observableIntegerList()
> ObservableIntegerList observableIntegerList(int[] values)
> }
>
> The issue with this idea is how to create a implementation of 
> ObservableList <Float> that uses a float[] as a internal backing 
> store. The list contract states that myList.get(10) == myList.get(10) 
> but this would fail as they would return two different instances of 
> Float objects. So this option breaks the contract of "List" and 
> "Collection" and may have issues if this list is passed into any API 
> that accepts a standard Collection and relies on the fact that a get() 
> will will return the same object as passed to the set().
>
> *OPTION 1b*
>
> Same API but inside the implementation of ObservableList <Float> we 
> have two arrays a float[] and a Float[] when the use calls 
> myList.get(10) we create a Float object and store it in the Float[] so 
> on the next call the same object instance is returns. 
> Then  myList.get(10) == myList.get(10) can be true. We can be lazy in 
> creating the Float[] instance to only create it on the first call of 
> get() or the use of any API methods that take a "Float". The pain with 
> this approach is the memory consumption explodes when you use any 
> "Float" API for example iterating of the List would result in the 
> whole list expanding. A rough class is a List of 100,000 floats would 
> take 400kb would expand to 1.6Mb if completely expanded to Float[]. 
> But it could completely abide by the contract of Collection and List.
>
> *OPTION 2*
>
> The other option is to create a new set of classes that are Observable 
> primitive Arrays but does not implement Collection or List. Something 
> like:
>
> public interface ObservableFloatArray extends Iterable<Float>, 
> Observable {
> public int size();
> public void addAll(float… elements);
> public void setAll(float... elements);
> float[] toArray(float[] a)
> public float get(int index)
> public void set(int index, float value)
> public void add(float value)
> public void add(int index, float value)
> public float remove(int index);
>         ….
> }
>
> The advantage of this option is don't have a contract of parent 
> interface like "List" or "Collection" so can do anything we want. We 
> can have only primitive "float" versions of get() and set() etc. It 
> can also avoid all costly boxing/unboxing expect for implementing 
> Iterable<Float>. The down side is that it is complete new collections 
> class and can't be used with any existing Collections API.
>
> So I am not loving any of the approaches at the moment but (2) seems 
> like its the best, what do you guys think?
>
> Thanks
>
> Jasper



More information about the openjfx-dev mailing list