Search Unity

After playing minecraft...

Discussion in 'General Discussion' started by jc_lvngstn, Oct 8, 2010.

  1. goldbug

    goldbug

    Joined:
    Oct 12, 2011
    Posts:
    684
    I think it is better to ask for small stuff at a time rather than "give me everything at once", it has a much better chance of being seen as a low hanging fruit and implemented.

    But feel free to post your own suggestion. I know I would prefer something that works across platforms, otherwise I would not be using Unity.
     
    Last edited: Jun 6, 2014
  2. jordantotty

    jordantotty

    Joined:
    Dec 15, 2011
    Posts:
    77
    Haven't posted in a while, but here's a screenshot of a zombie survival game I started working on yesterday :)
     
  3. Deni35

    Deni35

    Joined:
    Jul 10, 2012
    Posts:
    43
    [QUOTE="goldbug, post: 1655058, member: 67860"
    "give me everything at once"
    [/QUOTE]
    Everything? No. I just want to create fully custom mesh.

    When you create a texture, you can set TextureFormat from a large list of formats. What if this list had only 3 formats? For example: FullColor, ColorWithoutAlpha, OnlyAlpha. Or even without last format. Do you think it would be good?
    Of course, these 3 formats is enough for most cases. But not for all cases!

    Or if Material had only 1 or 2 or 3 properties?

    Not have to make a function for specific cases.
    Necessary to do that the programmer could create your own hight-level functions from low-level Unity API.


    I did not say that unity with Low-level OpenGL and DX API will be not crossplatform. Just you will have to write the implementation for OpenGL and DirectX. But it might give us a lot of opportunities.
    May be possible to create a cross-platform low-level API.
    To have a such API would be really interesting.

    By the way, game for the PC will not be so easy working on mobile. Or progress save system for PC, will not work on web player.

    I've created feedback http://feedback.unity3d.com/suggestions/customizable-mesh-class
     
    Last edited: Jun 7, 2014
  4. goldbug

    goldbug

    Joined:
    Oct 12, 2011
    Posts:
    684
    With the packing trick I saved 15MB of ram at max view distance, and rendering is actually faster (measured, because there are less comparisons, less arrays to deal with, and less data to send to the videocard).

    The day Unity adds a lower level api that lets me use something else other than float I will jump at it right away. For now, bit win!

    \o/
     
    Last edited: Jun 9, 2014
  5. Deni35

    Deni35

    Joined:
    Jul 10, 2012
    Posts:
    43
    How you did a vertex packing?

    Sending data to the video card is fast. Anyway, I have no fps falls when I'm sending data.
    And generation of mesh is very lowers fps due to access to grid structure of map. Only for compution smooth light for 1 vertex I should execute 4 access operation to neighboring blocks.
     
  6. goldbug

    goldbug

    Joined:
    Oct 12, 2011
    Posts:
    684
    vertex is the only one I am not able to compress. I was able to pack color + normal in the color field and uv + hue (I have a hue for colored blocks) in a single uv field,

    So before:
    Vector3 for vertex (12 bytes)
    Vector2 for uv (8 bytes)
    Vector2 for uv2 (I had hue here, 8 bytes)
    Vector3 for normal (12 bytes)
    Color32 for light. (4 bytes)

    Total: 44 bytes / vertex

    Now I have:
    Vector3 for vertex (12 bytes)
    Vector2 for uv + hue (8 bytes)
    Color32 for light + normal (4 bytes)

    Total: 24 bytes / vertex

    The speedup is only milliseconds, it is not significant, I am simply releaved that the extra operations did not slow anything down :), the big win is memory.

    If I could use a different data type for vertex and uv, I could save even more memory. for uv and hue all my data would fit in 2 bytes and still have spare space, for vertex, all vertex coords are integers 0-32, so they would fit in 3 bytes and have plenty of bits to spare, but opengl won't do bytes for this, so the best I could hope for is 6 bytes.
     
  7. Deni35

    Deni35

    Joined:
    Jul 10, 2012
    Posts:
    43
    I think that Unity storage UV in 4 bytes. Also for storage normal, can use only x and y. z = 1-(x+y). For x also can use 2 bytes.
    If Unity really storage vertex position in 12 bytes, you can pack all your data to position.
     
  8. goldbug

    goldbug

    Joined:
    Oct 12, 2011
    Posts:
    684
    Would that not mess up frustum culling, and lod?
     
  9. Deni35

    Deni35

    Joined:
    Jul 10, 2012
    Posts:
    43
    If Mesh.bounds is readonly then yes. Else you can manually set bounds.
     
    Last edited: Jun 9, 2014
  10. babaji1234

    babaji1234

    Joined:
    May 3, 2013
    Posts:
    36
    that guy is pure awesomeness
     
  11. babaji1234

    babaji1234

    Joined:
    May 3, 2013
    Posts:
    36
    goldbug, I had thought exactly the same thing and while implementing multithreading in my own game i created a class which is an all in one class for colors,verts and uvs and sped up my game somewhat :/
     
  12. Windexglow2

    Windexglow2

    Joined:
    Sep 23, 2012
    Posts:
    90
    This is something I've been searching for for 3 hours now. How do I handle things like stairs, or fences? Namely, the rotation part. In minecraft you each rotate stairs in any direction, but I can't think of a way without literally having mesh data for each direction.

    For example, say I have a stair model. It is split into 6 arrays, 1 for each side containing the vertices. By default, it was made to face north.
    The player places the block, but facing east. How do I translate the mesh information for this?
     
  13. Ellandar

    Ellandar

    Joined:
    Jan 5, 2013
    Posts:
    207
    Hi All,

    I've released an alpha version of my water simulator that can add water to your terrains. It's very early days and I'm keen to hear feedback on what you think.

    The forum thread is here:
    Liquid Voxels

    Support and Ideas go here:
    LiquidVoxels Feedback and Support

    Couple of video's





    - Ell
     
  14. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    5,343
  15. jordantotty

    jordantotty

    Joined:
    Dec 15, 2011
    Posts:
    77
    Couple screenshots from in game :)

    Should be on the app stores shortly!


     

    Attached Files:

    Last edited: Jul 4, 2014
    magic9cube likes this.
  16. goldbug

    goldbug

    Joined:
    Oct 12, 2011
    Posts:
    684
    We have released version 9.0 in google play of block story, with villages and animal riding.

    We have made it free with IAP, lets see how that goes.
     
  17. Wiivan

    Wiivan

    Joined:
    Dec 17, 2013
    Posts:
    7
    hi @goldbug im trying to develop a game similar to yours for IOS but when i use byte[,,] arrays my apps crashes. In unity editor everything works fine but once I do a development build Xcode shows errors . If i use Int[,,] arrays everything works fine. Any idea? since mobile devices cannot handle too much memory?
     
  18. goldbug

    goldbug

    Joined:
    Oct 12, 2011
    Posts:
    684
    how big is your byte[,,]? are you seeing any exception on the xcode log console?
     
  19. Wiivan

    Wiivan

    Joined:
    Dec 17, 2013
    Posts:
    7
    sometimes i get EXC_BAD_ACCESS and sometimes "IndexOutOfRangeException: Array índex is out of range." But i run the same code with no modifications in unity editor. And everything works fine. I'm declaring my arrays with this code
    public byte[,,] data = new byte[128,128,128];
     
  20. goldbug

    goldbug

    Joined:
    Oct 12, 2011
    Posts:
    684
    I have seen similar issues with big arrays like yours. I don't really have a solution for you, I simply don't allocate such large arrays.
     
  21. Wiivan

    Wiivan

    Joined:
    Dec 17, 2013
    Posts:
    7
    if I use a int[128,128,128] everything works fine even on iOS Do you think there could be a problem with memory allocation? Have you tried 1D arrays?
     
    Last edited: Jul 5, 2014
  22. goldbug

    goldbug

    Joined:
    Oct 12, 2011
    Posts:
    684
    I have seen problems with 1D arrays too. If you could narrow down a simple scene that reproduces this problem, submit a bug to unity.

    It looks to me that unity allocates an array smaller than specified or something like that, because I can access the first elements, but I start getting trouble when accessing the last ones.

    Check the array size returned with .GetLength(0), .GetLength(1) and .GetLength(2) to see if they match what you specified.

    I never tried with int arrays, I tried with a small struct array and got this result.
     
  23. Foam

    Foam

    Joined:
    Jun 13, 2012
    Posts:
    322
    Take a look at http://loufranco.com/blog/understanding-exc_bad_access

    Are you bumping up against the memory limits? Is this occurring when one array is allocated or do you have 10s or hundreds or thousands floating around?

    Are you accessing the array from more than 1 thread?

    Is the error in manage Mono code (in the compiled binaries) or has Unity compiled that portion to native code?

    The issue with bytes is curious... Try defining an array of chars and see what happens. It's possible Unity is converting yout byte array to an int array (that is, a 1 byte int, int_least8_t) and screwing up somewhere. Last I checked ObjC doesn't have a real "byte" type in the usual sense of the word.
     
  24. Wiivan

    Wiivan

    Joined:
    Dec 17, 2013
    Posts:
    7
    I have done several tests with with bytes , shorts and ints. I seems Bytes[,,] and short[,,] doesnt work with iOS . Bytes[,] and short[,] does.
     
  25. Wiivan

    Wiivan

    Joined:
    Dec 17, 2013
    Posts:
    7
    I'm under the limit. I'm not accessing the array from other threads. it seems 3D arrays doesnt work with bytes and shorts.
     
  26. Foam

    Foam

    Joined:
    Jun 13, 2012
    Posts:
    322
    The default int on that architecture is 4 bytes, I believe, so it would make sense that byte and short would both have the same problem. That's encouraging for narrowing things down. You'd think the bug would have been reported long ago though.

    Did you isolate the code, whether Unity translated it to native code or managed IL? Try compiling that specific class or code to a mono DLL, add it to your project, remove the original source files from your project, and have unity compile it again. That could narrow down the bug pretty well. There's nothing in the mono runtime or specs that should cause this issue, either in the language specs or the garbage collector. Which is why you aren't seeing it in the Editor.

    Unless Unity translates IL code directly now during the compilation process? I dunno about that. I know its one of their goals for 5.0 so maybe they are doing it partially now?

    Try out the DLL test. You may not have to use your project, just create C# file with the array test, compile it manually to DLL, create a new Unity project, import the dll, and give it a go. Oh, and thrash it to see if the GC pukes.
     
    Last edited: Jul 8, 2014
  27. magic9cube

    magic9cube

    Joined:
    Jan 30, 2014
    Posts:
    58
    Last edited: Jul 11, 2014
  28. Wiivan

    Wiivan

    Joined:
    Dec 17, 2013
    Posts:
    7
    I havent tried to créate a DLL but what is currently working is using only 2D arrays they work with bytes and bytes. Hope Unity 5.0 has fixed that
     
  29. Michaelangel007

    Michaelangel007

    Joined:
    Jul 10, 2014
    Posts:
    1
    Nice optimization!

    Could you explain how many bits you are using for:

    * uv
    * hue
    * light
    * normal

    please?

    Assuming a texture atlas of 16 x 16 tiles is it possible to only use nibbles (4-bits) for u and (4-bits) v texture coordinates?

    TIA.
     
  30. goldbug

    goldbug

    Joined:
    Oct 12, 2011
    Posts:
    684
    UV -> 3 bits for u, 3 bits for v
    hue -> RGB (4 bits per channel)
    light -> RGBA (6 bit each channel, A is for sunlight)
    normal -> XYZ (2 bits each, don't really need that much, but it is fast to unpack)


    to your question: yes, if you have a 16x16 atlas, you can use 4 bits for u and 4 bits for v. In my case I have 8x8, so I only need 3 bits each.
     
  31. magic9cube

    magic9cube

    Joined:
    Jan 30, 2014
    Posts:
    58
    I'm trying to implement this myself (Thank you very much for posting this c# version) I'm trying to work out how i can determine which face is being processed so i can set the correct winding order for correct normals. Any expert minds out here that may shed some light on what exactly is going on in this and where can we find the specific face sides? There should only be 6 options here right?

    As experiment I've tried things like;

    Code (CSharp):
    1.  if (x[0] == 1 && q[0]==1) { AddFace(v1, v2, v3, v4, vertices, elements); }
    2.  if (x[0] == 0 && q[0]==1) { AddFace(v4, v3, v2, v1, vertices, elements); }
    3.  
    While i do see faces only from 1 side with some of these experiments, i don't see all of them. It seems a bit close but close is not good enough.. :)

    Cheers!

     
    Last edited: Jul 12, 2014
  32. magic9cube

    magic9cube

    Joined:
    Jan 30, 2014
    Posts:
    58
    I've found a nasty work around for this. I add an extra flipped face. It halves the benefit of the optimization. Hopefully i can find another option!
    Code (CSharp):
    1.   int index = vertices.Count;
    2.  
    3.         vertices.Add(v1);
    4.         vertices.Add(v2);
    5.         vertices.Add(v3);
    6.         vertices.Add(v4);
    7.  
    8.         elements.Add(index);
    9.         elements.Add(index + 1);
    10.         elements.Add(index + 2);
    11.         elements.Add(index + 2);
    12.         elements.Add(index + 3);
    13.         elements.Add(index);
    14.  
    15.         index = vertices.Count;
    16.  
    17.         vertices.Add(v4);
    18.         vertices.Add(v3);
    19.         vertices.Add(v2);
    20.         vertices.Add(v1);
    21.  
    22.         elements.Add(index);
    23.         elements.Add(index + 1);
    24.         elements.Add(index + 2);
    25.         elements.Add(index + 2);
    26.         elements.Add(index + 3);
    27.         elements.Add(index);
    my next idea is something like this to find the face;

    Code (CSharp):
    1.  if (v1.x == v2.x && v3.x == v4.x && v4.x == v1.x) {}
     
    Last edited: Jul 12, 2014
  33. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    Hello Everyone-

    I've been lurking in the shadows for a while now working on my own game with the help and guidance of a lot of the information I have found in this thread. I have come to a point where I have several questions though and I know this is the right place to ask from seeing some of the impressive things some of you have done.

    So the first question I have has to deal with a custom shader and a texture atlas.

    I have written a "working" shader that uses my texture atlas, but there are a couple issues.


    1) The code below works however there are white dots places, most of the time it is along a seams, not always. I know this has been mentioned before in this thread, though I either can not find the exact posts i was looking for, or i did find them, but there was no answer about how to fix this.

    Also, the textures just look .... bad the farther away from the camera they get. Im guessing this has something to do with the math going on to determine what pixel to pick from the texture atlas.... but im shooting in the dark there.

    I've uploaded a screenshot where you can see both issues. The white dots in this case happen not to be in the seems but on a particular section on the dirt. You can also see how the textures close to the camera are very nice looking, but the farther away you go it just looks awful. Is this just a product of the style of texture being used here, or does it have something to do with the math to pick which pixel of the image to use?


    screenshot.jpg

    2) The code below does not have it in there now, but it i set it up to be able to use transparent images for block faces, when you are playing the transparency SOMETIMES (not always, and with no discernible pattern as to where and why) shows you into the world instead of showing a mix of the transparent face, and the face of whatever you can see through it. Other times (most of the time), it works exactly as I would expect.

    Why is this? Previously I had transparencies and everything else in separate meshes to work around this issue, but I obviously don't like the idea of having two separate Meshes that i have to render per chunk just for the landscape.


    Code (CSharp):
    1. Shader "Custom/CustomShader" {
    2.     Properties {
    3.         _MainTex ("Base (RGB)", 2D) = "white" {}
    4.         _SecondTex ("Secondary (RGB)", 2D) = "white" {}
    5.  
    6.     }
    7.     SubShader {
    8.         Tags { "RenderType"="Opaque" }
    9.         PASS
    10.         {
    11.         CGPROGRAM
    12.         #pragma vertex vert
    13.         #pragma fragment frag
    14.         #include "UnityCG.cginc"
    15.        
    16.         sampler2D _MainTex;
    17.         sampler2D _SecondTex;
    18.        
    19.             struct vertexInput {
    20.                 float4 vertex : POSITION;
    21.                 float4 color    : COLOR;
    22.                 float3 normal    : NORMAL;
    23.                 float2 texcoord0 : TEXCOORD0;
    24.                 float2 texcoord1 : TEXCOORD1;
    25.             };
    26.            
    27.             struct vert2frag{
    28.                 float4 pos : SV_POSITION;
    29.                 float4 color: COLOR;
    30.                 float3 normal :TEXCOORD3;
    31.                 float2 uv : TEXCOORD0;
    32.                 float2 uv2 : TEXCOORD1;
    33.                 float4 wPos : TEXCOORD2;
    34.                
    35.             };
    36.        
    37.         vert2frag vert(vertexInput i)
    38.         {
    39.             vert2frag OUT;
    40.             OUT.pos = mul (UNITY_MATRIX_MVP, i.vertex);
    41.             OUT.wPos = mul (_Object2World, i.vertex);
    42.             OUT.color = i.color;
    43.             OUT.uv = i.texcoord0;
    44.             OUT.uv2 = i.texcoord1;
    45.             OUT.normal = i.normal;
    46.          
    47.             return OUT;
    48.         }
    49.  
    50.         float4 frag (vert2frag i) : COLOR {
    51.        
    52.             float4 outcolor = float4(.5,.5,.5,1);
    53.             float4 ocolor = float4(0,0,0,0);
    54.             float2 uvs = float2(0,0);
    55.              
    56.             i.wPos /= i.wPos.w;
    57.            
    58.             i.uv = floor(i.uv  / .125f) * .125f ;
    59.            
    60.             i.wPos = fmod(abs(i.wPos), 1) / 8;
    61.            
    62.             uvs.x = i.wPos.x;
    63.             uvs.y = i.wPos.y;
    64.            
    65.             if ((i.normal.y == 1) || (i.normal.y == -1))
    66.             {
    67.                 uvs.x = i.wPos.x;
    68.                 uvs.y = i.wPos.z;
    69.             }
    70.             if ((i.normal.x == 1) || (i.normal.x == -1))
    71.             {
    72.                 uvs.x = i.wPos.z;
    73.                 uvs.y = i.wPos.y;
    74.             }
    75.            
    76.             if ((i.normal.z == 1) || (i.normal.z == -1))
    77.             {
    78.                 uvs.x = i.wPos.x;
    79.                 uvs.y = i.wPos.y;
    80.             }          
    81.            
    82.            
    83.               outcolor = tex2D(_MainTex, float2(  uvs + i.uv ) );
    84.               outcolor *= i.color ;
    85.              
    86.               return outcolor;
    87.            
    88.         }
    89.        
    90.  
    91.         ENDCG
    92.         }
    93.        
    94.     }
    95.     Fallback "VertexLit"
    96. }
    97.  
    So please do not feel the need to spare my feelings when asking anything about the code in my shader. I have never written, or dealt with shaders in any way shape or form before my attempt at doing this and I am sure there are things I could of done better, or are just plain wrong but work somehow.

    Ive looked all over and was unable to find an existing shader, example, or tutorial explaining how to properly use a texture atlas and then map it to the object. So i figure at very least this will give someone else somewhere to start if nothing else.

    My Texture Atlas is 8x8 of tiles that are 64x64 pixels each.

    This shader also supports tinting the tile with a color you pass in to the shader.

    Ideally I would like to have a single shader that fixes the problems of the pixels and looking bad at a distance, and also supports the transparency of tiles properly.

    Thanks,

    Jason
     
  34. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    7,096
  35. Vanamerax

    Vanamerax

    Joined:
    Jan 12, 2012
    Posts:
    818
    Those white dots seem to be appearing at the cube seams, this is probably due to the fact that you are not 'welding' your vertices (eg. multiple triangles are not sharing the same vertices, but create their own vertices at the exact same position) this can give some rendering errors due to floating point precision. You could try to change your algorythm so you are sharing the vertices, but it might make it a little more complex. If you get it to work, it would also reduce memory usage (by the meshes, due to the simple fact that you have less vertices to store) and are less likely to hit the 65k vertices limit per chunk.

    Textures looking bad at further distances is probably because either:
    - you are not using mipmaps, mipmaps are used to smooth out the textures at further distances, giving overall a better look
    - you are using mipmaps but the pixels from the different tiles in the atlas are blurring into each other. This is called 'pixel bleeding' and has indeed been discussed several times in this thread. I'd suggest to look it up on google, but there is no 'real' solution to this as far as I know. Try playing with the texture settings, or making some 'spare room' between your tile sets, so the pixels dont bleed into their neighbouring tiles as quickly
     
  36. kenlem

    kenlem

    Joined:
    Oct 16, 2008
    Posts:
    1,611
    I gave up but seeing your post made me think. If iterating though the voxels one way gives you 3 of the 6 required faces, won't iterating in the reverse order give you the other 3 faces?


     
  37. Dave-xP

    Dave-xP

    Joined:
    Nov 8, 2013
    Posts:
    106
    Hello, I was addicted to minecraft before I started making games with unity.
    I have been reading this thread for a few days and i came up with this...
    upload_2014-7-14_1-12-47.png
    but i am having one problem and that are these white dots between the block faces Capture214.png
    Can someone please tell me how to make them gone.
    Thank you all!
     
    Last edited: Jul 14, 2014
  38. shadbags

    shadbags

    Joined:
    Jul 14, 2014
    Posts:
    5
    Look literally 2 posts earlier. Or Google would have explained the issue.
     
  39. magic9cube

    magic9cube

    Joined:
    Jan 30, 2014
    Posts:
    58
    From what i can tell it builds all faces found on each 3 dimensional sweeps in batch for each of the 3 sweeps. There is no guarantee a face on one side of a dimensional sweep is matched with an opposing face, so its impossible to detect this way i think.

    I did find another version of the original code in which Mikola addressed the normal and materials issue; However, I'm not sure i can translate this to c# to test it. It uses a nested javascript function which has me a bit stuck for the moment. But this version may hold the key and i will look into it further. Lets get this working and share it! :)

    Code (CSharp):
    1. // The MIT License (MIT)
    2. //
    3. // Copyright (c) 2012-2013 Mikola Lysenko
    4. //
    5. // Permission is hereby granted, free of charge, to any person obtaining a copy
    6. // of this software and associated documentation files (the "Software"), to deal
    7. // in the Software without restriction, including without limitation the rights
    8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    9. // copies of the Software, and to permit persons to whom the Software is
    10. // furnished to do so, subject to the following conditions:
    11. //
    12. // The above copyright notice and this permission notice shall be included in
    13. // all copies or substantial portions of the Software.
    14. //
    15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    21. // THE SOFTWARE.
    22.  
    23.  
    24. var GreedyMesh = (function() {
    25. //Cache buffer internally
    26. var mask = new Int32Array(4096);
    27.  
    28. return function(volume, dims) {
    29.   function f(i,j,k) {
    30.     return volume[i + dims[0] * (j + dims[1] * k)];
    31.   }
    32.   //Sweep over 3-axes
    33.   var vertices = [], faces = [];
    34.   for(var d=0; d<3; ++d) {
    35.     var i, j, k, l, w, h
    36.       , u = (d+1)%3
    37.       , v = (d+2)%3
    38.       , x = [0,0,0]
    39.       , q = [0,0,0];
    40.     if(mask.length < dims[u] * dims[v]) {
    41.       mask = new Int32Array(dims[u] * dims[v]);
    42.     }
    43.     q[d] = 1;
    44.     for(x[d]=-1; x[d]<dims[d]; ) {
    45.       //Compute mask
    46.       var n = 0;
    47.       for(x[v]=0; x[v]<dims[v]; ++x[v])
    48.       for(x[u]=0; x[u]<dims[u]; ++x[u], ++n) {
    49.         var a = (0    <= x[d]      ? f(x[0],      x[1],      x[2])      : 0)
    50.           , b = (x[d] <  dims[d]-1 ? f(x[0]+q[0], x[1]+q[1], x[2]+q[2]) : 0);
    51.         if((!!a) === (!!b) ) {
    52.           mask[n] = 0;
    53.         } else if(!!a) {
    54.           mask[n] = a;
    55.         } else {
    56.           mask[n] = -b;
    57.         }
    58.       }
    59.       //Increment x[d]
    60.       ++x[d];
    61.       //Generate mesh for mask using lexicographic ordering
    62.       n = 0;
    63.       for(j=0; j<dims[v]; ++j)
    64.       for(i=0; i<dims[u]; ) {
    65.         var c = mask[n];
    66.         if(!!c) {
    67.           //Compute width
    68.           for(w=1; c === mask[n+w] && i+w<dims[u]; ++w) {
    69.           }
    70.           //Compute height (this is slightly awkward
    71.           var done = false;
    72.           for(h=1; j+h<dims[v]; ++h) {
    73.             for(k=0; k<w; ++k) {
    74.               if(c !== mask[n+k+h*dims[u]]) {
    75.                 done = true;
    76.                 break;
    77.               }
    78.             }
    79.             if(done) {
    80.               break;
    81.             }
    82.           }
    83.           //Add quad
    84.           x[u] = i;  x[v] = j;
    85.           var du = [0,0,0]
    86.             , dv = [0,0,0];
    87.           if(c > 0) {
    88.             dv[v] = h;
    89.             du[u] = w;
    90.           } else {
    91.             c = -c;
    92.             du[v] = h;
    93.             dv[u] = w;
    94.           }
    95.           var vertex_count = vertices.length;
    96.           vertices.push([x[0],             x[1],             x[2]            ]);
    97.           vertices.push([x[0]+du[0],       x[1]+du[1],       x[2]+du[2]      ]);
    98.           vertices.push([x[0]+du[0]+dv[0], x[1]+du[1]+dv[1], x[2]+du[2]+dv[2]]);
    99.           vertices.push([x[0]      +dv[0], x[1]      +dv[1], x[2]      +dv[2]]);
    100.           faces.push([vertex_count, vertex_count+1, vertex_count+2, vertex_count+3, c]);
    101.  
    102.           //Zero-out mask
    103.           for(l=0; l<h; ++l)
    104.           for(k=0; k<w; ++k) {
    105.             mask[n+k+l*dims[u]] = 0;
    106.           }
    107.           //Increment counters and continue
    108.           i += w; n += w;
    109.         } else {
    110.           ++i;    ++n;
    111.         }
    112.       }
    113.     }
    114.   }
    115.   return { vertices:vertices, faces:faces };
    116. }
    117. })();
    118.  
    119. if(exports) {
    120.   exports.mesher = GreedyMesh;
    121. }
    Using the integer array mask in place of the bool array i guess allows for that extra data.

    [edit]

    I think i'm past the nested function thing now up to;
    Code (JavaScript):
    1.   if((!!a) === (!!b) ) {
    2.           mask[n] = 0;
    3.         } else if(!!a) {
    4.           mask[n] = a;
    5.         } else {
    6.           mask[n] = -b;
    7.         }
    It's very elegant code but I'm not really sure what the logic is there.

    I will try something like this;

    Code (CSharp):
    1.  if (a > -1 && b > -1 && a == b) { mask[n] = 0; }
    2.  
    3.                         else if (a > -1)
    4.                         {
    5.                             mask[n] = a;
    6.                         }
    7.                         else
    8.                         {
    9.                             mask[n] = -b;
    10.                         }
    [edit]

    ok, i have _something_ working. i wont say it's 100% but it's at least showing all sides now!

    meshopt.jpg
     
    Last edited: Jul 14, 2014
  40. magic9cube

    magic9cube

    Joined:
    Jan 30, 2014
    Posts:
    58
    Here's what i have so far;

    Code (CSharp):
    1. // The MIT License (MIT)
    2.     //
    3.     // Copyright (c) 2012-2013 Mikola Lysenko
    4.     //
    5.     // Permission is hereby granted, free of charge, to any person obtaining a copy
    6.     // of this software and associated documentation files (the "Software"), to deal
    7.     // in the Software without restriction, including without limitation the rights
    8.     // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    9.     // copies of the Software, and to permit persons to whom the Software is
    10.     // furnished to do so, subject to the following conditions:
    11.     //
    12.     // The above copyright notice and this permission notice shall be included in
    13.     // all copies or substantial portions of the Software.
    14.     //
    15.     // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    16.     // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    17.     // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    18.     // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    19.     // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    20.     // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    21.     // THE SOFTWARE.
    22.  
    23.  
    24.     private Mesh ReduceMesh(Chunk chunk)
    25.     {
    26.  
    27.         List<Vector3> vertices = new List<Vector3>();
    28.         List<int> elements = new List<int>();
    29.  
    30.         int size = World.CHUNK_SIZE;
    31.  
    32.         //Sweep over 3-axes
    33.         for (int d = 0; d < 3; d++)
    34.         {
    35.  
    36.             int i, j, k, l, w, h, u = (d + 1) % 3, v = (d + 2) % 3;
    37.  
    38.             int[] x = new int[3];
    39.             int[] q = new int[3];
    40.  
    41.          //   bool[] mask = new bool[size * size];
    42.             int[] mask = new int[size*size*size];
    43.  
    44.             q[d] = 1;
    45.  
    46.  
    47.  
    48.             for (x[d] = -1; x[d] < size; )
    49.             {
    50.  
    51.                 // Compute the mask
    52.                 int n = 0;
    53.                 for (x[v] = 0; x[v] < size; ++x[v])
    54.                 {
    55.                     for (x[u] = 0; x[u] < size; ++x[u], ++n)
    56.                     {
    57.  
    58.  
    59.                         int a = (0 <= x[d] ? data(chunk, x[0], x[1], x[2]) : 0), b = (x[d] < size - 1 ? data(chunk, x[0] + q[0], x[1] + q[1], x[2] + q[2]) : 0);
    60.  
    61.  
    62.                         if (a !=-1 && b !=-1 && a == b) { mask[n] = 0; }
    63.  
    64.                         else if (a > 0)
    65.                         {
    66.                             mask[n] = a;
    67.                         }
    68.                         else
    69.                         {
    70.                             mask[n] = -b;
    71.                         }
    72.                     }
    73.                 }
    74.  
    75.                 // Increment x[d]
    76.                 ++x[d];
    77.  
    78.                 // Generate mesh for mask using lexicographic ordering
    79.                 n = 0;
    80.                 for (j = 0; j < size; ++j)
    81.                 {
    82.                     for (i = 0; i < size; )
    83.                     {
    84.  
    85.                         var c = mask[n];
    86.  
    87.                         if (c>-2)
    88.                         {
    89.                             // Compute width
    90.                             for (w = 1; c == mask[n + w] && i + w < size; ++w) { }
    91.  
    92.                             // Compute height (this is slightly awkward
    93.                             bool done = false;
    94.                             for (h = 1; j + h < size; ++h)
    95.                             {
    96.                                 for (k = 0; k < w; ++k)
    97.                                 {
    98.                                     if (c != mask[n + k + h * size])
    99.                                     {
    100.                                         done = true;
    101.                                         break;
    102.                                     }
    103.                                 }
    104.  
    105.                                 if (done) break;
    106.                             }
    107.  
    108.                             // Add quad
    109.                             bool flip = false;
    110.  
    111.                             x[u] = i;
    112.                             x[v] = j;
    113.                             int[] du = new int[3];
    114.                             int[] dv = new int[3];
    115.  
    116.                             if(c>-1)
    117.                             {
    118.                                 du[u] = w;
    119.                                 dv[v] = h;
    120.                             }
    121.                             else{
    122.                                 flip=true;
    123.                                 c = -c;
    124.                                 du[u] = w;
    125.                                 dv[v] = h;
    126.  
    127.                             }
    128.                      
    129.  
    130.                             Vector3 v1 = new Vector3(x[0], x[1], x[2]);
    131.                             Vector3 v2 = new Vector3(x[0] + du[0], x[1] + du[1], x[2] + du[2]);
    132.                             Vector3 v3 = new Vector3(x[0] + du[0] + dv[0], x[1] + du[1] + dv[1], x[2] + du[2] + dv[2]);
    133.                             Vector3 v4 = new Vector3(x[0] + dv[0], x[1] + dv[1], x[2] + dv[2]);
    134.  
    135.                             bool floor =false;
    136.  
    137.                             if (v1.y == 0 && v2.y == 0 && v3.y == 0 && v4.y == v1.y) { floor = true; }
    138.  
    139.                             if (c ==1&&!floor)
    140.                             {
    141.                              AddFace(v1, v2, v3, v4, vertices, elements);
    142.                             }
    143.  
    144.                             if (flip) {                          
    145.                                 AddFace(v4, v3, v2, v1, vertices, elements);                      
    146.                             }
    147.  
    148.                             // Zero-out mask
    149.                             for (l = 0; l < h; ++l)
    150.                                 for (k = 0; k < w; ++k)
    151.                                 {
    152.                                     mask[n + k + l * size] = 0;
    153.                                 }
    154.  
    155.                             // Increment counters and continue
    156.                             i += w; n += w;
    157.                         }
    158.  
    159.                         else
    160.                         {
    161.                             ++i;
    162.                             ++n;
    163.                         }
    164.                     }
    165.                 }
    166.             }
    167.         }
    168.  
    169.         Mesh mesh = new Mesh();
    170.         mesh.Clear();
    171.         mesh.vertices = vertices.ToArray();
    172.         mesh.triangles = elements.ToArray();
    173.  
    174.         mesh.RecalculateBounds();
    175.         mesh.RecalculateNormals();
    176.  
    177.         return mesh;
    178.  
    179.     }
    180.  
    181.  
    182.     private  void AddFace(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, List<Vector3> vertices, List<int> elements)
    183.     {
    184.         int index = vertices.Count;
    185.  
    186.         vertices.Add(v1);
    187.         vertices.Add(v2);
    188.         vertices.Add(v3);
    189.         vertices.Add(v4);
    190.  
    191.         elements.Add(index);
    192.         elements.Add(index + 1);
    193.         elements.Add(index + 2);
    194.         elements.Add(index + 2);
    195.         elements.Add(index + 3);
    196.         elements.Add(index);
    197.  
    198.     }
    199.  
    200.  
    201.     private  int data(Chunk chunk, int x, int y, int z)
    202.     {
    203.         //return voxelData[x + 32 * y + 32 * 32 * z] != 0;
    204.         int b = (int)chunk.blocks[x, y, z].blockType;
    205.         if (b > 1) { b = 1; }
    206.         return b;
    207.     }
    ..beyond any problems with this code, the next step i guess is uvs.

    [edit]
    This also worked for me;
    Code (CSharp):
    1.  int[] mask = new int[(size + 1) * (size + 1)];
    So perhaps you can have a smaller array.
     
    Last edited: Jul 14, 2014
    jordantotty likes this.
  41. kenlem

    kenlem

    Joined:
    Oct 16, 2008
    Posts:
    1,611

    That's awesome! I'll have a look at lunch today. As I was only concerned with optimizing my colliders, I hadn't even though about UV's.

    Of course, the fastest way to do collision is to keep a pool of cube colliders around and move them into place around characters as they move. That way you don't end up creating and destroying objects at runtime.
     
  42. magic9cube

    magic9cube

    Joined:
    Jan 30, 2014
    Posts:
    58
    That's an excellent point. I guess most games would never need more than that.

    I think i got material separation on the above code working anyway. very simple, its all in that integer array. just keep the actual value for the block type/material id until you draw the triangles.

    mats.jpg

    [edit]

    It looks like this will need a shader that can tile a texture atlas. If anyone can help out with that i'd appreciate it!

    I've found this but i'm not sure how to implement it;
    http://answers.unity3d.com/questions/214837/is-possible-to-tile-within-a-texture-atlas.html

    mats2.jpg
     
    Last edited: Jul 15, 2014
  43. Neurological

    Neurological

    Joined:
    Jun 25, 2012
    Posts:
    350
    I have a question for you guys that managed to pull out a collision system not bound to real physics. I'm trying to steer away from using physics as I don't need them that much and would like to save some performance for other stuff.

    I saw some of you talking about AABB and OBB collision, I researched some stuff but I'm still a bit clueless on how to proceed on unity, especially for one thing, how to reference a bounding box of another object or multiple objects touching it, do you guys have some suggestions for where to start looking?

    Mind that I'm not asking for any code, I would like just to learn myself but need some point to start that isn't too generic, most of the info I found is on 2D, would like something to study on instersections in 3D.

    Thanks for your time.
     
  44. goldbug

    goldbug

    Joined:
    Oct 12, 2011
    Posts:
    684
    Here is a fairly simple approach to get started:
    Create a AABBCollider component, this will hold a min and max points, which will define your bounding box relative to the center of the mob. AABB means Axis aligned bounding box, it does not matter what rotations have been applied to the character, the box can be fully defined by these 2 points.

    so for example, min: (-0.5,-1,-0.5) max: (0.5,1,0.5), then lets say your character is at point (10, 2, 20), then the bounding box for your character will be: (9.5, 1, 19.5) - (10.5, 3, 20.5). To know which voxels you are intersecting, you can calculate the floor (don't cast to int) for each coordinate, leaving you with: (9,1,19) - (10,3,20) then you loop through all those voxels (inclusive) and test if any of them is solid.

    That is a simple brute force method to test if you are overlapping a solid block. Works just fine for small mobs. It assumes your voxels are at integer coordinates.

    It gets a bit more complicated when you want to clip movement, so for example walk along a wall, or fall and have the terrain stop you. You can read about AABB SAP (sweep and prune).
     
  45. kenlem

    kenlem

    Joined:
    Oct 16, 2008
    Posts:
    1,611
    You're made some great progress here. I really only need the collider optimized and not the mesh used for display. I put ambient occlusion lighting in the vertices so I wouldn't want to lose them. I suppose you could join polys based on texture and ambient values but I'm not really sure that there will be much of a speed increase to do so.

    Are you profiling you changes to see what kind of impact they have? Do you know you really need to do this extra work?

     
  46. Neurological

    Neurological

    Joined:
    Jun 25, 2012
    Posts:
    350
    Thanks for the info, my main problem is that I'm not working with blocks of definite sizes, but different sizes of geometry, think of Doom 1 or 2. So since I can't do like in those games I mentioned without the complicate math to know how far I'm in each grid plane which is of varied size and I would need to hold too much info for each inch, I was thinking to add fake colliders that doesn't calculate physics but are just there to know if I'm going to hit on something and do the obivious calculations.

    I was reading some pages back about your Blockstory game and that you didn't use collision, not sure now if is the same, but how much often you would test against bounding boxes considering that also enemies does the same I guess could be an expensive operation for many characters at the same time.
     
  47. goldbug

    goldbug

    Joined:
    Oct 12, 2011
    Posts:
    684
    I invented my own algorithm for collision with the terrain, after finding some performance issues with AABB with bigger mobs. It takes advantage of the fact that all blocks are of the same size. My algorithm only does actual work when the player crosses a voxel boundary, and only for the voxels it is entering, this allowed me to have much bigger mobs without destroying FPS.

    I am for now using regular unity physics for collision between mobs, but I plan on implementing a SAP for this, since physics is showing in the profiler as one of the main bottlenecks. If I understand your requirements right, you don't have a evenly spaced grid, but you do have axis aligned boxes, so this is most likely what you need.

    http://www.codercorner.com/SAP.pdf
     
  48. Neurological

    Neurological

    Joined:
    Jun 25, 2012
    Posts:
    350
    Thanks that doc seems to cover what I was looking for, will be an interesting read.
     
  49. magic9cube

    magic9cube

    Joined:
    Jan 30, 2014
    Posts:
    58
    Only the collision side of things and that shows good improvement over non optimization but your suggested method would be miles ahead again.Though i do wonder how it handles many mobs? I think you're right that any speed increase on mesh rendering is going to be minimal. I may try using the data in other ways though, perhaps with RLE and reducing iteration times.
     
  50. goldbug

    goldbug

    Joined:
    Oct 12, 2011
    Posts:
    684
    If you plan to have ambient occlusion or light, then you need to make sure to take it into account when merging blocks.

    Here is a screenshot from block story showing block merging. This is not the collider (there are no colliders here), this is the rendered mesh
    blockmerge.PNG