Proposed integration with Simplex3D.

6 views
Skip to first unread message

Lex

unread,
Jun 21, 2010, 5:46:58 PM6/21/10
to sgine-dev
Recap of IRC discussion and quick overview.


Math library follows GLSL very closely. The idea is to allow vectors
and matrices to be treated like primitives most of the time. This
means functional style such as normalize(vector) instea of
vector.normalize().

The library is fully unit tested. You can use GLSL spec as
documentation. Additional documentation is available here:
http://code.google.com/p/simplex3d/wiki/MathLibrary_vsGLSL


Simplex3d Math has:
1) Strightforward API and implementation.
2) Vectors/Quaternions/Matrices only have operators, and always
produce a new Mutable instance.
3) Functions are static and always product a new Mutable instance with
some rare exceptions when they have to return more than one object.
4) Constant vectors instead of flyweight pattern. For example:
matrix(columnId) will return a constant vector, so there is ambiguity
on what happens when matrix(columnId).x = 1 is called. The same
approach is used for Vertex buffers.

Simplex3d Math tries to avoid:
1) Tricky API for manual garbage management.
2) Operators that mutate instances such as transformLocal,
translateLocal... anythingLocal (however component mutators and
methods like += and *= are supported).
3) Multiple aliases of the same function.
4) Ambiguities in the API where a programmer is unsure about the
result of an operation. Prevention of accidental leakage of mutable
data into multiple parts of the program when changes of such data
become unexpected.


Simplex3d Math list of key features examples:
http://code.google.com/p/simplex3d/wiki/MathLibrary_Features
More examples (less organized): http://code.google.com/p/simplex3d/wiki/MathLibrary_Examples

Working demo using Simplex3d Math: http://lexapplets.appspot.com/files/mercury.jnlp
Source for the demo: http://lexapplets.appspot.com/files/mercury-src.zip

Zipped ScalaDoc: http://code.google.com/p/simplex3d/downloads/detail?name=simplex3d-math-light.javadoc.zip&can=1&q=


Changes required to integrate (besides translating the code from
sgine.math to simplex3d.math):
1) Rewrite Ray class.
2) Redesign of Properties to handle mutable references to immutable
instances and track updates via new assignmnets to the reference.
3) General shift to treat Vectors and Matrices in more functional way.
4) General shift towards Properties with immutable data.


Once itegrated the secon step is to add Buffer API:
http://code.google.com/p/simplex3d/wiki/BufferLibrary

Hicks, Matt

unread,
Jun 21, 2010, 6:20:32 PM6/21/10
to sgin...@googlegroups.com
Thanks Lex!

Here are a few items of concern for me:
  1. Most of the code seems focused around instantiation of new objects instead of mutability of existing objects. I'm concerned about the performance impact of this in relation to GC'ing for larger applications.  In Java 7 you said your code is optimized for escape analysis which is awesome, but I'm concerned about people that are not and will not be running Java 7 in the future.
  2. The matrix classes do not back against a direct buffer, correct?  That is one of the features I find very nice in Sgine currently is that I can simply reference matrix.buffer to pass to OpenGL.  I like the idea of all objects being backed by a direct buffer...what are your thoughts on this?
  3. All mutable classes in Sgine currently support the Modifiable trait that essentially allows an outside entity to determine if the object has changed since it last looked at it.  Since Sgine is very much event-driven I'm concerned for this aspect of the coding.  Do you have any suggestions of a better way to avoid updating every frame for mutability?
I'm looking at the docs you linked to and I like much of what I see. I really don't want to convey that I'm opposed to this as I see many benefits, I would just prefer to handle all the concerns up-front so we can determine if this is the best route to take. It's very appealing to have a complete math API that we don't have to maintain in Sgine for ourselves. :)

I would like to get as much feedback on this as possible.  I am definitely not an expert in all of the math of a 3d engine so any suggestions or thoughts are very much welcome.

Lex

unread,
Jun 22, 2010, 2:05:10 PM6/22/10
to sgine-dev
Below is a benchmark showing performance differences between current
sgine Matrix implementation and simplex3d.

I have tried to compare different operations such as multiplication,
local multiplication ( *= in simplex3d) and transformations. However
allocating sgine Matrix in a loop would crash my computer. My guess
this happens due to directBuffer allocation and JVM not being able to
manage direct buffers allocation/deallocation efficiently. This may
not be an issue in general, but it's very easy to fall into the trap
and write a code that allocates many Matrix4 objects, crashing the
system.
Because of this limitation I had to stick with transformation tests,
which behave as expected. One thing to note is that sgine
transformation operations happend in order right to left, so:
Matrix4() trasnlate() scale() will scale first, then translate. In
simplex3d the order of operations is how they are wrtitten, from left
to right.

Since simplex3d transformations are optimised and are using 3x4
matrices instead of 4x4, i have added a test that is constructing and
multiplying simplex3d 4x4 matrices. This way it is more fair, because
sgine is using 4x4 matrices.

Below are the results (in milliseconds):
Sgine transform time: 12889.
Simplex transform time: 4999.
Simplex simulated transform time: 7397.

Simplex3d is 2.5 times faster when using optimized Mat3x4, and 1.75
times faster when doing transformations by multipling 4x4 matrices.
Notice that simplex3d is making a new instance on every operation, and
in case of simulating transformations it is making new instances to
multiply by. Yet it significantly outperforms sgine implementation.
The main reasons are: sgine Matrix using direct buffer, and tracking
updates to the Matrix.


Conclusion: making new instances on new operations are small potatoes
compares to backing with direct buffers and tracking changes. If the
performance is your main concern - upgrade! You will get an easy to
use math library that can help you write strightforward code. Mangling
your garbage objects manually will not net you much performance, but
will make your code bugprone, hard to read, and hard to maintain.
Moreover, the fastest possible math is when you inline it. And you
will end up doing it for heavily used methods such as
transformVertexBuffer(matrix, buffer) regardless of what math package
you use.

Benchmark code:
{{{
// Place both sgine.jar and simplex3d-math.jar on the classpath.
package bench

import java.nio._

import simplex3d.math._
import simplex3d.math.doublem.renamed._
import simplex3d.math.doublem.DoubleMath._

import org.sgine.math.mutable._


/**
* @author Aleksey Nikiforov (lex)
*/
object MatBench {

def main(args: Array[String]) {
val bench = new MatBench()
bench.run
bench.run
bench.run
}
}

class MatBench {
val length = 10000
val loops = 1000


def run() {
var start = 0L

//WARNING! Running the test with the following line uncommented
will crash your computer.
//testSgineCrash(length, loops)


System.gc()
start = System.currentTimeMillis
testTransformSgine(length, loops)
val sgineTransform = System.currentTimeMillis - start

System.gc()
start = System.currentTimeMillis
testTransformSimplex(length, loops)
val simplexTransform = System.currentTimeMillis - start

System.gc()
start = System.currentTimeMillis
testSimulatedTransformSimplex(length, loops)
val simplexSimTransform = System.currentTimeMillis - start


println()
println("Sgine transform time: " + sgineTransform + ".")
println("Simplex transform time: " + simplexTransform + ".")
println("Simplex simulated transform time: " + simplexSimTransform
+ ".")
println()
}

// This seemingly harmless code will consume all the available
memory.
def testSgineCrash(length: Int, loops: Int) {
val m = Matrix4(
0.1, 0.4, 0.7, 0.3,
0.6, 0.3, 0.6, 0.8,
0.9, 0.2, 0.3, 0.7,
0, 0, 0, 1
)

var l = 0; while (l < loops) {
var i = 0; while (i < length) {

m mult Matrix4(
i + 0, i + 1, i + 2, i + 3,
i + 4, i + 5, i + 6, i + 7,
i + 8, i + 9, i + 10, i + 11,
i + 12, i + 13, i + 14, i + 15
)

i += 1
}
l += 1
}

println(m)
}


def testTransformSgine(length: Int, loops: Int) {
val m = Matrix4(
0.1, 0.4, 0.7, 0.3,
0.6, 0.3, 0.6, 0.8,
0.9, 0.2, 0.3, 0.7,
0, 0, 0, 1
)

var l = 0; while (l < loops) {
var i = 0; while (i < length) {

m rotate(x = i) translate(l, i + 1, i + 2) scaleAll(1.00001)

i += 1
}
l += 1
}

println(m)
}

def testTransformSimplex(length: Int, loops: Int) {
var m = Mat3x4(
0.1, 0.4, 0.7, 0.3,
0.6, 0.3, 0.6, 0.8,
0.9, 0.2, 0.3, 0.7
)

var l = 0; while (l < loops) {
var i = 0; while (i < length) {

m = m rotateX(i) translate(Vec3(l, i + 1, i + 2))
scale(1.00001)

i += 1
}
l += 1
}

println(m)
}

// A comparision with unoptimised multiplication of Mat4x4, to be
fair.
def testSimulatedTransformSimplex(length: Int, loops: Int) {
var m = Mat4(
0.1, 0.4, 0.7, 0,
0.6, 0.3, 0.6, 0,
0.9, 0.2, 0.3, 0,
0.3, 0.8, 0.7, 1
)

var l = 0; while (l < loops) {
var i = 0; while (i < length) {

val s = Mat4(1.00001)
s.m33 = 1
val t = Mat4(1)
t(3) = Vec3(l, i + 1, i + 2)*1.00001

m = s * t * Mat4(rotationMat(i, Vec3.UnitX)) * m

i += 1
}
l += 1
}

println(m)
}
}
}}}

On Jun 21, 6:20 pm, "Hicks, Matt" <mhi...@captiveimagination.com>
wrote:
> Thanks Lex!
>
> Here are a few items of concern for me:
>
>    1. Most of the code seems focused around instantiation of new objects
>    instead of mutability of existing objects. I'm concerned about the
>    performance impact of this in relation to GC'ing for larger applications.
>    In Java 7 you said your code is optimized for escape analysis which is
>    awesome, but I'm concerned about people that are not and will not be running
>    Java 7 in the future.
>    2. The matrix classes do not back against a direct buffer, correct?  That
>    is one of the features I find very nice in Sgine currently is that I can
>    simply reference matrix.buffer to pass to OpenGL.  I like the idea of all
>    objects being backed by a direct buffer...what are your thoughts on this?
>    3. All mutable classes in Sgine currently support the Modifiable trait
> >http://code.google.com/p/simplex3d/downloads/detail?name=simplex3d-ma...

Lex

unread,
Jun 24, 2010, 11:00:13 PM6/24/10
to sgine-dev
I've been looking more at the sgine source code. It seems the scope of
the required changes is involved with sgine internals much more than I
anticipated. I think it's best if redesign of the property system and
state tracking is done by the original author.
> ...
>
> read more »

Hicks, Matt

unread,
Jun 26, 2010, 6:36:02 PM6/26/10
to sgin...@googlegroups.com
I have spent a bit of time looking through simplex3d and though it has definitely brought to light many mistakes I made in the architecture of Sgine's math system I still haven't decided whether it is a better idea to change what we currently have to follow a better design pattern or to switch to simplex3d.  I have some ideas about solving the existing problems in Sgine while avoiding some of the items I see as either problematic or over architected in Simplex.  Lex, I by no means want to lose the benefits of your math and programming knowledge in Sgine, but I do want to spend a little bit of time with some of these new ideas floating in my head and get them out into code to see if they actually make sense.  At that point I would like yours and others feedback on how to proceed.  If you think they are great ideas and would like to implement them in Simplex then great, if you think they suck and explain why it can be a learning experience, and if you prefer your way and I prefer mine we can agree to disagree and move on. :)

I wanted to take some time to write my current thoughts as I've been moderately quiet lately about this and didn't want you to think I had forgotten about you.

Thanks,

Matt / darkfrog

Hicks, Matt

unread,
Jun 26, 2010, 8:17:57 PM6/26/10
to sgin...@googlegroups.com
Well lex, I'm not sure you'll like what I've come up with, but I've got to say I really like it.  I've attached the very beginnings of the library to this message and apart from some possible performance hindrances (which I'm hoping you'll be willing to help out with), I think it is the most elegant way I've ever seen of handling such a thing.

I hope you all feel the same way and now I'm excited about integrating it. :)
sgine-math2.zip

Hicks, Matt

unread,
Jun 26, 2010, 9:06:50 PM6/26/10
to sgin...@googlegroups.com
Here is another update for better default efficiency. It adds quite a bit of code for the "simple" case, but keeps object creation to a minimum.
sgine-math2.zip

Lex

unread,
Jun 27, 2010, 1:10:15 AM6/27/10
to sgine-dev
I have already resolved all the performance issues in one math
library. Once is enough for me, so I respectfully decline any further
involvement in your experiment. Just remember to benchmark it before
making any judgement about performance.

Best Regards,
Lex


On Jun 26, 9:06 pm, "Hicks, Matt" <mhi...@captiveimagination.com>
> ...
>
> read more »
>
>  sgine-math2.zip
> 6KViewDownload

Hicks, Matt

unread,
Jun 27, 2010, 7:35:03 AM6/27/10
to sgin...@googlegroups.com
Not even interested in taking a look at the conceptual differences? :)

Hicks, Matt

unread,
Jun 27, 2010, 8:06:17 AM6/27/10
to sgin...@googlegroups.com
Ouch, I just did a simple comparison in basic performance and simplex3d is actually significantly faster for basic addition of immutable Vec3s.

I really like my approach to the design but unfortunately it would appear the performance doesn't touch yours....the way I did this would allow your API to shrink significantly in size, which is the primary reason I thought it would be beneficial.  Lex, I'd like your opinion if some of the ideas in this are applicable to simplex as API size is still a big concern.

Also, it bothers me that Vec3d basically seems to have color concepts built into it....logically it seems like ugly mixing of dissimilar things as Color isn't technically a Vector.  If you're open to some criticism and possible tweaks in design I think we can start moving forward with simplex.

Hicks, Matt

unread,
Jun 27, 2010, 9:32:05 AM6/27/10
to sgin...@googlegroups.com
Lex, some questions:

What is the proper way of doing this: Mat4d.Identity.translate(x = -630.0, y = 470.0, z = -500.0))

It says there isn't a translate method on Mat4d?

Also, is there a convenience method to update a buffer with the contents of a Mat4d or do I have to do it manually like:

def loadMatrix(matrix: Mat4d) = {
        matrixBuffer.put(0, matrix.m00)
        matrixBuffer.put(1, matrix.m10)
        matrixBuffer.put(2, matrix.m20)
        matrixBuffer.put(3, matrix.m30)
        matrixBuffer.put(4, matrix.m01)
        matrixBuffer.put(5, matrix.m11)
        matrixBuffer.put(6, matrix.m21)
        matrixBuffer.put(7, matrix.m31)
        matrixBuffer.put(8, matrix.m02)
        matrixBuffer.put(9, matrix.m12)
        matrixBuffer.put(10, matrix.m22)
        matrixBuffer.put(11, matrix.m32)
        matrixBuffer.put(12, matrix.m03)
        matrixBuffer.put(13, matrix.m13)
        matrixBuffer.put(14, matrix.m23)
        matrixBuffer.put(15, matrix.m33)
       
        glLoadMatrix(matrixBuffer)
    }

Thanks. :)

Lex

unread,
Jun 27, 2010, 12:50:31 PM6/27/10
to sgine-dev
Peformance, size, and design: I have tried many things to improve the
performance and size over the course of 6 month. Eventually I have
settled on the present design. In my opinion, given the feature set
and usability requirements, the disign is close to optimal and cannot
be improved much further.

Size concerns: The best way to reduce size is to remove features you
are not planning to use. I have made a custom jar with the size of
199.5Kb, and it is possible to push the size further by removing
functions from DoubleMath object.

Vector as Color: The color concepts are not build into vectors.
Vectors simply have RGBA accessors, just like they do in GLSL. This
feature is heavily used when developing shaders and I have never seen
anyone calling it "ugly mixing of dissimilar things" until now.
Addition, multiplication and other operations work out equally well
for vectors and colors. Also using vectors to store colors removes the
need for another Class, reducing the API size (which seems to be a big
concern for you).

Trasnformations and Matrices: Ma3x4 and Mat2x3 are the matrices that
have transformation methods. They are quicker than Mat4 and Mat3 and
represent the same transformations with the exception of projections.
Projections are used very rarely and in those cases you can use Mat4
and matrix multiplication.

Matrix to OpenGL: If you import "simplex3d.math._" you will have the
following methods avilable: matrixToArray() and matrixToBuffer() for
Float and Double Arrays/Buffers.


On Jun 27, 9:32 am, "Hicks, Matt" <mhi...@captiveimagination.com>
wrote:
> ...
>
> read more »

Hicks, Matt

unread,
Jun 27, 2010, 2:00:19 PM6/27/10
to sgin...@googlegroups.com
I still don't like it, but if you're deferring to GLSL standards I guess I can't complain too much. :o

Okay, I'm in the process of trying to switch over to using Simplex3D, so I'll probably be shooting questions out periodically throughout the day.

Hicks, Matt

unread,
Jun 27, 2010, 2:12:04 PM6/27/10
to sgin...@googlegroups.com
There does not appear to be an alternative to "Ray" in simplex3d...is this something you plan to add support for or should this be handled in Sgine?

Perhaps it would be better to do this migration when you are available on IRC.  Is there a good time over the next week we could schedule to do this?  I'll do all the coding, I just need some help understanding certain things about Simplex3D.

Lex

unread,
Jun 27, 2010, 4:12:37 PM6/27/10
to sgine-dev
Ray: There are many classes that can be useful in a 3d application. It
is not possible to put them all in one library. In case of the math
library I have tried to keep it to the most general classes. Ray and
Plane have not made it.

IRC time: I'll should have some time on tuesday.


On Jun 27, 2:12 pm, "Hicks, Matt" <mhi...@captiveimagination.com>
> ...
>
> read more »

Hicks, Matt

unread,
Jun 27, 2010, 5:56:12 PM6/27/10
to sgin...@googlegroups.com
Lex, what do you think about me creating a branch in Sgine that we can collaboratively work with?  I fear that I don't know enough about your library to integrate and you don't know enough about mine.  If you're willing to collaborate on a branch we could do the parts that we understand and ask for help on the parts we can't.  If you're willing I'll create a branch this evening with the small changes I've made (mostly deleting the math package, adding the simplex3d dependencies) and we can keep from messing with the tip until it's finished and working?

Lex

unread,
Jun 27, 2010, 6:57:25 PM6/27/10
to sgine-dev
Sounds like a plan. This way we dont have to depend on bein on IRC at
the same time.

On Jun 27, 5:56 pm, "Hicks, Matt" <mhi...@captiveimagination.com>
> ...
>
> read more »

Hicks, Matt

unread,
Jun 27, 2010, 8:07:24 PM6/27/10
to sgin...@googlegroups.com
If you switch from the default branch to the simplex3d branch you should have my broken copy. :)

I'm currently relying on your project from SVN rather than on JARs currently but we can check-in JARs after all is working again.
Reply all
Reply to author
Forward
0 new messages