Anim8or Community

Please login or register.

Login with username, password and session length
Advanced search  

News:

Ian Ross has just released a book on Anim8or. It's perect for a beginner and a good reference for experienced users. It contains detailed chapters on every aspect, with many examples. Get your own copy here: "Anim8or Tutorial Book"

Author Topic: SetFacePointIndex method  (Read 20234 times)

NickE

  • Full Member
  • ***
  • Posts: 167
    • View Profile
SetFacePointIndex method
« on: December 30, 2015, 06:56:01 pm »

I am trying to write an ASL script to essentially do what the Edit->Fix Normals command does.

I am using the technique of picking a face as the standard and testing whether the adjacent faces have the edges (or points) are wound in the same direction, then testing the adjacent to the adjacent, etc.  If I find a face that is wound in the same direction as the previous, I would like to reverse the winding.

I am trying to use the mesh.SetFacePointIndex method to do this:

Code: [Select]
for $k = 0 to $source.GetNumSides($otherface)-1 do {
   $source.SetFacePointIndex($otherface,$k,$ofptindex[$source.GetNumSides($otherface)-1-$k]);
}

where $ofptindex[] is the list of the index to the face points in the original order. 

I am working with a cube converted to a mesh as a test. E=EdgeIndex, F1:Face containing edge, F2:Other Face containing edge

Code: [Select]
E:1  F1:0 F2:5
E:2  F1:0 F2:3
E:3  F1:0 F2:4
E:4  F1:0 F2:2
E:5  F1:1 F2:2
E:6  F1:1 F2:4
E:7  F1:1 F2:3
E:8  F1:1 F2:5
E:9  F1:2 F2:4
E:10 F1:2 F2:5
E:11 F1:3 F2:5
E:12 F1:3 F2:4
So, if the original vtxIndex were [4,5,7,6], then the new would be [6,7,5,4].  Unfortunately, the above code results in three extra edges: 6-5, 5-5, and 4-4.

Code: [Select]
E:1  F1:0 F2:5
E:2  F1:0 F2:3
E:3  F1:0 F2:4
E:4  F1:0 F2:2
E:5  F1:1 F2:2
E:6  F1:1 F2:4
E:7  F1:1 F2:3
E:8  F1:1 F2:5
E:9  F1:2 F2:4
E:10 F1:2 F2:5
E:11 F1:3 F2:5
E:12 F1:3 F2:4
E:13 F1:0 F2:0 *
E:14 F1:0 F2:0 *
E:15 F1:0 F2:0 *

I am guessing that the extra edges are left over when the Face Point Index is re-assigned one vertex at a time.

Am I understanding the mesh.SetFacePointIndex method correctly?  What is the proper way to accomplish this?

Thank you!
Logged

Claude

  • Sr. Member
  • ****
  • Posts: 285
    • View Profile
Re: SetFacePointIndex method
« Reply #1 on: December 30, 2015, 09:00:49 pm »

When you're finished editing  the mesh,do you call Close() ? I have to ask since you didn't post
the code and I assume it's what should get rid of the unwanted edges.
Logged

NickE

  • Full Member
  • ***
  • Posts: 167
    • View Profile
Re: SetFacePointIndex method
« Reply #2 on: December 31, 2015, 09:16:34 am »

The full code is below.  Unfortunately, I have opened and closed the mesh properly.

Code: [Select]
/* fix normals
   change all faces to the same orientation by starting with the first face.
   The direction of vertex winding is noted and compared to each edge adjacent face.
   If the direction of vertex winding is the same (should be opposite), fix it.
*/

/* section to initialize console output */
file $output;
string $fname;
$fname="$console";
$output.open($fname,"w");

object $curObject;
shape $shape, $shapes[0], $childShapes[1],$source;

int $havesource,$sourcenumpts,$sourcenumfaces,$sourcenumedges;

int $i,$j,$k,$m,$n;
int $tempedgeindex,$epi1,$epi2,$epi1_p,$epi2_p,$firstface;
int $tepi1,$tepi2,$tepi1_p,$tepi2_p;
int $f1,$f2;
int $cw1,$cw2;
int $flipped;
int $facestatus[0],$edgeface1[0],$edgeface2[0];
int $mainedge,$checkedge;
int $otherface;
int $ofptindex[0];

$curObject = project.curObject;
$curObject.GetShapes($childShapes);
$shapes.size = 0;
while ($childShapes.size > 0)
    $shapes.push($childShapes.pop());
   
while ($shapes.size > 0) {
    $shape = $shapes.pop();

    if ($shape.GetKind() == SHAPE_KIND_MESH && $havesource == 0)
    {
       $source=$shape;
       $sourcenumpts=$source.GetNumPoints();
       $sourcenumedges=$source.GetNumEdges();
       $sourcenumfaces=$source.GetNumFaces();
       $facestatus.size=$sourcenumfaces;
       $edgeface1.size=$sourcenumedges+1;
       $edgeface2.size=$sourcenumedges+1;
       $havesource=1;
    }
}

$shape.Open();
if ($havesource == 1) {
    /* build index of Edges to Faces to save cycles*/
    for $i = 1 to $sourcenumedges do
    {
        $firstface=0;
        for $j = 0 to $sourcenumfaces-1 do
        {
            for $k = 0 to $source.GetNumSides($j)-1 do
            {
                $tempedgeindex = $source.GetEdgeIndex($j,$k);
                if (abs($tempedgeindex) == $i) {
                    if ($firstface==0) {
                        $edgeface1[$i]=$j;
                    } else {
                        $edgeface2[$i]=$j;
                    }
                    $firstface=1;
                }
            }
        }
    }
   
    /* output list of the edges with the faces connected to it */
    for $i = 1 to $sourcenumedges do {
        $output.print("E:%d F1:%d F2:%d\n",$i,$edgeface1[$i],$edgeface2[$i]);
    }
   
   
    /* Cycle through faces edges to determine if adjacent faces have the same normals
       If the clockwise-counterclockwise order of face points is the same for adjacent faces,
       the normals are flipped
    */
   
    for $i = 0 to $sourcenumfaces-1 do {
        for $j = 0 to $source.GetNumSides($i)-1 do {
            $mainedge = $source.GetEdgeIndex($i,$j);                                /* current edge of current face */
            $epi1=$source.GetEdgeIndex0($mainedge);                                 /* end point of current edge */
            $epi2=$source.GetEdgeIndex1($mainedge);
            for $k = 0 to $source.GetNumSides($i)-1 do {
                if ($epi1==$source.GetFacePointIndex($i,$k)) $epi1_p=$k;            /* position in face vertex winding */
                if ($epi2==$source.GetFacePointIndex($i,$k)) $epi2_p=$k;
            }
            $output.print("F:%d E:%d ep1:(%d,%d) ",$i,$mainedge,$epi1_p,$epi2_p);
            if ($edgeface1[$mainedge] == $i) {                                     
                $otherface=$edgeface2[$mainedge];
            } else {
                $otherface=$edgeface1[$mainedge];
            }
            $ofptindex.size=$source.GetNumSides($otherface);                        /* retrieve other face with same edge */
            for $k = 0 to $source.GetNumSides($otherface)-1 do {
                $ofptindex[$k] = $source.GetFacePointIndex($otherface,$k);
                if ($epi1==$source.GetFacePointIndex($otherface,$k)) $tepi1_p=$k;   /* position in other face vertex winding */
                if ($epi2==$source.GetFacePointIndex($otherface,$k)) $tepi2_p=$k;
            }
            $output.print("F:%d E:%d ep1:(%d,%d) ",$otherface,$mainedge,$tepi1_p,$tepi2_p);
            if (abs($epi1_p - $epi2_p)==1) {                                        /* logic to determine direction of winding */
                if ($epi1_p > $epi2_p) {                                            /* can be simplified a bit :) */
                    $cw1=0;
                } else {
                    $cw1=1;
                }
            } else {
               if ($epi1_p > $epi2_p) {
                    $cw1=1;
               } else {
                    $cw1=0;
               }
            }

            if (abs($tepi1_p - $tepi2_p)==1) {
               if ($tepi1_p > $tepi2_p) {
                    $cw2=0;
               } else {
                    $cw2=1;
               }
            } else {
               if ($tepi1_p > $tepi2_p) {
                    $cw2=1;
               } else {
                    $cw2=0;
               }
            }
            $flipped=0;
            if ($cw1 == $cw2) $flipped=1;
            $output.print("->%d\n",$flipped);
            if ($cw1 == $cw2) {
                for $k = 0 to $source.GetNumSides($otherface)-1 do {
                    $source.SetFacePointIndex($otherface,$k,$ofptindex[$source.GetNumSides($otherface)-1-$k]);  /* reverse winding order of other face */
                    $output.print("Alter F:%d v:%d was:%d now:%d\n",$k,$otherface,$ofptindex[$k],$ofptindex[$source.GetNumSides($otherface)-1-$k]);
                }
            }
           
           
        }
    }
 }     

$shape.Close();
$output.close;

Thank you!
Logged

Claude

  • Sr. Member
  • ****
  • Posts: 285
    • View Profile
Re: SetFacePointIndex method
« Reply #3 on: January 04, 2016, 11:25:21 am »

NickE
You're using it the way I would have.
It's disappointing that calling Close() doesn't clean up.
Which way are you going now?
Cleaning up yourself,delete face and rebuild or else.

Happy new year.
Claude
Logged

Steve

  • Administrator
  • Hero Member
  • *****
  • Posts: 2124
    • View Profile
Re: SetFacePointIndex method
« Reply #4 on: January 04, 2016, 04:42:50 pm »

I'll look into this. You should be able to do this.
Logged

kreator

  • Hero Member
  • *****
  • Posts: 1146
  • Anim8or, Blender, & Carrara. A Great Combination!
    • View Profile
    • Anim8orWorld
Re: SetFacePointIndex method
« Reply #5 on: January 05, 2016, 12:36:44 am »

This is interesting, something that has been bugging me for some time now, that the Move mesh along path script no longer works, and the parametric mesh2path_2 script hangs on many occasions,  is it because the $shape.Close(); $output.close; is not functioning correctly? 
Logged
O

NickE

  • Full Member
  • ***
  • Posts: 167
    • View Profile
Re: SetFacePointIndex method
« Reply #6 on: January 05, 2016, 08:38:32 am »

Claude,
Luckily, "new" edges are always added to the end of the list, so as a workaround, I can just delete them without it causing problems with rearranging the index.

Kreator,
I had no idea that these scripts had stopped working.  I haven't used them in quite some time.  I will investigate further.

Steve,
Thank you!
Logged

kreator

  • Hero Member
  • *****
  • Posts: 1146
  • Anim8or, Blender, & Carrara. A Great Combination!
    • View Profile
    • Anim8orWorld
Re: SetFacePointIndex method
« Reply #7 on: January 05, 2016, 02:24:58 pm »



Kreator,
I had no idea that these scripts had stopped working.  I haven't used them in quite some time.  I will investigate further.




 As you can see from the cosole window I tried many times, but eventually I did get a result, so there is something very wrong!
Logged
O

NickE

  • Full Member
  • ***
  • Posts: 167
    • View Profile
Re: SetFacePointIndex method
« Reply #8 on: January 06, 2016, 01:52:07 pm »

Kreator,

When I ran through the tank tread tutorial (including downloading the scripts posted there) on Build 1205, it worked properly.

Also the mesh_2_path_2 worked properly without hanging when I tried it.

Could it be something unique to your setup?  I am happy to help in any way.
Logged

kreator

  • Hero Member
  • *****
  • Posts: 1146
  • Anim8or, Blender, & Carrara. A Great Combination!
    • View Profile
    • Anim8orWorld
Re: SetFacePointIndex method
« Reply #9 on: January 07, 2016, 02:15:39 am »

Have solved the mesh_2_path_2 problem it was me trying to click on the copytarget every time to get it to work, it ran the script but didn`t display. However, if I don`t highlight anything, but just drag in the workspace it runs OK every time.

Now I have problems with the parametric  SourceMesh2Target, result don`t happen for me, any ideas?

Note:The scripted mesh2mesh_5_wnfi_final works fine
« Last Edit: January 07, 2016, 03:59:51 am by kreator »
Logged
O

NickE

  • Full Member
  • ***
  • Posts: 167
    • View Profile
Re: SetFacePointIndex method
« Reply #10 on: January 07, 2016, 12:39:01 pm »

Kreator,

I am not sure which script your are referring to as "parametric SourceMesh2Target".

If you are referring to the parametric script in http://www.anim8or.com/smf/index.php/topic,906.msg6613.html#msg6613 called "mesh2mesh_1.a8s", I tested it in Build 1205 and it worked fine for me.  You kind of have to click the script button, then sort of click-drag a bit in some open area and the parametric copies appear.

What behavior are you seeing?

Thank you,
NickE
Logged