|
vec_for_vertex gap issue
#472249
04/18/18 06:46
04/18/18 06:46
|
Joined: May 2005
Posts: 868 Chicago, IL
Dooley
OP
User
|
OP
User
Joined: May 2005
Posts: 868
Chicago, IL
|
I am trying to make some nifty tentacled creatures, and I am using individual segments that are held together with the vec_for_vertex command. It works, however, if I use too many segments, or if there is some more stuff on the level, the segments start to separate, especially near the end of the tentacles, see image... I have uploaded a sample of my script, if anyone is interested. I am wondering if there is a way to get the segments to apply their movement in the right order so these gaps don't appear, or if this is a limitation of the engine... Tentacles Zip File Here is the actual script, if you don't feel like downloading the file... /////////////////////////////// #include <acknex.h> #include <default.c> #include <mtlFX.c> ///////////////////////////////
//Tentacle Test var segments = 50; var roots = 20; var speed = 3;
action segment() { set(my,PASSABLE); my.material = mtl_specBump; my.skill1 = handle(you); my.skill2 = you.skill2 + 1; my.scale_x = you.scale_x * .95; my.scale_y = my.scale_x; my.scale_z = my.scale_x; //initialize movement variables var my_angles; var my_speed = speed; //create next segment if(my.skill2 < segments) { ent_create("tentacle.mdl",my.x,segment); } //start loop while(1) { you = ptr_for_handle(my.skill1); //make rotation changes my_angles += my_speed * time_step; my.pan = you.pan + 5 * sin(my_angles); my.tilt = you.tilt + 5 * sin(my_angles); my.roll = you.roll + 5 * sin(my_angles); vec_for_vertex(my.x,you,15); wait(1); } }
var pan_mod = 0; var tilt_mod = 0; var roll_mod = 0;
action root() { random_seed(0); my.pan = random(360) + pan_mod; random_seed(0); my.tilt = random(90) + tilt_mod; random_seed(0); my.roll = random(360) + roll_mod; random_seed(0); pan_mod += random(45) + 15; random_seed(0); tilt_mod += random(45) + 15; random_seed(0); roll_mod += random(45) + 15; set(my,PASSABLE); my.material = mtl_specBump; ent_create("tentacle.mdl",my.x,segment); if(roots > 0) { roots -= 1; ent_create("tentacle.mdl",my.x,root); } }
function main() { sky_color.red = 0; sky_color.green = 57; sky_color.blue = 77; // bright blue sky
d3d_antialias = 9;
level_load("Tentacles.WMB"); wait(2); }
|
|
|
Re: vec_for_vertex gap issue
[Re: Dooley]
#472254
04/18/18 08:57
04/18/18 08:57
|
Joined: Jun 2009
Posts: 2,210 Bavaria, Germany
Kartoffel
Expert
|
Expert
Joined: Jun 2009
Posts: 2,210
Bavaria, Germany
|
to me it looks like some of the segments are just not rotated correctly
POTATO-MAN saves the day! - Random
|
|
|
Re: vec_for_vertex gap issue
[Re: Dooley]
#472292
04/18/18 19:54
04/18/18 19:54
|
Joined: May 2005
Posts: 868 Chicago, IL
Dooley
OP
User
|
OP
User
Joined: May 2005
Posts: 868
Chicago, IL
|
@Superku Thank you! Controlling all the segments from one loop did the trick! It's a little less versatile now, since I have to have a fixed number of segments per arm, but they all keep together really nicely. Here's the code I used, in case anyone else wants to use some tentacles... /////////////////////////////// #include <acknex.h> #include <default.c> #include <mtlFX.c> ///////////////////////////////
//Tentacle Test var segments = .01; var roots = 50; var speed = 10; var taper = .85; var bend = 10;
action segment() { set(my,PASSABLE); my.material = mtl_specBump; wait(1); while(my.skill1 > 0) { my.scale_x = my.scale_x * taper; my.skill1 -= 1; } my.scale_y = my.scale_x; my.scale_z = my.scale_x; }
var pan_mod = 0; var tilt_mod = 0; var roll_mod = 0;
action root() { ENTITY* ent_seg01; ENTITY* ent_seg02; ENTITY* ent_seg03; ENTITY* ent_seg04; ENTITY* ent_seg05; ENTITY* ent_seg06; ENTITY* ent_seg07; ENTITY* ent_seg08; ENTITY* ent_seg09; ENTITY* ent_seg10; random_seed(0); my.pan = random(360) + pan_mod; random_seed(0); my.tilt = random(90) + tilt_mod; random_seed(0); my.roll = random(360) + roll_mod; random_seed(0); pan_mod += random(45) + 45; random_seed(0); tilt_mod += random(45) + 90; random_seed(0); roll_mod += random(45) + 180; set(my,PASSABLE); my.material = mtl_specBump; if(roots > 0) { roots -= 1; ent_create("tentacle.mdl",my.x,root); wait(1); } ent_seg01 = ent_create("tentacle.mdl",my.x,segment); ent_seg01.skill1 = 1; my.skill1 = handle(ent_seg01); wait(1); ent_seg02 = ent_create("tentacle.mdl",my.x,segment); ent_seg02.skill1 = 2; my.skill2 = handle(ent_seg02); wait(1); ent_seg03 = ent_create("tentacle.mdl",my.x,segment); ent_seg03.skill1 = 3; my.skill3 = handle(ent_seg03); wait(1); ent_seg04 = ent_create("tentacle.mdl",my.x,segment); ent_seg04.skill1 = 4; my.skill4 = handle(ent_seg04); wait(1); ent_seg05 = ent_create("tentacle.mdl",my.x,segment); ent_seg05.skill1 = 5; my.skill5 = handle(ent_seg05); wait(1); ent_seg06 = ent_create("tentacle.mdl",my.x,segment); ent_seg06.skill1 = 6; my.skill6 = handle(ent_seg06); wait(1); ent_seg07 = ent_create("tentacle.mdl",my.x,segment); ent_seg07.skill1 = 7; my.skill7 = handle(ent_seg07); wait(1); ent_seg08 = ent_create("tentacle.mdl",my.x,segment); ent_seg08.skill1 = 8; my.skill8 = handle(ent_seg08); wait(1); ent_seg09 = ent_create("tentacle.mdl",my.x,segment); ent_seg09.skill1 = 9; my.skill9 = handle(ent_seg09); wait(1); ent_seg10 = ent_create("tentacle.mdl",my.x,segment); ent_seg10.skill1 = 10; my.skill10 = handle(ent_seg10); wait(1); //initialize movement variables var my_angles; var my_speed = speed; random_seed(0); segments += random(.2) + .01; wait(-1 * segments); //begin waving sequence while(1) { //Move Segment 1 //ent_seg01 = ptr_for_handle(my.skill1); //make rotation changes my_angles += my_speed * time_step; ent_seg01.pan = my.pan + bend * sin(my_angles); ent_seg01.tilt = my.tilt + bend * sin(my_angles); ent_seg01.roll = my.roll + bend * sin(my_angles); vec_for_vertex(ent_seg01.x,my,15); ent_seg02.pan = ent_seg01.pan + bend * sin(my_angles); ent_seg02.tilt = ent_seg01.tilt + bend * sin(my_angles); ent_seg02.roll = ent_seg01.roll + bend * sin(my_angles); vec_for_vertex(ent_seg02.x,ent_seg01,15); ent_seg03.pan = ent_seg02.pan + bend * sin(my_angles); ent_seg03.tilt = ent_seg02.tilt + bend * sin(my_angles); ent_seg03.roll = ent_seg02.roll + bend * sin(my_angles); vec_for_vertex(ent_seg03.x,ent_seg02,15); ent_seg04.pan = ent_seg03.pan + bend * sin(my_angles); ent_seg04.tilt = ent_seg03.tilt + bend * sin(my_angles); ent_seg04.roll = ent_seg03.roll + bend * sin(my_angles); vec_for_vertex(ent_seg04.x,ent_seg03,15); ent_seg05.pan = ent_seg04.pan + bend * sin(my_angles); ent_seg05.tilt = ent_seg04.tilt + bend * sin(my_angles); ent_seg05.roll = ent_seg04.roll + bend * sin(my_angles); vec_for_vertex(ent_seg05.x,ent_seg04,15); ent_seg06.pan = ent_seg05.pan + bend * sin(my_angles); ent_seg06.tilt = ent_seg05.tilt + bend * sin(my_angles); ent_seg06.roll = ent_seg05.roll + bend * sin(my_angles); vec_for_vertex(ent_seg06.x,ent_seg05,15); ent_seg07.pan = ent_seg06.pan + bend * sin(my_angles); ent_seg07.tilt = ent_seg06.tilt + bend * sin(my_angles); ent_seg07.roll = ent_seg06.roll + bend * sin(my_angles); vec_for_vertex(ent_seg07.x,ent_seg06,15); ent_seg08.pan = ent_seg07.pan + bend * sin(my_angles); ent_seg08.tilt = ent_seg07.tilt + bend * sin(my_angles); ent_seg08.roll = ent_seg07.roll + bend * sin(my_angles); vec_for_vertex(ent_seg08.x,ent_seg07,15); ent_seg09.pan = ent_seg08.pan + bend * sin(my_angles); ent_seg09.tilt = ent_seg08.tilt + bend * sin(my_angles); ent_seg09.roll = ent_seg08.roll + bend * sin(my_angles); vec_for_vertex(ent_seg09.x,ent_seg08,15); ent_seg10.pan = ent_seg09.pan + bend * sin(my_angles); ent_seg10.tilt = ent_seg09.tilt + bend * sin(my_angles); ent_seg10.roll = ent_seg09.roll + bend * sin(my_angles); vec_for_vertex(ent_seg10.x,ent_seg09,15); wait(1); } }
function main() { sky_color.red = 0; sky_color.green = 57; sky_color.blue = 77; // bright blue sky
d3d_antialias = 9;
level_load("Tentacles.WMB"); wait(2); }
|
|
|
Re: vec_for_vertex gap issue
[Re: Dooley]
#472294
04/18/18 20:55
04/18/18 20:55
|
Joined: Sep 2003
Posts: 6,861 Kiel (Germany)
Superku
Senior Expert
|
Senior Expert
Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
|
I just gave it a try the way I had it in mind earlier, try this:
///////////////////////////////
#include <acknex.h>
#include <default.c>
#include <mtlFX.c>
///////////////////////////////
//Tentacle Test
var segments = 50;
var roots = 20;
var speed = 3;
#define nextSegment skill10
void segmentsCreate(ENTITY* eParent, int numSegments)
{
ENTITY* eNewSegment = ent_create("tentacle.mdl",eParent.x,NULL);
set(eNewSegment,PASSABLE);
eNewSegment.material = mtl_specBump;
eNewSegment.scale_x = eParent.scale_x * .95;
eNewSegment.scale_y = eNewSegment.scale_x;
eNewSegment.scale_z = eNewSegment.scale_x;
eParent.nextSegment = eNewSegment;
if(numSegments > 0) segmentsCreate(eNewSegment, numSegments-1);
}
action creature()
{
set(my,INVISIBLE | UNLIT);
int i;
for(i = 0; i < roots; i++)
{
you = ent_create("tentacle.mdl",my.x,NULL);
you.material = mtl_specBump;
your.pan = random(360);
your.tilt = random(360);
your.roll = random(360);
segmentsCreate(you,segments);
my.skill[19+i] = you; // my.skill[19+0] is the same as my.skill20
}
var mainAngle = 0;
while(1)
{
mainAngle += speed*time_step;
for(i = 0; i < roots; i++)
{
ENTITY* eRoot = my.skill[19+i];
eRoot.pan += time_step;
eRoot.tilt += time_step;
eRoot.roll += time_step;
ENTITY* eSegment = eRoot.nextSegment;
ENTITY* eParent = eRoot;
var extraAngle = 0;
while(eSegment)
{
var angleAdd = 5 * sinv(mainAngle+extraAngle);
eSegment.pan = eParent.pan + angleAdd;
eSegment.tilt = eParent.tilt + angleAdd;
eSegment.roll = eParent.roll + angleAdd;
vec_for_vertex(eSegment.x,eParent,15);
eParent = eSegment;
eSegment = eSegment.nextSegment;
extraAngle += 10;
}
}
wait(1);
}
}
function main()
{
sky_color.red = 0;
sky_color.green = 57;
sky_color.blue = 77; // bright blue sky
video_mode = 10;
random_seed(0);
d3d_antialias = 9;
max_entities = 9999;
level_load(NULL);
ent_create(CUBE_MDL,nullvector,creature);
camera.x -= 150;
def_move();
}
Number of roots is limited (by 80 or 100 if you change the code), segments "unlimited", you could vary their lengths as well. Personally, I'd make this all one model though, as you want to keep the number of objects low. One model, let's say 9 tentacles, which are rotated via bones around the origin. The actual tentacle movement would be realized with a vertex shader that does all the heavy lifting, and you're good.
"Falls das Resultat nicht einfach nur dermassen gut aussieht, sollten Sie nochmal von vorn anfangen..." - Manual Check out my new game: Pogostuck: Rage With Your Friends
|
|
|
Re: vec_for_vertex gap issue
[Re: Superku]
#472309
04/19/18 11:55
04/19/18 11:55
|
Joined: Jun 2007
Posts: 1,337 Hiporope and its pain
txesmi
Serious User
|
Serious User
Joined: Jun 2007
Posts: 1,337
Hiporope and its pain
|
Hi, I feel that tentacles thingy appealing and gived a try to an approach with animated polylines and quadratic bezier curves. Probably worse than bones but it has been fun I use the tentacles skills to store an array of vectors that serve as polyline.
void tentacleInit(ENTITY *entTentacle) {
c_setminmax(entTentacle);
entTentacle->skill99 = floatv(entTentacle->max_x / 8.5); // section length
int _i = 0;
for (; _i<9; _i+=1) {
entTentacle->skill[_i*3] = 50 - _i * 4;
entTentacle->skill[1+_i*3] = 0;
entTentacle->skill[2+_i*3] = 0;
vec_set(&entTentacle->skill[30 + _i * 3], &entTentacle->skill[_i * 3]);
}
entTentacle->material = mtl_create();
effect_load(entTentacle->material, "tentacle.fx");
entTentacle->material->flags |= ENABLE_TREE;
entTentacle->material->event = evnTentacle;
}
Those vectors are processed and passes to the material each frame.
void evnTentacle () {
float fSpline[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
fSpline[0] = -0.5 * my->skill[0];
fSpline[1] = -0.5 * my->skill[2]; // swapped X & Z axes
fSpline[2] = -0.5 * my->skill[1];
int _i = 1;
for(; _i<10; _i+=1) {
fSpline[_i*3] = fSpline[-3+_i*3];
fSpline[1+_i*3] = fSpline[-2+_i*3];
fSpline[2+_i*3] = fSpline[-1+_i*3];
fSpline[_i*3] += (float)my->skill[-3+_i*3];
fSpline[1+_i*3] += (float)my->skill[-1+_i*3]; // swapped X & Z axes
fSpline[2+_i*3] += (float)my->skill[-2+_i*3];
}
LPD3DXEFFECT fx1 = my->material->d3deffect;
if (fx1) {
fx1->SetValue("fSpline", fSpline, 30 * sizeof(float));
fx1->SetValue("fStep", &my->skill99, sizeof(var));
}
}
I presented a tentacle along the X axe so I assign the mesh into the polyline according to its position in length.
float3 fSpline[10];
float fStep;
float3 doSpline(in float depth, out float3 vTangent) {
depth = max(depth - fStep * 0.5f, 0);
float index = floor(depth / fStep);
float factor = fmod(depth, fStep) / fStep;
float3 v1 = lerp(fSpline[index], fSpline[index+1], 0.5);
float3 v1b = lerp(v1, fSpline[index+1], factor);
float3 v2 = lerp(fSpline[index+1], fSpline[index+2], 0.5);
float3 v2b = lerp(fSpline[index+1], v2, factor);
vTangent = normalize(v2b - v1b);
return lerp(v1b, v2b, factor);
}
I use the returned tangent in order to rotate (not really) transverse sections.
void VS (
in float4 inPos: POSITION,
out float4 outPos: POSITION,
out float3 outNormal: TEXCOORD0) {
float3 vTangent = 0;
float3 vPos = doSpline(inPos.x, vTangent);
outPos.x = vPos.x - vTangent.y * inPos.y - vTangent.z * inPos.z;
outPos.y = vPos.y + inPos.y;
outPos.z = vPos.z + inPos.z;
outPos.w = 1.0f;
outNormal = normalize(mul(outPos.xyz - vPos, (float3x3)matWorld));
outPos = mul(outPos, matWorldViewProj);
}
This simplification needs the tangent to be smaller than 45 degrees from the X axe, so the tentacles has to point, more or less, to the front. Otherway it looks wrong. Logaritmic distribution of angular speeds and segment lengths beside a single step of forward inverse kinematic make the random animation look pretty soft and natural.
void tentacleAnimate (ENTITY *entTentacle) {
int _i = 0;
for(; _i<9; _i+=1) {
VECTOR vOff;
vec_diff(&vOff, &entTentacle->skill[30+_i*3], &entTentacle->skill[_i*3]);
var _length = 2 * time_step / (9 - _i);
if (vec_length(&vOff) < _length) {
entTentacle->skill[30+_i*3] = 10;
entTentacle->skill[31+_i*3] = random(10+_i*10) - (_i+1)*5;
entTentacle->skill[32+_i*3] = random(10+_i*10) - (_i+1)*5;
vec_normalize(&entTentacle->skill[30+_i*3], 50 - _i * 4);
} else {
vec_normalize(&vOff, _length);
}
vec_add(&entTentacle->skill[_i*3], &vOff);
vec_sub(&entTentacle->skill[(_i+1)*3], &vOff); // forward inverse kinematic
}
}
Salud!
|
|
|
|