<p>Barycentric coordinates need to sum to 1.0, so pick two of them (say <span class="math-container">$u, v$</span>) randomly from [0, 1] and then set the third as <span class="math-container">$w = 1 - u - v$</span>. This will give you random points that are evenly distributed with respect to area, in a parallelogram consisting of two copies of the triangle. Then, you can reflect across the triangle edge to bring both copies of the triangle together. This can be done by checking if <span class="math-container">$u + v &gt; 1$</span>, and if so, reflect by setting <span class="math-container">$u' = 1-u,\, v' = 1-v$</span> and then recalculate <span class="math-container">$w$</span>.</p>
<p>See also: <a href="https://blogs.sas.com/content/iml/2020/10/19/random-points-in-triangle.html" rel="nofollow noreferrer">Generate random points in a triangle</a>.</p>

CC BY-SA 4.0
2020-12-10T19:47:13.923Z
2020-12-10T19:47:13.923Z
Nathan Reed
<p>I would like to implement a random placement for objects like trees stones etc. on a triangles surface.
The important part is to have an equally probability to place an object on this surface. That means, that for example to randomly place a tree in the middle should not be higher than placing it at a corner / edge.</p>
<p>The second requirement is to program this placement algorithm onto the GPU by using OpenGL/GLSL. So randomly generate a position and loop as long as it is not inside the triangle is no option because of branching...  I need to place tons of objects per frame...</p>
<p>I had the idea of using Barycentric coordinates where the three scalars are randomly generated. but it turned out, that the middle and the lines from the middle to the middle of an edge is more probably than hitting a corner. The good thing about Barycentric coordinates is, that the surface of the 3D triangle is always hit, so the generated position is not above or outside the triangle. Another plus is, that to calculate the Barycentric coordinate is extremely fast during using multiplication of 3D vectors with scalars and addition of vectors with vectors.</p>
<p>here is my C++ code to generate random positions on the triangles' surface.</p>
<pre><code>#include &lt;iostream&gt;
#include &lt;fstream&gt;
#include &lt;string&gt;
#include &lt;vector&gt;
#include &lt;stdlib.h&gt;

struct Vector3D
{
public:

    Vector3D()
    {

    }

    Vector3D(double x, double y, double z)
    {
        this-&gt;x = x;
        this-&gt;y = y;
        this-&gt;z = z;
    }

    void operator*=(double factor)
    {
        x *= factor;
        y *= factor;
        z *= factor;
    }

    void operator+=(double factor)
    {
        x += factor;
        y += factor;
        z += factor;
    }

    Vector3D operator*(double factor)
    {
        Vector3D result;
        result.x = x * factor;
        result.y = y * factor; 
        result.z = z * factor; 
        return result;
    }

    Vector3D operator+(Vector3D v2)
    {
        Vector3D result;
        result.x = x + v2.x;
        result.y = y + v2.y;
        result.z = z + v2.z;
        return result;
    }

    double x;
    double y;
    double z;
};


Vector3D getBarycentricPosition(Vector3D p0, Vector3D p1, Vector3D p2, double scalar0, double scalar1, double scalar2)
{
    return (p0 * scalar0) + (p1 * scalar1) + (p2 * scalar2);
}


void main()
{
    Vector3D p0(1, 0, 0);
    Vector3D p1(0, 1, 0);
    Vector3D p2(0, 0, 1);

    std::ofstream writefile(&quot;C:/Data[![enter image description here][1]][1]/barycentricTest.obj&quot;);
    if (writefile.is_open())
    {
        for (unsigned int i = 0; i &lt; 100000; ++i)
        {
            //generate random values
            double random0 = rand() % 1000;
            double random1 = rand() % 1000;
            double random2 = rand() % 1000;

            //
            double powFactor = 1.0f;
            random0 = pow(random0, powFactor);
            random1 = pow(random1, powFactor);
            random2 = pow(random2, powFactor);

            int sum = random0 + random1 + random2;

            //scalar0 + scalar1 + scalar2 = 1 !!
            double scalar0 = static_cast&lt;double&gt;(random0) / static_cast&lt;double&gt;(sum);
            double scalar1 = static_cast&lt;double&gt;(random1) / static_cast&lt;double&gt;(sum);
            double scalar2 = static_cast&lt;double&gt;(random2) / static_cast&lt;double&gt;(sum);

            Vector3D p = getBarycentricPosition(p0, p1, p2, scalar0, scalar1, scalar2);
   
            //write to .obj file to see results in blender
            writefile &lt;&lt; &quot;v &quot; &lt;&lt; p.x &lt;&lt; &quot; &quot; &lt;&lt; p.y &lt;&lt; &quot; &quot; &lt;&lt; p.z &lt;&lt; std::endl;
        }
        writefile.close();
    }
}
</code></pre>
<p>By looking at the code, you'll recognize, that there is the double <em>powFactor</em>. I tried to bring the probability of the corners a little bit up.</p>
<p>Here are some images with different <em>powFactor</em> values.</p>
<p><strong>powFactor = 1.0   So without influencing the algorithm</strong>
<a href="https://i.sstatic.net/gsTyd.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/gsTyd.png" alt="enter image description here" /></a></p>
<p><strong>powFactor = 1.3</strong>
<a href="https://i.sstatic.net/lEua0.jpg" rel="nofollow noreferrer"><img src="https://i.sstatic.net/lEua0.jpg" alt="enter image description here" /></a></p>
<p>Like you can see, to pow with 1.3 looks good inside, but the corners / edges are over weighted...</p>
<p>Is there a fast algorithm (branching free) which gives good results?</p>

<opengl><glsl><distribution>
Equally distribution on triangle surfaces
Thomas
# Equally distribution on triangle surfaces

(Asked by: username_0 on 2020-12-10)

I would like to implement a random placement for objects like trees stones etc. on a triangles surface.
The important part is to have an equally probability to place an object on this surface. That means, that for example to randomly place a tree in the middle should not be higher than placing it at a corner / edge.

The second requirement is to program this placement algorithm onto the GPU by using OpenGL/GLSL. So randomly generate a position and loop as long as it is not inside the triangle is no option because of branching... I need to place tons of objects per frame...

I had the idea of using Barycentric coordinates where the three scalars are randomly generated. but it turned out, that the middle and the lines from the middle to the middle of an edge is more probably than hitting a corner. The good thing about Barycentric coordinates is, that the surface of the 3D triangle is always hit, so the generated position is not above or outside the triangle. Another plus is, that to calculate the Barycentric coordinate is extremely fast during using multiplication of 3D vectors with scalars and addition of vectors with vectors.

here is my C++ code to generate random positions on the triangles' surface.

```
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <stdlib.h>

struct Vector3D
{
public:

    Vector3D()
    {

    }

    Vector3D(double x, double y, double z)
    {
        this->x = x;
        this->y = y;
        this->z = z;
    }

    void operator*=(double factor)
    {
        x *= factor;
        y *= factor;
        z *= factor;
    }

    void operator+=(double factor)
    {
        x += factor;
        y += factor;
        z += factor;
    }

    Vector3D operator*(double factor)
    {
        Vector3D result;
        result.x = x * factor;
        result.y = y * factor; 
        result.z = z * factor; 
        return result;
    }

    Vector3D operator+(Vector3D v2)
    {
        Vector3D result;
        result.x = x + v2.x;
        result.y = y + v2.y;
        result.z = z + v2.z;
        return result;
    }

    double x;
    double y;
    double z;
};

Vector3D getBarycentricPosition(Vector3D p0, Vector3D p1, Vector3D p2, double scalar0, double scalar1, double scalar2)
{
    return (p0 * scalar0) + (p1 * scalar1) + (p2 * scalar2);
}

void main()
{
    Vector3D p0(1, 0, 0);
    Vector3D p1(0, 1, 0);
    Vector3D p2(0, 0, 1);

    std::ofstream writefile("C:/Data[![enter image description here][1]][1]/barycentricTest.obj");
    if (writefile.is_open())
    {
        for (unsigned int i = 0; i < 100000; ++i)
        {
            //generate random values
            double random0 = rand() % 1000;
            double random1 = rand() % 1000;
            double random2 = rand() % 1000;

            //
            double powFactor = 1.0f;
            random0 = pow(random0, powFactor);
            random1 = pow(random1, powFactor);
            random2 = pow(random2, powFactor);

            int sum = random0 + random1 + random2;

            //scalar0 + scalar1 + scalar2 = 1 !!
            double scalar0 = static_cast<double>(random0) / static_cast<double>(sum);
            double scalar1 = static_cast<double>(random1) / static_cast<double>(sum);
            double scalar2 = static_cast<double>(random2) / static_cast<double>(sum);

            Vector3D p = getBarycentricPosition(p0, p1, p2, scalar0, scalar1, scalar2);
   
            //write to .obj file to see results in blender
            writefile << "v " << p.x << " " << p.y << " " << p.z << std::endl;
        }
        writefile.close();
    }
}

```

By looking at the code, you'll recognize, that there is the double *powFactor*. I tried to bring the probability of the corners a little bit up.

Here are some images with different *powFactor* values.

**powFactor = 1.0 So without influencing the algorithm**
[![enter image description here](https://i.sstatic.net/gsTyd.png)](https://i.sstatic.net/gsTyd.png)

**powFactor = 1.3**
[![enter image description here](https://i.sstatic.net/lEua0.jpg)](https://i.sstatic.net/lEua0.jpg)

Like you can see, to pow with 1.3 looks good inside, but the corners / edges are over weighted...

Is there a fast algorithm (branching free) which gives good results?

**Tags:** opengl, glsl, distribution


---

## 1 answers

### Answer by username_1 on 2020-12-10. Score: 1 | Accepted answer

Barycentric coordinates need to sum to 1.0, so pick two of them (say $u, v$) randomly from [0, 1] and then set the third as $w = 1 - u - v$. This will give you random points that are evenly distributed with respect to area, in a parallelogram consisting of two copies of the triangle. Then, you can reflect across the triangle edge to bring both copies of the triangle together. This can be done by checking if $u + v > 1$, and if so, reflect by setting $u' = 1-u,\, v' = 1-v$ and then recalculate $w$.

See also: [Generate random points in a triangle](https://blogs.sas.com/content/iml/2020/10/19/random-points-in-triangle.html).


---

