Gamestudio Links
Zorro Links
Newest Posts
Blobsculptor tools and objects download here
by NeoDumont. 03/28/24 03:01
Issue with Multi-Core WFO Training
by aliswee. 03/24/24 20:20
Why Zorro supports up to 72 cores?
by Edgar_Herrera. 03/23/24 21:41
Zorro Trader GPT
by TipmyPip. 03/06/24 09:27
VSCode instead of SED
by 3run. 03/01/24 19:06
AUM Magazine
Latest Screens
The Bible Game
A psychological thriller game
SHADOW (2014)
DEAD TASTE
Who's Online Now
5 registered members (AndrewAMD, Nymphodora, Quad, TipmyPip, Imhotep), 852 guests, and 5 spiders.
Key: Admin, Global Mod, Mod
Newest Members
sakolin, rajesh7827, juergen_wue, NITRO_FOREVER, jack0roses
19043 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
vec_for_vertex gap issue #472249
04/18/18 06:46
04/18/18 06:46
Joined: May 2005
Posts: 868
Chicago, IL
Dooley Offline OP
User
Dooley  Offline 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...

Quote:
///////////////////////////////
#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 Offline
Expert
Kartoffel  Offline
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: Kartoffel] #472270
04/18/18 14:07
04/18/18 14:07
Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
Superku Offline
Senior Expert
Superku  Offline
Senior Expert

Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
Could just be a timing issue, a 1 frame delay (child segments are set before their parents are updated, each frame).
Either way, you should re-think and re-code your approach IMO. Use one action and a single loop for the creature and position subsequent segments iteratively/ via skill linking (loop over main segments, like 10 starting tentacles, then move forward via skills, pointers (faster) or handles (suitable for game_save)). No additional while loops in the segments.


"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] #472281
04/18/18 15:21
04/18/18 15:21
Joined: May 2005
Posts: 868
Chicago, IL
Dooley Offline OP
User
Dooley  Offline OP
User

Joined: May 2005
Posts: 868
Chicago, IL
@Superku That sounds good. I think, instead of storing a pointer to the parent segment, maybe having the parent store a pointer to the child.

I am a little unclear on how I could do it without a while loop in the segments. If my reverse approach above does not work, then I will have to think about that more...

@Kartoffel You're right, they appear to be all facing the same direction... hmmmm

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 Offline OP
User
Dooley  Offline 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...

Quote:

///////////////////////////////
#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 Offline
Senior Expert
Superku  Offline
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:

Code:
///////////////////////////////
#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 Offline
Serious User
txesmi  Offline
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 laugh



I use the tentacles skills to store an array of vectors that serve as polyline.

Code:
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.

Code:
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.

Code:
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.

Code:
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.

Code:
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!

Re: vec_for_vertex gap issue [Re: txesmi] #472319
04/19/18 20:15
04/19/18 20:15
Joined: May 2005
Posts: 868
Chicago, IL
Dooley Offline OP
User
Dooley  Offline OP
User

Joined: May 2005
Posts: 868
Chicago, IL
@Superku,
I tried yours, it looks awesome! I love the smooth movement. I will probably keep my version for the game for now, just because I actually understand it and it is working, but thanks. I do plan to study your code in more detail, and hopefully learn a few things from it.

@txesmi
That looks really neat! I will try that out when I have the chance. Thanks for your contribution. It is humbling to see so much more sophisticated code than mine (both you and Superku) so I appreciate the help!


Moderated by  HeelX, Lukas, rayp, Rei_Ayanami, Superku, Tobias, TWO, VeT 

Gamestudio download | chip programmers | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1