Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Vertex Modelling Tool

Sanderman Cyclone
Registered User
Join date: 29 Jun 2006
Posts: 8
02-13-2007 07:10
I made this tool because I felt it would be of much help to me, or any builder making complex objects. What it does is simple, it allows you to model by positioning vertices and create fitting triangles between them. This gives u a lot of precision while building as it eliminates the need to manually position, rotate, taper and sheer prims to form a surface.

Of course this tool is only useful in certain situations, in others, prim building is more efficient, the best way is to use both methods, this tool, and traditional prim building. anyone can see that a single prim for a square is more efficient that 2 tri's.

Nevertheless, I think this tool is going to be of great help to any builder and I'm looking forward to the interesting things that could sprout from this. This tool has lot's of potential. A hint: change your way of thinking to using triangles in the most efficient ways.

I want to stress that not only me deserves credit but even more Seifert Surface, as his triangle creation scripts made this tool possible, all I've done is implemented his tri's (with permission) into this userfriendly tool.

Comments and instructions how to use can be found in the main script.

I'm giving this away to the community for free.
Feel free to do what u want with the script, just don't sell it as is.

Vertex script:
CODE
// Vertex
// by Sanderman Cyclone
// also incorporates work by Seifert Surface
// Jan 2007
//
// Use this as you want but don't resell it as is.
//
// How to use the Vertex Modelling Tool:
//
// Use this tool to make triangles between preset position vectors.
// This could be used for vertex modelling, as done in RL modelling apps.
// This will not kill prim building, there is still the prim limit :(
// Every triangle is actually a single prim so prim count could go up fast, but a good builder
// keeps this in mind and creates fantastic things with this. :)
// The tool works best in combination with traditional prim building, currently a limit of the tool
// is that it can not make polygons, so these should be made manually unless u want to use 2 tris
// for a square for example. :(
//
// To start vertex modelling, just rez a vertex, shift-copy it a few times, position them as you
// want, and click them one by one, every time, 3 vertices are selected, a triangle will be formed,
// this way you can create cool surfaces. :)
//
// The tool accepts 3 different voice commands over the chat on the command channel:
//
// 1. depth x replace x with a float to set the depth of to be created triangles
// I find that depth of 0.01 is good for precision while 0.1 or 1 gives crudeness.
// 2. clean removes all vertices when done building
// 3. freeze removes the scripts and triangle object from vertices, usefull if u want that
// for some reason
//
//
// How to use the vertex modelling tool scripts:
// (this is important if assembling yourself from the forums)
//
// Rez a prim, name it Triangle, put the Triangle script in it.
// Rez a second prim, name it Vertex, put the Vertex script and the Triangle Detailer script in it.
// Also put the Triangle object in the Vertex.
// Resize and deform the Vertex prim to your preference. I prefer it to be a small sphere.
// Your Vertex is ready to use, always keep a copy of it in inventory. Rez some Vertices in world
// to start the fun. :)
//
// Note. you could also customize this with custom scripting or a different predefined triangle
// color or whatever.
//
// How it works:
//
// Basically, every time a vertex is touched, it broadcasts it's position over chat so others know
// that position. These positions are saved and when an object is touched and it already has 2
// positions in variable, then get third position of itself and rez a triangle between the 3 vectors.
//
// The triangle creation part is actually the biggest part of the system and Seifert Surface recieves
// full credit for that. He gave permission on the forums for people to use his script in third party
// tools.
//
// What I've done is integrate his triangles into a user friendly tool that will help builders with
// building complex shapes. The builder should however, be aware of prim count as it could go up
// fast.
//
integer chan = 22; //change this if u want a different command channel.

vector a;
vector b;
vector c;
vector origin;
float scale = 1;
float depth = 0.01;
float delta = 0.01;
rotation rot;
integer comm_channel = -61347732;
integer rez_counter;

//Function for rezzing triangle between vectors a, b and c.
//Credit for this goes to Seifert Surface.
rez_triangle(vector a, vector b, vector c)
{
a = origin + scale * a;
b = origin + scale * b;
c = origin + scale * c;
//check for 2 vertices in the same place
if(llVecDist(a,b) < delta || llVecDist(b,c) < delta || llVecDist(c,a) < delta)
{ //if so, don't try to rez the triangle
return;
}
float cosA = (b - a) * (c - a);
float cosB = (c - b) * (a - b);
float cosC = (a - c) * (b - c); //signs -ve means obtuse angle
if(cosA < 0.0) //so the angle at a is obtuse, meaning the opposite edge must be the base of the prim
{
triangle(a, b, c, TRUE);
}
else if(cosB < 0.0)
{
triangle(b, c, a, TRUE);
}
else if(cosC < 0.0)
{
triangle(c, a, b, TRUE);
}
else //all acute angles... so we can choose which way to base the prim, so as to minimise the
{ //error introduced by the shear value having a resolution of only 0.01
float error1 = triangle(a,b,c,FALSE);
float error2 = triangle(b,c,a,FALSE);
float error3 = triangle(c,a,b,FALSE);
if(error1 < error2)
{
if(error1 < error3)
{
triangle(a,b,c,TRUE);
}
else
{
triangle(c,a,b,TRUE);
}
}
else
{
if(error2 < error3)
{
triangle(b,c,a,TRUE);
}
else
{
triangle(c,a,b,TRUE);
}
}
}
}

float triangle(vector a, vector b, vector c, integer rez)
{
float width = llVecDist(b, c);
vector left = llVecNorm(b - c);
vector fwd = llVecNorm(left % (a - c));
vector up = fwd % left;
float height = (a - c) * up;
float y_shear = 0.5 - ((b-a) * left) / width;

if(rez)
{
vector center = 0.5 * ( (b+c) + (height * up) );
vector scale = <depth, width, height>;
rotation rot = llAxes2Rot(fwd, left, up);
llMessageLinked(LINK_THIS, comm_channel + rez_counter, (string)scale + "|" + (string)y_shear, NULL_KEY);

while(llVecDist(llGetPos(), center) > 9.5)
{
llSetPos(center);
}
llRezObject("Triangle", center, ZERO_VECTOR, rot, comm_channel + rez_counter);
rez_counter += 1;
return -1.0;
}
else
{
y_shear = (float)llRound(y_shear * 100.0) / 100.0;
return llVecDist(a, 0.5 * (b + c) + height * up + y_shear * width * left);
//error between where the vertex of the triangle should be and would be...
}
}
//function for resetting the vertex
reset()
{
a = ZERO_VECTOR;
b = ZERO_VECTOR;
c = ZERO_VECTOR;
llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <1, 1, 1>, 1]);
}
//default state
default
{
on_rez(integer num)
{
reset();
}
state_entry()
{
llListen(chan,"","","");
llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <1, 1, 1>, 1]);
}

touch_start(integer num_detected)
{
if(llDetectedKey(0) == llGetOwner())
{
//If clause to detect user error, resetting
if(llGetPos() == a || llGetPos() == b || llGetPos() == c)
{
llShout(chan, "reset");
reset();
}
//Else if to set vector a
else if(a == ZERO_VECTOR)
{
a = llGetPos();
llShout(chan,"vectora "+(string)a);
llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <1, 0, 0>, 1]);
}
//Else if to set vector b
else if(b == ZERO_VECTOR)
{
b = llGetPos();
llShout(chan,"vectorb "+(string)b);
llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <1, 0, 0>, 1]);
}
//Else if to set vector c, rez triangle, and reset
else if(c == ZERO_VECTOR)
{
c = llGetPos();
llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <1, 0, 0>, 1]);
rez_triangle(a,b,c);
llShout(chan, "reset");
reset();
}
}
}
//listening for communication
listen(integer chan, string name, key id, string msg)
{
//checking if the speaker is owner or owner's object
if(llGetOwnerKey(id) == llGetOwner())
{
//process commands
list cmdLine = llParseString2List(msg, [" "], [""]);
string cmd = llList2String(cmdLine, 0);
cmd = llToLower(cmd);
//reset command
if(msg == "reset")
{
reset();
}
//command to set depth
else if (cmd == "depth")
{
depth = llList2Float(cmdLine, 1);
}
//freeze command, used to remove inventory from vertices
else if (cmd == "freeze")
{
llShout(chan, "freeze");
llRemoveInventory("Triangle");
llRemoveInventory("Triangle Detailer");
llRemoveInventory(llGetScriptName());
}
//clean command, to remove all vertices.
else if (cmd == "clean")
{
llShout(chan, "clean");
llDie();
}
//setting vector a from message
else if(cmd == "vectora")
{
a = (vector)llGetSubString(msg, llSubStringIndex(msg, "<"),llStringLength(msg));
}
//setting vector b from message
else if(cmd == "vectorb")
{
b = (vector)llGetSubString(msg, llSubStringIndex(msg, "<"),llStringLength(msg));
}
//setting vector c from message
else if(cmd == "vectorc")
{
c = (vector)llGetSubString(msg, llSubStringIndex(msg, "<"),llStringLength(msg));
}
}
}
}


Seifert Surface Triangle scripts, included for convenience:

Triangle:
CODE
//Triangle Rezzee
//by Seifert Surface
//Nov 2006

integer comm_channel = -61347732;
integer comm_channel2 = 61347732;
integer me;
integer listen_control;
integer times_to_ask = 10;

default
{
state_entry()
{
llListen(347, "", "", "");
}
on_rez(integer param)
{
if(param != 0)
{
me = param;
llSetObjectName((string)(me - comm_channel));
listen_control = llListen(me, "", "", "");
llShout(comm_channel2, (string)me);
llSetTimerEvent(5.0);
}
}
listen(integer chan, string name, key id, string msg)
{
if(msg == "die")
{
llDie();
}
else if(msg == "clear")
{
llRemoveInventory(llGetScriptName());
}
else if(chan == me)
{
list data = llParseStringKeepNulls(msg, ["|"], []);
vector scale = (vector)llList2String(data, 0);
if(scale.x < 0.01)
{
scale.x = 0.01;
}
if(scale.y < 0.01)
{
scale.y = 0.01;
}
if(scale.z < 0.01)
{
scale.z = 0.01;
}
float y_shear = (float)llList2String(data, 1);
llSetPrimitiveParams([PRIM_TYPE, PRIM_TYPE_BOX, 0, <0.0, 1.0, 0.0>, 0.0, <0.0, 0.0, 0.0>, <1.0, 0.0, 0.0>, <0.0, y_shear, 0.0>, PRIM_SIZE, scale]);
llSetObjectName("Object");
llRemoveInventory(llGetScriptName()); //if you want to remove scripts as soon as possible, uncomment this.
llListenRemove(listen_control);
llSetTimerEvent(0.0);
}
}
timer()
{
llShout(comm_channel2, (string)me);
times_to_ask -= 1;
if(times_to_ask <= 0)
{
llSetTimerEvent(0.0);
llSay(DEBUG_CHANNEL, "no reply after 10 tries");
}
}
}


Triangle Detailer:
CODE
//Triangle Detailer
//by Seifert Surface
//Nov 2006

integer comm_channel2 = 61347732;
list rezzees;
list tri_data;

default
{
state_entry()
{
llListen(comm_channel2, "", NULL_KEY, "");
}
link_message(integer sender, integer num, string str, key id)
{
rezzees += [num];
tri_data += [str];
if(llGetListLength(rezzees) > 10)
{
llSay(DEBUG_CHANNEL, "Detailer list getting long...");
}
}
listen(integer chan, string name, key id, string msg)
{
//llOwnerSay((string)llGetFreeMemory() + " " + (string)llGetListLength(rezzees)); //in case you want to see if the detailer is getting overloaded
integer who = llListFindList(rezzees, [(integer)msg]);
if(who != -1)
{
llShout((integer)msg, llList2String(tri_data, who));
rezzees = llDeleteSubList(rezzees, who, who);
tri_data = llDeleteSubList(tri_data, who, who);
}
}
}
Nada Epoch
The Librarian
Join date: 4 Nov 2002
Posts: 1,423
Discussion Thread
02-14-2007 11:04
/54/17/166223/1.html
_____________________
i've got nothing. ;)
Ray Musketeer
Registered User
Join date: 22 Oct 2005
Posts: 418
02-16-2007 14:05
Hate to go on a rant here but those who would use such tools are not builders, they are script users. Same with the dress maker scripts, the jewlery making scripts, and any others that portends some skill behind using a script to build with.