Extracting disconnected pieces from a mesh

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

Extracting disconnected pieces from a mesh

Postby Bird » Sun Nov 27, 2011 4:56 am

I have a single mesh composed of separate cubes and I'm trying to extract each cube to become a separate piece using the code below. It works as expected if the cubes are spaced out from one another but if they are stacked on top of one another, I'm getting unexpected results, sometimes more, sometimes less than the actual number of disjoint cubes in the original mesh. Is there a way to accomplish what I'm after or is this not supported by MeshEffects? Or more likely, am I doing something wrong. :)

Code: Select all
void Newton3Tools::extractDisjointParts (const TriMesh * const triMesh,
                                         TriMeshes & parts)
{   TRACE("Newton3Tools::extractDisjointParts")

   NewtonMesh * disjointPieces = triMeshToNewtonMesh(triMesh);

   NewtonMesh* nextPiece = 0;
   for (NewtonMesh* piece = NewtonMeshCreateFirstSingleSegment (disjointPieces); piece; piece = nextPiece)
   {
      parts.push_back( newtonMeshToTriMesh(piece) );
      
      nextPiece = NewtonMeshCreateNextSingleSegment (disjointPieces, piece);
      NewtonMeshDestroy(piece);
   }

   NewtonMeshDestroy(disjointPieces);
}
Bird
 
Posts: 636
Joined: Tue Nov 22, 2011 1:27 am

Re: Extracting disconnected pieces from a mesh

Postby Julio Jerez » Sun Nov 27, 2011 8:20 am

yes when you add the point you can add an id to associate with a subpart. How are you initiliazing the mesh. I suppose you are creating it in this function
Code: Select all
NewtonMesh * disjointPieces = triMeshToNewtonMesh(triMesh);


if you show me the implementation I can show you how to make it posible to do what you want,
then after that you can also do stuf like make the mesh a perfect tringular mesh, because then triangulation feature produce the best mesh by the delanay critiria,
that is minumizes slivers, reduces joint, etc


for example if you use these function to crate the mesh
Code: Select all
   void NewtonMeshBeginFace(const NewtonMesh* const mesh);
   void NewtonMeshAddFace(const NewtonMesh* const mesh, int vertexCount, const dFloat* const vertex, int strideInBytes, int materialIndex);
   void NewtonMeshEndFace(const NewtonMesh* const mesh);

   void NewtonMeshBuildFromVertexListIndexList(const NewtonMesh* const mesh,
      int faceCount, const int* const faceIndexCount, const int* const faceMaterialIndex,
      const dFloat* const vertex, int vertexStrideInBytes, const int* const vertexIndex,
      const dFloat* const normal, int normalStrideInBytes, const int* const normalIndex,
      const dFloat* const uv0, int uv0StrideInBytes, const int* const uv0Index,
      const dFloat* const uv1, int uv1StrideInBytes, const int* const uv1Index);


then you pass the id as the fourth paratmeter in the vertex, for example say you are adding a cube you start with and id counter

int id = 0
then for each polygon that form the first mash segment you asign id as the

verte[i] = (x0, y0, z0, id)
verte[i] = (x1, y1, z1, id)
...

the you increment ID and for each point of the next segmnet you asign this new id, and so on.
if you do not do that the the manifold will get confused with complanar faces that share more than two edges and will try to do the best it could by separating then automatically.

I am glad you are usin the mesh, that tool also has poweful feature like the voronoi decompolsition, you will see that is faste tha any othe version out there by several order of magnitud.
It also has bollean, liek diffrenct, or, and oteh stuff, I still ahe to do some wotk of that but for teh most part they work
I never continues working on then because thre was no one testing it, but if some one is using it I can continues.
some of the algorithm there are very very poerweful rubust, and fast all in one package.

as it you can actually make voronoi pieces from convex pieces of almost any density practically in real time.
it also provide a way to apply materals ans tow UV channels to the segment as they are generated.
This can be use to simulate simple fracturing, and I am working on fix the sumerical round of but on the bollean so that I can apply fracture to more concave pieces.
but for simple convex is can be use and is faste that any tool out there, it is also more acurate since it alway mmake pefect voronoi, not vertex preporssesing and no round errros instabilities.
Julio Jerez
Moderator
Moderator
 
Posts: 12452
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Extracting disconnected pieces from a mesh

Postby Bird » Sun Nov 27, 2011 11:57 am

then you pass the id as the fourth paratmeter in the vertex, for example say you are adding a cube you start with and id counter

int id = 0
then for each polygon that form the first mash segment you asign id as the

verte[i] = (x0, y0, z0, id)
verte[i] = (x1, y1, z1, id)


I was using dgMeshEffect::dgMeshEffectBuilder to help me build the mesh, but I wasn't using the id parameter. But if I understand correctly I'm using it now but it's not working correctly.

Here's the code I'm using to create the NewtonMesh from my TriMesh:
Code: Select all
// triMeshToNewtonMesh
NewtonMesh * Newton3Tools::triMeshToNewtonMesh (const TriMesh * const triMesh)
{   TRACE("Newton3Tools::triMeshToNewtonMesh")

   if( !triMesh ) return 0;

   NewtonMesh* newtonMesh = NewtonMeshCreate(world_);

   VBufferAccess vba( triMesh->getVertexFormat(), triMesh->getVertexBuffer() );

   Surface::Ptr surface = triMesh->getSurface(0);
   if( !surface ) return 0;

   IBuffer * iBuffer = surface->getIndexBuffer();
   if( !iBuffer ) return 0;

   unsigned *indices = (unsigned*)iBuffer->getData();   
   int triCount = iBuffer->getNumElements()/3;
   
   NewtonMeshBuilder builder;  // it's dgMeshEffectBuilder
   for ( int i = 0; i < triCount; i++)
   {
      dgFloat32 verts[9];
      int index = 0;
      for( int j = 0; j < 3; j++ )
      {
         Vector3f p = vba.position<Vector3f>( *indices++ );
         verts[index++] = p[0];
         verts[index++] = p[1];
         verts[index++] = p[2];
      }
      builder.addFace(3, verts, i);
   }
   dgStack<dgInt32>indexList (builder.m_vertexCount);
   dgVertexListToIndexList (&builder.m_vertex[0].m_x, sizeof (dgVector), sizeof (dgVector), 0, builder.m_vertexCount, &indexList[0], DG_VERTEXLIST_INDEXLIST_TOL);   

   dgStack<dgInt32> materialIndex(builder.m_faceCount);
   dgStack<dgInt32> m_normalUVIndex(builder.m_vertexCount);

   dgVector normalUV(dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f));

   memset (&materialIndex[0], 0, size_t (materialIndex.GetSizeInBytes()));
   memset (&m_normalUVIndex[0], 0, size_t (m_normalUVIndex.GetSizeInBytes()));

   NewtonMeshBuildFromVertexListIndexList( newtonMesh, builder.m_faceCount, builder.m_faceIndexCount, &materialIndex[0],
                                 &builder.m_vertex[0].m_x, sizeof (dgVector), &indexList[0],
                                 &normalUV.m_x, sizeof (dgVector), &m_normalUVIndex[0],
                                 &normalUV.m_x, sizeof (dgVector), &m_normalUVIndex[0],
                                 &normalUV.m_x, sizeof (dgVector), &m_normalUVIndex[0]);
   return newtonMesh;
}


where NewtonMeshBuilder is a modified version of dgMeshEffectBuilder and I replaced
m_vertex[vertexIndex].m_w = brush;
with
m_vertex[vertexIndex].m_w = id;

Is that the right way? With this code I get 48 separate pieces... so I looks like it's making 1 piece for every triangle.

-Bird

Code: Select all
// addFace
void NewtonMeshBuilder::addFace (dgInt32 vertexCount,
                                 const dgFloat32 * faceVertex,
                         dgInt32 id)
{   TRACE("NewtonMeshBuilder::addFace")

   dgInt32 vertexIndex;

      if (m_faceCount >= m_maxFaceCount)
      {
         dgInt32* index;

         m_maxFaceCount *= 2;
         index = (dgInt32*) dgMallocStack(m_maxFaceCount * sizeof(dgInt32));
         memcpy (index, m_faceIndexCount, m_faceCount * sizeof(dgInt32));
         dgFreeStack(m_faceIndexCount);
         m_faceIndexCount = index;
      }
      m_faceIndexCount[m_faceCount] = vertexCount;
      m_faceCount = m_faceCount + 1;

      vertexIndex = m_vertexCount;
      dgFloat32 brush = dgFloat32 (m_brush);
      for (dgInt32 i = 0; i < vertexCount; i ++)
      {
         if (vertexIndex >= m_maxVertexCount)
         {
            dgVector* points;

            m_maxVertexCount *= 2;
            points = (dgVector*) dgMallocStack(m_maxVertexCount * sizeof(dgVector));
            memcpy (points, m_vertex, vertexIndex * sizeof(dgVector));
            dgFreeStack(m_vertex);
            m_vertex = points;
         }

         m_vertex[vertexIndex].m_x = faceVertex[i * 3 + 0];
         m_vertex[vertexIndex].m_y = faceVertex[i * 3 + 1];
         m_vertex[vertexIndex].m_z = faceVertex[i * 3 + 2];
         m_vertex[vertexIndex].m_w = id;
         vertexIndex ++;
      }

      m_vertexCount = vertexIndex;
}
Bird
 
Posts: 636
Joined: Tue Nov 22, 2011 1:27 am

Re: Extracting disconnected pieces from a mesh

Postby Bird » Sun Nov 27, 2011 12:13 pm

I am glad you are usin the mesh, that tool also has poweful feature like the voronoi decompolsition, you will see that is faste tha any othe version out there by several order of magnitud.
It also has bollean, liek diffrenct, or, and oteh stuff, I still ahe to do some wotk of that but for teh most part they work
I never continues working on then because thre was no one testing it, but if some one is using it I can continues.
some of the algorithm there are very very poerweful rubust, and fast all in one package.


I'm very much interested in dynamic fracturing and soft bodies for my project, so I'll be happy to test anything you can come up with. :)

My first goal is to be able to do something like this in Newton: http://physbam.stanford.edu/movies/wall.avi

it you can actually make voronoi pieces from convex pieces of almost any density practically in real time
it also provide a way to apply materals ans tow UV channels to the segment as they are generated.
This can be use to simulate simple fracturing, and I am working on fix the sumerical round of but on the bollean so that I can apply fracture to more concave pieces.
but for simple convex is can be use and is faste that any tool out there, it is also more acurate since it alway mmake pefect voronoi, not vertex preporssesing and no round errros instabilities.


I haven't tried Newton's voronoi tools yet but hope too soon. I've been using Voro++ to make the shatter debris and found is very fast and robust http://math.lbl.gov/voro++/about.html

Thanks again for your help and for making such an wonderful library available to us!
-Bird
Bird
 
Posts: 636
Joined: Tue Nov 22, 2011 1:27 am

Re: Extracting disconnected pieces from a mesh

Postby Julio Jerez » Sun Nov 27, 2011 12:53 pm

Bird wrote:My first goal is to be able to do something like this in Newton: http://physbam.stanford.edu/movies/wall.avi


actually you cna do that now with newton, this demo


was in core 200, as well as some other that try on smaller scale in real time for almost three years now.
I realized it is too math intensive for real time, and I decide to make an off line possess for core300.
in the video all the decomposition, all the texturing, and mesh generation is done at run time. and each piece is different. The demo is in the SDK download.

you can actually implement simple stuff like you show even in core 200.
I have not gotten to recompile the same demo for core 300, but I am positive is does work since those algorithm had changed very little from core 200.

as for the library that create the voronoi, yes I am awere of some of the those libraries, some are very good the majority only work on contrive demos.
I do not know if that particular one is faster that Newton's, I can assure you it is not more accurate, because the Newton one uses an exact algorithm with exact arithmetic.
therefore any other library can be equally accurate as Newton's, by never ever more accurate since voronoi partition are unique.
In reality what many of those library do is that the preprocess the vertex cloud to round it off to some neighbor vertex.

The Newton algorithm crate a convex hull in four dimensions. This is the only algorithm that can generate an exact tetrahedralization,
all others are derivation of that and has to deal with a large number of float inaccuracy and doe to the lost of one dimension.
The Newton algorithm is error less.

I am positive that library you are using is probably more finish, but I will put my money in mine as accuracy goes.
In fact at the time I was writing it, and a far as I know Netwon's is the only one that uses convex hull in 4 dimension to do that.

I had being working on this stuff for many, year, I just no public paper, because of my broken English, so my work never get attention.
Julio Jerez
Moderator
Moderator
 
Posts: 12452
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Extracting disconnected pieces from a mesh

Postby Julio Jerez » Sun Nov 27, 2011 1:05 pm

BTW, did you figure out how to mak eteh NetwonMesh so that it preseve the segments as you want then?


on teh sof body, yes I am working on that, I took a break these weeke to add the conve decompsition demo, and fix a bug with teh mutotreadin with collison tree and compounds.
I added a demo that shows few conev decomposition using HACD,

I found the library is still as slow as it was before, I beleove I can re enable my version with amost bind then at iteratiove time.
I thinke the original library is very cool, but it is too slow for a tool set, it is taking few minutes to make the conve ste of 3 or 4 tousands vertex, so I reduce the meshes point count fo some of
the original models and save in teh NewtonMesh format. The demo is to how how is can be integrated not how fast it is.
Julio Jerez
Moderator
Moderator
 
Posts: 12452
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Extracting disconnected pieces from a mesh

Postby Bird » Sun Nov 27, 2011 2:19 pm

as in core 200, as well as some other that try on smaller scale in real time for almost three years now.
I realized it is too math intensive for real time, and I decide to make an off line possess for core300.
in the video all the decomposition, all the texturing, and mesh generation is done at run time. and each piece is different. The demo is in the SDK download.


That's very cool! I didn't notice it in the SDK since it isn't part of the NewtonDemos project yet.

In my world users need to break complex meshes like cows, cars and characters. Can Newton dynamically fracture a mesh that has been decomposed into convex pieces using HACD?

Another thing my beta testes ask for is that the debris pieces continue to shatter when they collide again with another object. Is that possible with Newton?

I am positive that library you are using is probably more finish, but I will put my money in mine as accuracy goes.
In fact at the time I was writing it, and a far as I know Netwon's is the only one that uses convex hull in 4 dimension to do that.


That's good to know. I am much more interested in accuracy and reliability than speed.

BTW, did you figure out how to mak eteh NetwonMesh so that it preseve the segments as you want then?


Still having problems probably cause I'm doing something stupid. I replied to you a few posts back about it... maybe you didn't see it.

I found the library is still as slow as it was before, I beleove I can re enable my version with amost bind then at iteratiove time..


Yes, HACD is very cool. but I wish it could be faster. I use it in my project before sending the body to the physics engine and I have to provide the user a progress display to let them know the plugin is still working.

-Bird
Bird
 
Posts: 636
Joined: Tue Nov 22, 2011 1:27 am

Re: Extracting disconnected pieces from a mesh

Postby Julio Jerez » Sun Nov 27, 2011 2:33 pm

Bird wrote:Still having problems probably cause I'm doing something stupid. I replied to you a few posts back about it... maybe you didn't see it.
-Bird


where, it is a very, very eassy thong to do, maybe three of for line of core to you funtion that makes the NewtonMesh form you mesh.
Show wher you posted, I am sure I can help with that.

and the answe to all teh oeth equetsion is yes, newton can do all of that. has you seen teh entire build bein destriey by the same tecnique.



taht was no using voranoi, inetsa it was using the the bollean untionality of teh newton mesh.
basically if clip the mesh unet the pices whe almost convex. and it make a adjacenty edge list to do local destrution.
I was adding the hierchical destruction, and I stop for tow reasons.

Apernetely no one was interested at teh time I was doing, untion teh comecial engien did it, than it became popular.
secund I realicse that teh nest is no do do vonev clipping all teh way, or vodori all teh way, but rather use somethong similat to qua quic sort does.
combine the two method.
-clip larger pieces untill the are qwaus convex usinf plane clipping,
-clip the sub quasy convex using boronid.
-from the edge graphs for the hiearchical destructions.
it is in fact a very simple algorth wit teh proper tools, and the engen has then.

but since not one was intertest and I do no get paid for doing this, I work on what I like when I want.
if you want to use it, I can work on it, if there is demand, then that gives me porpuse and focus, and a complete the feaure.
Julio Jerez
Moderator
Moderator
 
Posts: 12452
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Extracting disconnected pieces from a mesh

Postby Bird » Sun Nov 27, 2011 2:52 pm

where, it is a very, very eassy thong to do, maybe three of for line of core to you funtion that makes the NewtonMesh form you mesh.
Show wher you posted, I am sure I can help with that.


It's here(http://newtondynamics.com/forum/viewtopic.php?f=9&t=6973&p=48320#p48316)


and the answe to all teh oeth equetsion is yes, newton can do all of that. has you seen teh entire build bein destriey by the same tecnique.


Wow! That's awesome.

Code: Select all
if you want to use it, I can work on it, if there is demand, then that gives me porpuse and focus, and a complete the feaure.


Yes please! I'd love to be able to do that with my tool.

-Bird
Bird
 
Posts: 636
Joined: Tue Nov 22, 2011 1:27 am

Re: Extracting disconnected pieces from a mesh

Postby Julio Jerez » Sun Nov 27, 2011 7:24 pm

Oh I think understand what you mean now. You have a mesh that has connected pieces but you do not know what those are, and you want the find then. Is that what the problems is?
My impression what that you had the pieces with id’s already and you want to preserve then when converting to the Newton mesh.
The Newton mesh handle both case, but the interface will not allow you to do it right now.
I will add an extra parameter to function
void NewtonMeshBuildFromVertexListIndexList(const NewtonMesh* const mesh,
int faceCount, const int* const faceIndexCount, const int* const faceMaterialIndex,
const dFloat* const vertex, int vertexStrideInBytes, const int* const vertexIndex,
const dFloat* const normal, int normalStrideInBytes, const int* const normalIndex,
const dFloat* const uv0, int uv0StrideInBytes, const int* const uv0Index,
const dFloat* const uv1, int uv1StrideInBytes, const int* const uv1Index);

that will be a
void NewtonMeshBuildFromVertexListIndexList(const NewtonMesh* const mesh,
int faceCount, const int* const faceIndexCount, const int* const faceMaterialIndex,
const dFloat* const vertex, int vertexStrideInBytes, const int* const vertexIndex,
const dFloat* const normal, int normalStrideInBytes, const int* const normalIndex,
const dFloat* const uv0, int uv0StrideInBytes, const int* const uv0Index,
const dFloat* const uv1, int uv1StrideInBytes, const int* const uv1Index,
int preserveVertexOrder);

what that will do is that it will enumerate the connected pieces before optimization, turning identical vertices in different ones by the auto enumeration.
Right now what it does is that it optimize the vertices before enumeration therefore unless the vertices are enumerated already it will fuse them together, with that option the problem should be solved.

stand by I will try to put is tonight, it is actually very eassy to get it.
Julio Jerez
Moderator
Moderator
 
Posts: 12452
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Extracting disconnected pieces from a mesh

Postby Bird » Sun Nov 27, 2011 8:53 pm

Oh I think understand what you mean now. You have a mesh that has connected pieces but you do not know what those are, and you want the find then. Is that what the problems is?

Yes, that's it. Here's what my mesh looks like ... It's a 3x3 array of disconnected cubes ( I pulled one out to show that they are disconnected ). I want to extract them from the single mesh file and add 27 rigid bodies to my simulation using NewtonMesh tools.

stand by I will try to put is tonight, it is actually very eassy to get it

Great. Thanks a bunch!
I haven't been able to compile the last few 64 bit versions using project_vs2008 because of compile errors like this:
source\newton\Newton.cpp(8450) : warning C4273: 'NewtonDeformableMeshSegmentGetIndexList' : inconsistent dll linkage
e:\depenencies\latestnewtontrunk\corelibrary_300\source\newton\Newton.h(867) : see previous definition of 'NewtonDeformableMeshSegmentGetIndexList'

-Bird

Image
Bird
 
Posts: 636
Joined: Tue Nov 22, 2011 1:27 am

Re: Extracting disconnected pieces from a mesh

Postby Julio Jerez » Mon Nov 28, 2011 9:32 am

Ok I was lokking at the problems and for waht I can see the funtion in newton is correct, it sodul generets teh mesh corrently

here is what happened, the function you use as a model to create the mesh, you are using an uniqhew id for each face, that was the parameter named brush.
instead you are usin an ID. ID is a "per segment id" not per face id. pasing an unique id per face will make a segment from each face.

Try using the same funtion by pass 0 as id for all face, the mesh shoudl preserve all the segment as they originally are.
if that does no work, can I get as sample of one of teh problematic mesh for me to test what is wrong?
but I beleieve that passing zero should solve the problem.


I also checked in teh 64 bit libraries, I can no run the demo because I do not have teh Qt64 bit libraries (that is another 100 meg)
but the library should work.
Julio Jerez
Moderator
Moderator
 
Posts: 12452
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Extracting disconnected pieces from a mesh

Postby Julio Jerez » Mon Nov 28, 2011 9:52 am

I am going to bring back my version of the convex aproximation, I removed from the engine in version 613 in SVN, because i though Mamun was going to do add me suggested to his method.
but intead he did what he propose to me.

his solution probably work, by does not make the code any more efficent in any way.
I do not think he undertood what I was saying so I will do it in my engine and make a post on his web site to let him know.

The good new is that teh code is still on teh late vesion on newton, I jsu do no call it, because It was commnet ot, but it si still funtional, so I should get this in very soon.

what I will do is that I will place in a seprate file so that if Khaled Mamou what to go over it and get my inside to his algorithm he can add it to his,
beacasue his algorith is really awesome it just need to be more efficient.
Julio Jerez
Moderator
Moderator
 
Posts: 12452
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Extracting disconnected pieces from a mesh

Postby Julio Jerez » Mon Nov 28, 2011 12:12 pm

all right I re enable my implemnetaion again.

In the cow mesh that has abput 1500 vetex, Mamou take abput 40 secund to make it, Netwon's take less that halh a secund, about 70 time faster.

I still ahe teh problem wi the metrix of concavity, I also was mentioning that his definiot of concavity can be a lithe more mininful, and I chnage a bit in mine, but I have a bug so my mertion is comming aout of many my convex.
but that has nothing to do wi th teh time complexity of the algorithm, if anything mine should be slower.

Basically newtone impelmnetation is 1 and half orders of magnitud fasters than his.
but I still nee to peek up where I left when I stopped to add his orginal version. anyway the demo si in with both vertions, his and mine.

tonight I will work to fix the convexity metric bug and add the fix for the concaves faces left overs. that should complete this task for good
Julio Jerez
Moderator
Moderator
 
Posts: 12452
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Extracting disconnected pieces from a mesh

Postby Bird » Mon Nov 28, 2011 3:26 pm

Julio Jerez wrote:Ok I was lokking at the problems and for waht I can see the funtion in newton is correct, it sodul generets teh mesh corrently

here is what happened, the function you use as a model to create the mesh, you are using an uniqhew id for each face, that was the parameter named brush.
instead you are usin an ID. ID is a "per segment id" not per face id. pasing an unique id per face will make a segment from each face.

Try using the same funtion by pass 0 as id for all face, the mesh shoudl preserve all the segment as they originally are.
if that does no work, can I get as sample of one of teh problematic mesh for me to test what is wrong?
but I beleieve that passing zero should solve the problem.
.


I tried again passing in 0 for id for each face but it still does not work. Here's the simplest test case I could make. In one mesh there are 2 cubes that have space between them and in the other the 2cubes have 1 coplanar face. I saved in meshes in .OBJ format .... if that's not ok for you, please let me know

http://www.hurleyworks.com/downloads/meshes_with_disconnected_pieces.zip

If I parse the separated cubes I get 2 segments as expected but if I parse the touching cubes I get 3 segments.

-Bird
Bird
 
Posts: 636
Joined: Tue Nov 22, 2011 1:27 am

Next

Return to General Discussion

Who is online

Users browsing this forum: No registered users and 45 guests

cron