Sunday, December 29, 2013

Concave or convex angle? (Inside or Outside the Polygon)

Intro

So I needed this function for my building generator script, for the floor plans to rotate the walls to the correct angle. But it doesn't know whether its concave or convex. This script checks for the point P, on a polygon, to see if its inside or outside the polygon consisting of all points minus the point P.


Problem Breakdown

To find whether a point is inside or outside a polygon, I will need to use the Jordan Curve Theorem. To put it simply, for a point P, draw a line using its X axis, for each intersection with the polygon to the left or right of the point P, count it. If the count is even, then point P is outside, if its odd, it is inside. Imagine a pentagon. For its first point, pp0, I'd like to check if the angle0 is concave or convex. 

1. First I'll need to draw a line using the X axis through pp0. lineP

2. Secondly, I'll need to find the edges of the rectangle consisting of lines, line(pp4, pp1), line(pp1,pp2), line(pp2,pp3), line(pp3, pp4).

3. Use line-line intersection to see if line0, line1, line2, line3 intersects with lineP. If intersect, note if the intersection point is to the left or right of pp0 and add the count. 

4. If the count is even, pp0 is outside the rectange, which makes angle0 convex, if the count is odd, pp0 is inside the rectangle, and makes angle0 concave.


Source

global proc int checkInside(int $i) {//checks
    string $sel = "ngon";
    int $vtxSize[] = `polyEvaluate -v "ngon"`;
    int $a, $b, $c, $d, $e, $l_count, $r_count;
    float $a1, $a2, $b1, $b2, $c1, $c2;
    float $pp0[], $pp1[], $pp2[], $pointMax[], $pointXmin[];
    float $xx, $yy, $det;
    //this checks the immediate line AC from the point B. return should be boolean
     $a = $i - 1;
     $b = $i;
     $c = $i + 1;
     if($i == 0) {
         $a = $vtxSize[0] - 1;
         $b = 0;
     }//if

    float $pp0[] = pointPosition ($sel + ".vtx[" + $a + "]"); //coord of $a
    float $pp1[] = pointPosition ($sel + ".vtx[" + $b + "]"); //after checking the above, if none of the above, continue getting pp of next two vtx
    float $pp2[] = pointPosition ($sel + ".vtx[" + $c + "]"); //^
    float $min = min($pp0[2], $pp2[2]);
    float $max = max($pp0[2], $pp2[2]);
    
    $pointXmax = $pp1;
    $pointXmax[0] = $pointXmax[0] + 20;//arbitrary max, should be max x of the polygon
    $pointXmin = $pp1;
    $pointXmin[0] = $pointXmin[0] - 20;//lets only look at one side of the polygon            

    $a2 = $pointXmax[2] - $pointXmin[2];
    $b2 = $pointXmin[0] - $pointXmax[0];
    $c2 = ($a2 * $pointXmin[0] + $b2 * $pointXmin[2]);          
     
    if(($pp1[2] < $max) && ($pp1[2] > $min)) {    //if inside do check
        $a1 = $pp2[2] - $pp0[2];
        $b1 = $pp0[0] - $pp2[0];
        $c1 = ($a1 * $pp0[0]) + ($b1 * $pp0[2]);

        $det = ($a1 * $b2) - ($a2 * $b1);
        if($det != 0) {
            $xx = ($b2*$c1 - $b1*$c2)/$det;
            $yy = ($a1*$c2 - $a2*$c1)/$det;
        }
        else {
            print "det = 0";
        }

        if($xx > $pp1[0]) {
                $r_count = $r_count + 1;
        }
        else if($xx < $pp1[0]) {
                $l_count = $l_count + 1;
        }
        }//if

    //--------------------checks the imaginary line of prev and next point---end//
    //check every other edge in the polygon
    for($j = 0; $j < $vtxSize[0] - 2; $j++) {//every other edge
        $d = $j + $i + 1;
        $e = $d + 1;
        if($e >= $vtxSize[0]) {
            $e = $e - $vtxSize[0];
        }
        if($d >= $vtxSize[0]) {
            $d = $d - $vtxSize[0];
        }
        float $pp0[] = pointPosition ($sel + ".vtx[" + $d + "]"); //coord of $a
        float $pp2[] = pointPosition ($sel + ".vtx[" + $e + "]"); //^                
        float $min = min($pp0[2], $pp2[2]);
        float $max = max($pp0[2], $pp2[2]);    

        if(($pp1[2] < $max) && ($pp1[2] > $min)) {    //if inside do check
            $a1 = $pp2[2] - $pp0[2];
            $b1 = $pp0[0] - $pp2[0];
            $c1 = ($a1 * $pp0[0]) + ($b1 * $pp0[2]);
            
            $det = ($a1 * $b2) - ($a2 * $b1);
            if($det != 0) {
                $xx = ($b2*$c1 - $b1*$c2)/$det;
                $yy = ($a1*$c2 - $a2*$c1)/$det;
            }        

            if($xx > $pp1[0]) { //jordan curve theorem, simmple test to see inside or outside
                $r_count = $r_count + 1;
            }
            else if($xx < $pp1[0]) {
                $l_count = $l_count + 1;
            }
            //print ("rcount = " + $r_count + "\n");
            //print ("lcount = " + $l_count + "\n");                                  
        }//if inside
    } //for $j
    if($l_count % 2 == 0) {//even == outside
        return 0;
    } 
    else return 1;
}

Notes

Input: int $i, point $i on the polygon.
Output: boolean, 0 = outside, 1 = inside.

Sunday, August 18, 2013

Reflection SLBOX cheat

Synopsis

Some problems came up with the reflection node in SLIM, the shading normal connection wasn't doing anything and I needed to modify it for some watery reflection, so had to roll my own in a SLBOX.

SLBOX code
normal Nf = faceforward (N, I);
vector V = -normalize (I);

point p = transform("object", P);
normal n = transform("object", N + point "object" (0,0,0));
p += normalize(n) * b * amplitude;
p = transform("object", "current", p);
n = calculatenormal(p);

vector D = reflect(normalize(I), normalize(n));
D = vtransform("current", "world", D);

result = Kr * color environment(v8, D) * v9 * v10;
 


  1. float b is a fractal noise used to modify the normal. 
  2. color v8 is an environment texture, remember to convert using environment setting. 
  3. color v9 and v10 are just some more noise and/or fresnel functions.

Tuesday, May 28, 2013

Export/Import Shading Group Set Members

On the off chance a scenes shaders needs to be exported and then imported to the same scene without shaders(happens in production...). Doesn't work with face components, will need to do that manually. fixed: copy pasted the import code in the export code.


Export

proc exportSG() {
    string $shadingGroup[];
    $shadingGroup = `ls -sl -type shadingEngine`;
    string $mesh[];
    string $shaders[];
    string $meshList = ("/home/julio/meshlist.txt" );
    int $fileId =`fopen $meshList "w"`;
    for($i = 0; $i < size($shadingGroup); $i++) {
        select -r -ne $shadingGroup[$i];
        $mesh = `listConnections -s 1 -d 0 -type mesh`;
        $face = `listConnections -s 1 -d 0`;
        $meshList = ("/home/julio/meshlist.txt" );
    
        for($j = 0; $j < size($mesh); $j++) {
            fprint $fileId ($shadingGroup[$i] + " " + $mesh[$j] + "\n");
            }
    }
        fclose $fileId;
    }
    
    exportSG;


Import

proc importSG() {
    int $fileId =`fopen "/home/julio/meshlist.txt" "r"`;
    string $buffer[];
    string $nextLine = `fgetline $fileId`;
    while ( size( $nextLine ) > 0 ) {
        tokenize $nextLine " " $buffer;
        select -r $buffer[1];
        sets -e -forceElement $buffer[0];    
        $nextLine = `fgetline $fileId`;
    }
    fclose $fileId;
}

importSG;