Generate random points on geometry [SOLVED]



  • On 08/08/2014 at 22:58, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   14, 15 
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    Hi,

    I am looking for a way to scatter some objects on arbitrary geometry. How do I go about generating random points on that geometry as an array, and how do I get the vertex/polygon normals under those points in order to calculate proper orientation?

    Thanks!



  • On 13/08/2014 at 11:51, xxxxxxxx wrote:

    Any help on this guys?

    Also, how can I set the distribution according to a noise map?



  • On 13/08/2014 at 12:14, xxxxxxxx wrote:

    Naive approach pseudo code:
    - Precompute Vertex/polygon normals
    - Go through all polygons
    - On each polygon place points according to your distribution policy (random, noise...)
    - Once done, go through all points and create the objects you need there and align according to normals

    You don't expect anyone to write the code for you do you? You shouldn't. Also if you search this forum you may even find code for this (or not). Worth a shot.



  • On 15/08/2014 at 13:57, xxxxxxxx wrote:

    Thanks for the pointer Katachi. I was able to solve most of the point distribution problems. 
    I was looking to see if there is a ready-made function that generated points instead of having to do it manually. I guess there is not.

    Anyway, I have a new question, one that I haven't been able to find an answer for in this forum. 
    Is there a way to automatically convert a linked polygonal object into a RENDER INSTANCE without the user needing to do that manually?
    That would result in a great performance gain in rendering.

        BaseList2D myObjectLink = bc->GetLink(OBJECTLINK,doc);
      
        myObject = static_cast<BaseObject*>(myObjectLink->GetClone(COPYFLAGS_0, NULL));
        if (myObject )
        {
      	//NEED TO CONVERT myObject INTO A RENDER INSTANCE
        }
    

    Thanks!



  • On 15/08/2014 at 23:35, xxxxxxxx wrote:

    I think RenderInstances have to do with VolumeData::GetRenderInstance
    Anyone has an example of how I can get it to work?



  • On 16/08/2014 at 05:24, xxxxxxxx wrote:

    The problem is in your consideration of Render Instances.  You don't 'convert' an object into one.  You reference an object in the Render Instance and make transformational changes to the latter.  In essence, a bunch of Render Instances all refer to the same object but with different transformations for each instance.  The idea is instead of using a thousand real objects, you use one and have it shadowed as many.



  • On 16/08/2014 at 07:40, xxxxxxxx wrote:

    Maybe I used the wrong terminology, but thanks for the clarification Robert.

    What I am basically looking for is this: When using the Duplicate function in C4D, you get to choose whether you need to create Render Instances or not. Well, I need to provide the same functionality whenever the user adds an object to a link field (which is used in a scatter function). I hope that makes sense.



  • On 16/08/2014 at 08:32, xxxxxxxx wrote:

    In my Greebler plugin (which sounds close to what you are doing), I have Description options for using Instances or RenderInstances as Checkboxes for the user.  Then I use these to determine whether or not to use a copied object, an instance, or a render instance.

    // In my .res file
    BOOL		GREEBLER_NURN_INSTANCE					{ ANIM OFF; }
    BOOL		GREEBLER_NURN_RENDERINSTANCE			{ ANIM OFF; }
      
    // In the code
    // Instance Nurnie Object and add under nurnieOp Null object
    // 'niop' is a BaseObject* to the object being instanced.
    // 'render_instance' is a Bool that contains the value of GREEBLER_NURN_RENDERINSTANCE
    BaseObject*	iop =		BaseObject::Alloc(Oinstance);
    if (!iop)				return;
    iop->InsertUnderLast(tnull);
    BaseContainer*	ibc =	iop->GetDataInstance();
    if (!ibc)				return;
    ibc->SetLink(INSTANCEOBJECT_LINK, niop);
    ibc->SetBool(INSTANCEOBJECT_RENDERINSTANCE, render_instance);
    

    You do this for each instance and then set the instances' matrices (or PSR values).



  • On 16/08/2014 at 08:43, xxxxxxxx wrote:

    Just to add: it is encouraged to use SetParameter() instead of BaseContainer->Set....() these days. No need to get the BaseContainer either. That part of the code can be easily changed to:

    iop->SetParameter(DescId(ISNTANCEOBJECT_LINK), GeData(niop),DESCFLAGS_SET_PARAM_SET);
    iop->SetParameter(DescId(ISNTANCEOBJECT_RENDERINSTANCE), GeData(render_instance),DESCFLAGS_SET_PARAM_SET);
    


  • On 16/08/2014 at 11:36, xxxxxxxx wrote:

    Thanks a lot Robert (as always). Render Instances work like a charm using your code snippet.

    Any pointers on how to disseminate an array of vector positions over a surface?
    The way I did it (which so far is not a great solution) is to randomize the positions in space and then use GeRayCollider to project these points onto the surface, thus getting the intersection positions and normals. I wonder if there is a better way to do it.

    Thanks again!



  • On 16/08/2014 at 13:11, xxxxxxxx wrote:

    why randomize positions in space? you can randomize positions on surface
    consider this, mesh got an array of triangles, each triangle got 3 vertices and a normal
    to randomize position on a triangle, it will be a function of barycentric coordinates , let the 3 points of triangle be:p1 , p2 , p3

    barycentric coordinates should be something like: p = (1 - a) p1 + (1 - b)p2 + p3 where a and b [0,1] and a + b < 1 "I don't remember if this is correct but google and wikipedia should confirm the exact equation"

    so with this equation , all you need is to randomize a and b on each triangle to get a position on that triangle, + reading this triangle normal and it's done



  • On 16/08/2014 at 13:26, xxxxxxxx wrote:

    That's how to do it (simply).  In Greebler, I also have a 'relax' option which lets the objects being randomly placed flow outside the triangle.  While the results sometimes end up floating in space because of the angle between the triangle and its neighbors, the results are less triangle-rigid.



  • On 16/08/2014 at 21:54, xxxxxxxx wrote:

    Thanks for the tips Mohamed and Robert.
    The equation that I used (from Google) is:
    P = P1 + u*(P2-P1) + v*(P3-P1)
    where P1, P2 and P3 are the triangle vertex positions, and u and v are scalars, such that u + v <= 1


Log in to reply