Surface Net

Hello, i am currently trying to implement the surface net’s logic similar to this here: http://www.cs.tufts.edu/~frisken/surfaceNets.pdf



I think i have layed out the surfaceNodes/Links right, also the smoothing i think should work. However, i have no idea how to generate the mesh from the results.



Basically i have:

[java]

public class SurfaceNode {



int x, y, z;

Vector3f position;

float scale;

SurfaceNode surfaceNodes[];

Surface surface;



public enum Link {



Front, Back, Top, Bottom, Left, Right;

}



public SurfaceNode(int x, int y, int z, Vector3f position, float scale, Surface surface) {

this.x = x;

this.y = y;

this.z = z;

this.position = position;

this.scale = scale;

this.surface = surface;

surfaceNodes = new SurfaceNode[6];

}



public void setLinkNode(SurfaceNode node, Link link) {

this.surfaceNodes[link.ordinal()] = node;

}



public SurfaceNode getLinkNode(Link link) {

return this.surfaceNodes[link.ordinal()];

}

}

[/java]



Can anybody give me a hint on this?

1 Like

Ouhouuuu, done. It even works way better then expected for such a dirty approach. Whats left to do is to find a way how to calculate the normals. The resulting terrain looks pretty natural on the first view, after calculation i have the same performace as with a plain bloxel world. Not unexpected since no additional vertices are added.



However, easy world design, caves, overhangs… No idea yet about texturing.



Here are some screens:



Bloxel:

http://i.imgur.com/8tUMY.png



Surface Net:

http://i.imgur.com/Y7g7z.png



Bloxel:

http://i.imgur.com/wgTgc.png



Surface Net:

http://i.imgur.com/Q27Ho.png

3 Likes

Cool :smiley: Care to replace the currently non-working block world/surface mesh plugins for the SDK? :slight_smile:

nice!

@normen said:
Cool :D Care to replace the currently non-working block world/surface mesh plugins for the SDK? :)


Block world plugin for the SDK? Never have seen that..
There are a few things left before this can be used:
-Currently the surface layer does not know on which side the solid part is. So calculating the normals and putting the vertices in the correct order is still a problem.
-I don't know yet how texturing can work on this.
-Currently each change on the underlying binary bloxel data requires to recalculate the whole map.
-I have also no idea how tiling on this type of terrain should be implemented, because in the current design it will produce round edges where the tiles meet.

So i think in the current state it will cause more problems to users than it would solve.

All the thing is currently only about 400 LOC without any line of documentation.. So i am not sure how to publish it..

…as a jar library I’d say, ideally with javadoc :wink: You can wrap these in a plugin so users can install them in the SDK and get updates.

Aw crap… now I am gonna be freakin’ out until I’m able to figure out how this works. This would make procedural generated vegetation a breeze. To many things to learn… not enough brain to remember them all… never mind figure them out >.<

Ok… here be my initial assumption on how this works. It’s pretty much identical to using Catmull Clark Sub-Sufacing… but instead of adding verts, you’re averaging using the existing surrounding verts.



Am I close?? hahahahaha This is killin’ me. Great work!

@t0neg0d said:
Ok... here be my initial assumption on how this works. It's pretty much identical to using Catmull Clark Sub-Sufacing... but instead of adding verts, you're averaging using the existing surrounding verts.

Am I close?? hahahahaha This is killin' me. Great work!


The link in the first post explains it way better than i ever could. It's acutally pretty easy in theory, the implementations for linking the SurfaceNodes made me loose some hair .. ;)

Basically i am generating one vertex for each visible side of a Bloxel(On a new Block, outside). During the smoothing i am minimizing the sum of distances between a vertex and it's neightbours. (Each vertice is however not allowed to move outside of the original bloxel)..

That's it ;) Way less complicated the any SubDivision Algo i have seen.

[patch][/patch]

@zzuegg said:

During the smoothing i am minimizing the sum of distances between a vertex and it’s neightbours.



If you know the vertices neighboring vertices already... the normals calculation is really easy.

This is set up for calculating a grid... but the idea is the same... just potentially less neighboring vertices:

[java] private void recalculateNormals(float[] buffer, Vector3f[][] vMap) {
int index = 0;

int mapSize = vMap.length;

Vector3f v0 = new Vector3f(),
v1 = new Vector3f(),
v2 = new Vector3f(),
v3 = new Vector3f(),
v4 = new Vector3f(),
v5 = new Vector3f(),
v6 = new Vector3f(),
v7 = new Vector3f(),
v8 = new Vector3f(),
r = new Vector3f();
for (int x = 1; x < mapSize-1; x++) {
for (int y = 1; y < mapSize-1; y++) {
// System.out.println(String.valueOf(x) + "," + String.valueOf(y));
// Assume grid normals are facing upward
v1.set(0,1,0);
v2.set(0,1,0);
v3.set(0,1,0);
v4.set(0,1,0);
v5.set(0,1,0);
v6.set(0,1,0);
v7.set(0,1,0);
v8.set(0,1,0);

// Set center vertex
v0.set(vMap[x][y]);
// Grab adjacent vertices in a clockwise fashoin
v1.set(vMap[x-1][y-1]);
v2.set(vMap[x-1][y]);
v3.set(vMap[x-1][y+1]);
v4.set(vMap[x][y+1]);
v5.set(vMap[x+1][y+1]);
v6.set(vMap[x+1][y]);
v7.set(vMap[x+1][y-1]);
v8.set(vMap[x][y-1]);

// Substract the center vertex from each of the adjacent
v1.subtractLocal(v0);
v2.subtractLocal(v0);
v3.subtractLocal(v0);
v4.subtractLocal(v0);
v5.subtractLocal(v0);
v6.subtractLocal(v0);
v7.subtractLocal(v0);
v8.subtractLocal(v0);

// Get the normalized cross product of each vertex
// and it's clockwise adjacent vertex
Vector3f r1 = v1.cross(v2).normalize();
Vector3f r2 = v2.cross(v3).normalize();
Vector3f r3 = v3.cross(v4).normalize();
Vector3f r4 = v4.cross(v5).normalize();
Vector3f r5 = v5.cross(v6).normalize();
Vector3f r6 = v6.cross(v7).normalize();
Vector3f r7 = v7.cross(v8).normalize();
Vector3f r8 = v8.cross(v1).normalize();

// Get a sum of the results
r.set(r1);
r.addLocal(r2);
r.addLocal(r3);
r.addLocal(r4);
r.addLocal(r5);
r.addLocal(r6);
r.addLocal(r7);
r.addLocal(r8);

// Append it to the normals float buffer
buffer[index] = r.x;
index++;
buffer[index] = r.y;
index++;
buffer[index] = r.z;
index++;
}
}
}[/java]
@t0neg0d said:
[patch][/patch]

If you know the vertices neighboring vertices already... the normals calculation is really easy.

This is set up for calculating a grid... but the idea is the same... just potentially less neighboring vertices:



Thanks, but the problem is i don't know which side is solid. Currently i also need the disable face culling...
@zzuegg said:
Thanks, but the problem is i don't know which side is solid. Currently i also need the disable face culling...


Couple questions...

The shapes I see in the screen caps, before you run this process,
Are they individual quads?
Or a single connected mesh?

Either way, I guess it really doesn't matter. If you are building the original mesh out of box faces (top, left, bottom, etc, etc)... set up the normals on these and apply these normals to the verts as you create them... this won't produce usable final normals, but will tell you which direction the new verts is generally facing (i.e. which direction the "outside" solid face is)

When it comes to texturing …

I am using triplanar texture mapping and encode the used material in the VertexColors ( There is some fiddling involved… ). I then blend the different textures and calculates the UV maps at runtime. It gives nice results for a single material, okayish for multiple. But im trying to get the whole thing in one pass, one render cycle etc. I dont want multiple meshes.



Maybe someone can find some helpfull advice in that. ^^"







PS: Nice work there. :slight_smile:

@t0neg0d said:
Couple questions...

The shapes I see in the screen caps, before you run this process,
Are they individual quads?
Or a single connected mesh?

Either way, I guess it really doesn't matter. If you are building the original mesh out of box faces (top, left, bottom, etc, etc)... set up the normals on these and apply these normals to the verts as you create them... this won't produce usable final normals, but will tell you which direction the new verts is generally facing (i.e. which direction the "outside" solid face is)


One single connected mesh, it's actually the same mesh as after smoothing, i only modify the vertex positions.
I get what you mean, and i will try it of course. Currently i cannot imagine how it would work because:

Let's assume i have such a box layout

_ _ _ _ _ _ _
_ b _ _ _ _ _
_ b b b _ _ _
_ b b b _ _ _
_ _ _ b _ _ _
_ _ b b _ _ _
_ _ _ _ _ _ _

This will generate following surface net

N N N _ _ _ _
N b X N N _ _
N b b b N _ _
N b b b N _ _
N X X b N _ _
_ N b b N _ _
_ N N N N _ _

The net nodes marked with an X have more than one block as parent. While the Nodes with only one parent are not a problem, the one with more are currently a problem...

add: during writing this i maybe found a way, i probably can simply average the normals of all parents on these specific nodes... i am going to try
1 Like
@KuroSei said:
When it comes to texturing ...
I am using triplanar texture mapping and encode the used material in the VertexColors ( There is some fiddling involved.... ). I then blend the different textures and calculates the UV maps at runtime. It gives nice results for a single material, okayish for multiple. But im trying to get the whole thing in one pass, one render cycle etc. I dont want multiple meshes.

Maybe someone can find some helpfull advice in that. ^^"



PS: Nice work there. :)


Thanks, any information on texturing is going to be helpful. This is the next target right after i fixed the normal generation

First test seems to give at least some usuable results.



http://i.imgur.com/VvPLM.png

Niceness, then throw some tessellation magic on this and your good to go :stuck_out_tongue:

@kwando said:
Niceness, then throw some tessellation magic on this and your good to go :P


Nah, first i want a texturing system, then a good editor, the i have to look on how to increase the editing speed for big meshes, the i will make an RTS game i have in my mind for years, and then maybe i am adding displacement mapped tessellation for the details. So basically really really low priority until everything else works nicely

I wasn’t really serious… I sure do waiting for a RTS game from you :slight_smile:

@kwando said:
I wasn't really serious.. I sure do waiting for a RTS game from you :)


Oh, don't wait, could be a very very long time..