Thread: 3D Array of Bool

  1. #16
    Registered User
    Join Date
    Jun 2007
    Posts
    30
    Quote Originally Posted by KIBO View Post
    Why do you need 10^9 bools anyway?
    It is a matrix that represents a 3D space. If that point is true, that means something is on that space. Any better idea than using a matrix? Speed is very important.

  2. #17
    Ethernal Noob
    Join Date
    Nov 2001
    Posts
    1,901
    Code:
    struct point3D
    {  
       int x;
       int y;
       int z;
    };
    it works for OpenGL .

  3. #18
    Registered User
    Join Date
    Jun 2007
    Posts
    30
    Quote Originally Posted by indigo0086 View Post
    Code:
    struct point3D
    {  
       int x;
       int y;
       int z;
    };
    it works for OpenGL .
    I was thinking to let my program only represent points that exist in the 3D space, since there are many more slots than the number of the points in the 3D space. However, if I declare a struct like above, it seems that I would lose the ability to check if a particular point in the 3D space has any neighbors in the space, since the indices of the struct provide no clue about the spatial relationships of the points.

    If I group the points in a more complicated data structure like a tree, the speed is not as fast as a 3D array.
    Last edited by cybernike; 06-27-2007 at 08:31 AM.

  4. #19
    Ethernal Noob
    Join Date
    Nov 2001
    Posts
    1,901
    Well, in your 3d array to find a neighbor "near" a point you would have to specify some sort of spherical radius around the point to find the neighbor. If you put a bunch of point3D's in an array or vector, you can simply search the array to find points that lie within the specified radius of one point. With the 3d array you would just have to calculate indexes, but you take up much more space.

  5. #20
    Registered User
    Join Date
    Jun 2007
    Posts
    30
    Quote Originally Posted by indigo0086 View Post
    Well, in your 3d array to find a neighbor "near" a point you would have to specify some sort of spherical radius around the point to find the neighbor. If you put a bunch of point3D's in an array or vector, you can simply search the array to find points that lie within the specified radius of one point. With the 3d array you would just have to calculate indexes, but you take up much more space.
    With what you said, let the radius be 1.
    I'd like to know if a point with coordinates (1,1,1) has any particles right next to it. I would have to check if any particle would have the coordinates (0,1,1), (2,1,1), (1,0,1), (1,2,1), (1,1,0), or (1,1,2). The trouble is I would probably have to look through the whole array of struct to see which particle has such coordinates, unless there is some kind of sorting that tells me which particles are closest to the particle that I am interested; that would slow things down quite a bit.

  6. #21
    Ethernal Noob
    Join Date
    Nov 2001
    Posts
    1,901
    But which tradeoff is larger, doing a search for a few points through a vector that most likely won't reach 1000x1000x1000 point3D's in size, or always have a 1000x1000x1000x8-bit sized array no matter how many points you may have. What if you want to represent a larger area in space?

    Pllus your search would most likely be short circuit execution. If one arameter is not within the boundary you would ignore the entire entry. Still slow but the alternative is having a large file.

    Also, how are you going to refer to these points in 3d space with an array?

  7. #22
    Amazingly beautiful user.
    Join Date
    Jul 2005
    Location
    If you knew I'd have to kill you
    Posts
    254
    If you simply store the points that have something, you can organize them into a tree, therefore allowing reasonable (log n) search time, but saving massive amounts of memory.
    Programming Your Mom. http://www.dandongs.com/

  8. #23
    Registered User
    Join Date
    Jun 2007
    Posts
    30
    Quote Originally Posted by indigo0086 View Post
    But which tradeoff is larger, doing a search for a few points through a vector that most likely won't reach 1000x1000x1000 point3D's in size, or always have a 1000x1000x1000x8-bit sized array no matter how many points you may have. What if you want to represent a larger area in space?
    Pllus your search would most likely be short circuit execution. If one arameter is not within the boundary you would ignore the entire entry. Still slow but the alternative is having a large file.
    Doing a search for a few points through a vector? why only a few points? do you mean you have done some kind of sorting that would tell us the nearest neighbors of a particular particle?
    I really can't sacrifice any speed since my fully implemented program with about 1000 particles in a 1000x1000x1000 space would require a whole week to finish the simulations of the trajectories of the particles.



    Quote Originally Posted by indigo0086 View Post
    Also, how are you going to refer to these points in 3d space with an array?
    I don't really care which point is which; I only care if a particle has any neighbors right next to it, so I would check the truth values of the 6 sets of coordinates that are next to the particle interested.
    Last edited by cybernike; 06-27-2007 at 11:03 AM.

  9. #24
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    but then somewhere you are still generating/storing a list of particles to check, unless you intend to check every particle location, in which case that check will take far longer than just having a list of particles that do exist and running a distance check with every other particle to check for proximity. There are optimizations for checking locality that are much faster than calculating the geometric distance, check out some good books on game programming, they usually have an entire chapter on collision detection, which deals heavily with proximity of objects.

    In any case, you either have to put up with having a huge memory requirement, or having a huge processing requirement. The choice is up to you, there is no magical third choice.

    With only 1000 particles, I dont see how ANY calculation of trajectories would take a whole week. Perhaps you could elaborate on exactly what you are calculating.
    Last edited by abachler; 06-27-2007 at 12:12 PM.

  10. #25
    Registered User
    Join Date
    Jun 2007
    Posts
    30
    Quote Originally Posted by abachler View Post
    but then somewhere you are still generating/storing a list of particles to check, unless you intend to check every particle location, in which case that check will take far longer than just having a list of particles that do exist and running a distance check with every other particle to check for proximity. There are optimizations for checking locality that are much faster than calculating the geometric distance, check out some good books on game programming, they usually have an entire chapter on collision detection, which deals heavily with proximity of objects..
    Thanks, I will definitely try to get some ideas from game programming.
    Quote Originally Posted by abachler View Post
    In any case, you either have to put up with having a huge memory requirement, or having a huge processing requirement. The choice is up to you, there is no magical third choice.
    If I have to choose between memory and speed, speed is definitely more important.
    Quote Originally Posted by abachler View Post
    With only 1000 particles, I dont see how ANY calculation of trajectories would take a whole week. Perhaps you could elaborate on exactly what you are calculating.
    I have not specified the time scale; in each time unit, there are about 6*1000 jumps of the particles. In each simulation run, there are about 2^22 time units. So there are about 6*1000*2^22 hops. Also, I need to at least run the simulation for 5 to 10 times to get an average. Therefore, there are many many many calculations, even though each calculation may not be too complicated. I haven't even mentioned the data analysis in the program.

  11. #26
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Voxel data can easily be represented by a 4D vector.

    Code:
    struct Voxel
    {
      float cx;  //center X
      float cy;  //center Y
      float cz;  //center Z
      float size; //size of voxel
    };
    
    Voxel *pVoxelData=new Voxel[size];
    Your voxel extents are:

    cx-size,cy-size,cz-size
    cx+size,cy+size,cz+size

    In a 3D game you would frustum cull based on this diagonal and test against the frustum, or you could do a more expensive six plane test. It would not be a good idea to cull at the voxel level and perhaps a quad tree voxel system would work best. Those voxels that fall within a certain volume of space would be calculated. So you would have sections of voxels or, if you will, larger voxels containing sub-voxel data.

    Code:
    #define QTREE_ROOT 1
    #define QTREE_NODE 2
    #define QTREE_LEAF 3
    
    struct Vector3
    {
      float x;
      float y;
      float z;
    };
    
    struct VoxelQuadTree
    {
      std::vector<Voxel *> pVoxels;      //list of voxels belonging to this voxel
      int iType;    //Is this the root, a node, or a leaf?
      Vector3 Max;  //Max Extents of this volume - for bounds check
      Vector3 Min;   //Min Extents of this volume
      VoxelQuadTree *pUpperLeft;    //Upper left neighbor
      VoxelQuadTree *pUpperRight;  //Upper right neighbor
      VoxelQuadTree *pLowerLeft;   //Lower left neighbor
      VoxelQuadTree *pLowerRight;   //Lower right neighbor
    };
    Keep in mind if the voxel position data does not change and therefore will never cross a quad-tree boundary, you can use an array instead of std::vector. This looks like a 2D tree but it is actually a volumetric quad-tree structure.

    Rules for frustum culling:
    • If current node is out, all of the node's neighbors are too and do not need to be checked. The entire node and all it's associated neighbors can be discarded.
    • If current node is in, all of the node's neighbors are also in and do not need to be checked. The entire node and all it's neighbors can be added to a render list or update list.
    • If current node is partially in, you must check all of it's neighbors to also see if they are in or out. Check until you get all in or all out.
    • Do not worry about sub-voxels that may be partially in and partially out. Cull at the voxel volume level and not at the sub-voxel level.


    With an approach like this you could eliminate hundreds or thousands of voxels in about 2 recursions through the tree.

    Whatever way you approach it what we are all saying is there is a much better way to store your data in memory than what you have chosen.
    Last edited by VirtualAce; 06-27-2007 at 11:48 PM.

  12. #27
    Registered User
    Join Date
    Jun 2007
    Posts
    30
    Quote Originally Posted by Bubba View Post
    Voxel data can easily be represented by a 4D vector.

    Code:
    struct Voxel
    {
      float cx;  //center X
      float cy;  //center Y
      float cz;  //center Z
      float size; //size of voxel
    };
    
    Voxel *pVoxelData=new Voxel[size];
    Your voxel extents are:

    cx-size,cy-size,cz-size
    cx+size,cy+size,cz+size

    In a 3D game you would frustum cull based on this diagonal and test against the frustum, or you could do a more expensive six plane test.

    Either way you approach it what we are all saying is there is a much better way to store your data in memory than what you have chosen.
    Let me state the problem more clearly. In a 1000x1000x1000 space, there are 1000 particles. We can only move one particle at a time, and the particle can move in one of the six directions by 1 unit as long as it is not blocked by the other particles.

    I am sure there are more efficient ways to represent the data in terms of space.
    However, please let me ask your opinion on this. Is there any other way that is faster or as fast as using a 3D-matrix to determine if a move is allowed. As I said, I wouldn't want to sacrifice any speed.

  13. #28
    Kiss the monkey. CodeMonkey's Avatar
    Join Date
    Sep 2001
    Posts
    937
    Let me state the problem more clearly. In a 1000x1000x1000 space, there are 1000 particles.
    Think again.
    "If you tell the truth, you don't have to remember anything"
    -Mark Twain

  14. #29
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    If you only have 1000 particles you do not need a 1000x1000x1000 array to represent them. An array of 1000 vertices or particles will suffice. You can do a sphere check to see if the particles can move or not. But you don't want to test each of the 1000 particles against all 999 other particles to do the movement. You will need some type of spatial partitioning system. It does not make sense to test whether particle 1 comes into contact with particle 999 if particle 1 is thousands of units away from particle 999. It also does not make sense to test particles colliding if they are not moving, or if they are not moving toward each other. Two particles that are moving away from each other will never collide and therefore testing whether they will or not is a waste of time.

    You can use this sphere test:

    Code:
    bool SphereTest(Vector3 vec1,Vector3 vec2,float fDistSquared)
    {
      float diffx=vec1.x-vec2.x;
      float diffy=vec1.y-vec2.y;
      float diffz=vec1.z-vec2.z;
    
      float diffx2=diffx*diffx;
      float diffy2=diffy*diffy;
      float diffz2=diffz*diffz;
    
      float fTotalDistSquared=diffx2+diffy2+diffz2;
      if (fTotalDistSquared<fDistSquared)
      {
         //We have a proximity hit
         return true;
      } else return false;
    }
    To determine if two particles are heading towards or away from one another you can compute the dot product of the two velocity vectors. You only need to worry about the sign of the result. You do not need to worry about normalizing the vectors here because the sign will not be affected.

    Code:
    float DotProduct(Vector3 vec1,Vector3 vec2)
    {
      return ((vec1.x*vec2.x)+(vec1.y*vec2.y)+(vec1.z*vec2.z));
    }
    Result is:
    • >0 - Vectors are basically pointing in same direction
    • =0 - Vectors are perpendicular
    • <0 - Vectors are basically pointing in opposite directions


    To further illustrate the dot product here is a Java app I found. Just follow the instructions on the page.
    http://www.falstad.com/dotproduct/
    Last edited by VirtualAce; 06-28-2007 at 12:37 AM.

  15. #30
    l'Anziano DavidP's Avatar
    Join Date
    Aug 2001
    Location
    Plano, Texas, United States
    Posts
    2,743
    It is true that using a 1000x1000x1000 matrix will give you a general O(1) algorithm, because you will have direct indexing, which of course is blazingly fast. We all know that, and we are not denying that.

    What many people before me are saying, and what I am about to say, is that there are better ways to do it that use much less memory, and are still very very fast, even if they don't qualify as O(1). How do you think advanced games such as Doom 3, Quake 4, or HalfLife would do this kind of thing? They certainly don't store a 970 MB boolean array in your computer's memory. That is absurd to think about....yet....these games still run incredibly fast...so how did they do it? Well...they used many of the principles that have already been mentioned above.

    Now, I would like to suggest an alternative method that might be kind of out of the ordinary, but it might work. It is based on the idea of using a binary tree, which has already been suggested. My idea is basically to further that same idea, and use a map. A map just uses a binary tree on the back end anyways. Like someone as already stated, it will give you O(log n) time in your algorithm, which is still incredibly fast.

    All you will have to do is check to see if a certain point is contained in the map. For example:

    Code:
    struct Point3D
    {
        int x;
        int y;
        int z;
    };
    
    map < Point3D, bool > myPointMap;
    First initialize all of your 1000 points that you
    say that you have...that's fairly simple to do.
    Then, just iterate through all those points, and
    initialize your map:

    Code:
    myPointMap[ myPoint3D[i] ] = true;
    Now your map is completely set up. Anytime you move a point,
    you can go to that point in the map, and do a simple spherical
    radius check of the points around that point. If nothing
    blocks it, set that point in the map to false, and move it
    to the new point.

    log n time using a map.
    My Website

    "Circular logic is good because it is."

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 05-29-2009, 07:25 PM
  2. Code review
    By Elysia in forum C++ Programming
    Replies: 71
    Last Post: 05-13-2008, 09:42 PM
  3. DirectInput help
    By Muphin in forum Game Programming
    Replies: 2
    Last Post: 09-10-2005, 11:52 AM
  4. How do I play an MP3?
    By Hunter2 in forum Windows Programming
    Replies: 28
    Last Post: 05-20-2002, 08:49 PM
  5. 3d array
    By Pamela in forum C++ Programming
    Replies: 1
    Last Post: 10-24-2001, 03:59 AM