Author Topic: decals  (Read 11572 times)

0 Members and 1 Guest are viewing this topic.

Offline Bobboau

  • Just a MODern kinda guy
    Just MODerately cool
    And MODest too
  • 213
I have to know if the point definitively is in the cube or not, the rest of the code makes desisions based on the number of points that are in the cube, and then the number of intersections the cube makes with the poly
a sphere would give false positives and/or negitives where they were close to the centers of the planes and/or tips
though I supose i could rule the majority in or out useing a min distance were they were defenantly in and a max distance were they would defanantly be out, then for thouse few remaining in between I could use the slower subtraction and rotation method
Bobboau, bringing you products that work... in theory
learn to use PCS
creator of the ProXimus Procedural Texture and Effect Generator
My latest build of PCS2, get it while it's hot!
PCS 2.0.3


DEUTERONOMY 22:11
Thou shalt not wear a garment of diverse sorts, [as] of woollen and linen together

 

Offline daveb

  • WHEE!!
  • 25
FWIW : proper dynamic decal code is easily in the top 5 of the classic "hardest things you'll ever have to do in 3d graphics". There's a whole jumble of math involved, and a whole slew of pure graphics issues like zbuffer fighting, multipass, clamping, etc.  Its a very, -very- difficult thing to get right.  Bobboau's got cojones for giving it a shot :)

 

Offline LtNarol

  • Biased Banshee
  • 211
    • http://www.3dap.com/hlp/hosted/the158th
Quote
Originally posted by daveb
FWIW : proper dynamic decal code is easily in the top 5 of the classic "hardest things you'll ever have to do in 3d graphics". There's a whole jumble of math involved, and a whole slew of pure graphics issues like zbuffer fighting, multipass, clamping, etc.  Its a very, -very- difficult thing to get right.  Bobboau's got cojones for giving it a shot :)
Couldn't they be implemented in a maner similar to whats done for squad logos? Or am I being an oblivious idiot again?  Because it seems to me that a system similar to whats used for squad logos could be done with far greater ease kinda like the way glowpoints were done.

 

Offline Sesquipedalian

  • Atankharz'ythi
  • 211
Not the same thing at all.  Squad logos are specific polygons in set positions, whereas decals need to be applied on the fly to any possible position anywhere on the mesh.
Sesqu... Sesqui... what?
Sesquipedalian, the best word in the English language.

The Scroll of Atankharzim | FS2 syntax highlighting

 

Offline Bobboau

  • Just a MODern kinda guy
    Just MODerately cool
    And MODest too
  • 213
well in spite of it being slower than a specal-ed student stuck in hardened tree resen, some of it does work a little bit, it's enough to make me think I was on the right track, but if you have any sorces of knowlege that might give me a better way of doing things I'd be willing to start over from scratch.

just out of curiosity, what are the other four?

for the record, my current methodology takes a pre-generated triangulated version of any subobject, and figures out which part of any triangle (that might be in the decal) is going to be in the decal, and it figures out what part it has to make, then it makes the part that has to be generated by intersecting the triangle with the cube and the cube with the triangle.

I tried simplifying what I'd have to do by reduceing all polys to triangles and intersecting with a cube with equaly sized sides.
I figured there were only a finite number of ways that a triangle could posably intersect with a cube of equal dimentions

I think there were about 13 difernt cases that I have to think about
Bobboau, bringing you products that work... in theory
learn to use PCS
creator of the ProXimus Procedural Texture and Effect Generator
My latest build of PCS2, get it while it's hot!
PCS 2.0.3


DEUTERONOMY 22:11
Thou shalt not wear a garment of diverse sorts, [as] of woollen and linen together

 

Offline LtNarol

  • Biased Banshee
  • 211
    • http://www.3dap.com/hlp/hosted/the158th
So decals are not meant to be limited to predefined areas like squad logos?  (I'm feeling dumber every minute, bear with me here)

 

Offline Bobboau

  • Just a MODern kinda guy
    Just MODerately cool
    And MODest too
  • 213
you fire a gun at a ship,
it hits,
it leaves a scorch mark or something
Bobboau, bringing you products that work... in theory
learn to use PCS
creator of the ProXimus Procedural Texture and Effect Generator
My latest build of PCS2, get it while it's hot!
PCS 2.0.3


DEUTERONOMY 22:11
Thou shalt not wear a garment of diverse sorts, [as] of woollen and linen together

 

Offline mikhael

  • Back to skool
  • 211
  • Fnord!
    • http://www.google.com/search?q=404error.com
Quote
Originally posted by LtNarol
So decals are not meant to be limited to predefined areas like squad logos?  (I'm feeling dumber every minute, bear with me here)


DAMAGE decals, Narol. Think of when you shoot up walls in a First Person Shooter. The bullet holes are applied with decals.
[I am not really here. This post is entirely a figment of your imagination.]

 

Offline KARMA

  • Darth Hutt
  • 211
    • http://members.fortunecity.com/aranbanjo
stupid questions(don't kill me plz!!:)):

stupid question 1:
i did not understand if your problem is to calculate the position or (as i think) to apply the effect, in the first case can't you use the code for the "fire column" effect when you hit the hull of a ship? the column appear in the point where the lasers hit the hull, so maybe there is something you can use in the code

stupid question 2:
tweaking the decal code -when it will work- will be impossible to realize the virtual shield effect that was discussed sometimes ago? i mean.... the only differences seems to me that the virtual shield is an animated effect+ that it is not persistent. (with virtual shield i consider the effect you see in many games to represent shields for big ships: shields are not a mesh, simply when you hit a ships with shield>0 you see the virtual shield effect, if shield=0 you see decals)

 

Offline Rampage

  • Son Of Rampage
  • 211
  • Urogynaecologist
Bobboau, let my inexperienced knowledge in complex vector calculus guide you.  :p

My suggestion is that you set some vector-valued equation in rectangular coordinates (A circle might work... r=x^2[i+y^2j)

Then use Stokes' Theorm to find the normal of the vector function.  The normal being the position where [roughly] the shot was fired.  After, the shot will cast the decal, the circle or what-not.

Code: [Select]
Stokes' Theorm

     /                                   /    /
     |                                   |    |
     |  [b]F[/b]*d[b]r[/b] =                           |    | ([b]curl F[/b])*N dS
     |                                   |    |
    /  C                                 / S /


That's the notorious theorm that could help you a lot.  Although you probably have the thing programmed into your TI-89 or what-not.

Hope this helped. :)

 

Offline Goober5000

  • HLP Loremaster
  • Moderator
  • 214
    • Goober5000 Productions
:wtf: :wtf: :wtf:

I'm not sure how that'll help here.  Of course, I forget most of all the Calculus III I had two years ago... :p

Rampage, it seems that Bobboau's problem is transforming a cube into orthogonal coordinates.  In other words, he has a cube rotated to an arbitrary orientation, and he needs to know what the vertices and measurements would be if the cube was rotated to align with the x, y, and z axes.

Bobboau, how does that cube matrix specify the orientation?

 

Offline daveb

  • WHEE!!
  • 25
Ok, this is a tremendously huge simplification of things, but there are 2 classic ways to solving this problem, which share some common ideas.


Common stuff
-----------------

- define a volume (typically an axis-aligned box) which represents the volume of space you'd have if you projected a square bitmap (the decal) forward. create 4 planes which represent the "sides" of this box if you were looking at the bitmap itself as the "top". Think of it like a cookie cutter.

- rotate this volume into the model coords of the mesh you want to project onto. In Freespace math-speak, to rotate a point in world space into the model space of an object, you do something like :

vector world_point = world_point - object->pos;
vm_vec_rotate(world_point, object->orient);  // NOT an unrotate!

- for each face in the model, do a quick backfacing check to see if the normal of the face is pointing in the same direction as the projection of the decal - if so, it can be discarded, otherwise calculate an axis-aligned bounding box that encompasses all the points. If the bounding box for the face does not intersect the bounding box for the decal, you can discard it since it will never have a decal projected on it. Otherwise continue.

- for each plane defined in step one, clip the face in 3d space. This is probably the most expensive part and certainly the most annoying/hard to write.

- if, after you've clipped the face successively against all 4 planes and you still have points left, these points represent the resulting part of the polygon that the decal projects on to. At this point, you go one of two directions.


Method 1 "stickers"
-----------------------

- using a little trig you can figure out what the texture coords of the decal are on the resulting points.

- You now have a bunch of model space polygons with proper uv decal coords. After the base model is drawn, simply iterate over all the decal faces and draw them with read-only zbuffer. While this works, there's a 99% chance you'll get zbuffer fighting (the "venetian blind" effect you get with overlapping polygons). This can be hacked around using hard z-biasing but is generally going to be problematic.


Method 2 "multipass"
---------------------------

- instead of using the clipped points as a decal, treat the entire original face as part of the decal and calculate UV's for the vertices based on the clipped coords. If you have texture clamping enabled, and you have a 1-pixel border of transparency/nothing in your decal bitmap, things should just work.

- Now you just draw each face that has a decal on it twice. Once with the base texture, and once using read-only zbuffer using the decal bitmap with the generated uv coords. Because the verts are -exactly- the same in both passes, you avoid zbuffer fighting.


Method 2 is a much preferable method, and is much much less likely to result in  "but it doesn't work on MY VIDEO CARD!" sorts of situations.   Anyway, clear as mud I'm sure.  Hopefully it'll help ol' Bob here get pointed in the right direction. Its a very very ugly piece of code to write.
« Last Edit: November 26, 2002, 05:45:26 pm by 700 »

 

Offline LtNarol

  • Biased Banshee
  • 211
    • http://www.3dap.com/hlp/hosted/the158th
Quote
Originally posted by mikhael


DAMAGE decals, Narol. Think of when you shoot up walls in a First Person Shooter. The bullet holes are applied with decals.
OHHH! I get it, this whole time I was thinking of like different detail/paint decals to make certain individual ships unique, but now I see what you mean; that explains the 'need to be applied on the go' comment too...I feel really dumb.

To the point though, what kind of math is currently being used to locate points on ships for those impact spew animations?

 

Offline Bobboau

  • Just a MODern kinda guy
    Just MODerately cool
    And MODest too
  • 213
I've been sick for the last few days so I only started reworking this last night,
I didn't see any good distance from plane function so I made one my self, would someone tell me if I got this little bit right
Code: [Select]
//tells distance from a plain to a point-Bobboau
float fvi_point_dist_plane( vector *plane_pnt, vector *plane_norm, // Plane description, a point and a normal
   vector *point //a point to test
)
{
float dist,D;

D = -vm_vec_dot(plane_norm,plane_pnt);

dist = vm_vec_dot(plane_norm, point) + D;
return dist;
}


plane_pnt is a point on you're plane
plane_norm is the plane's normal
point is the point in question
it should return > 0 if the point is in front of the plane, < 0 if behind, and 0 if right on the plane.

in the decal code I start an intersection test from the first point that is in front of each of the six planes (I'm checking the top and bottom of my volume) and after the first intersection I don't copy any vert data untill I get an other one

might as well post the current decal code
I have this all in a interpeter, like the rendering and colision code has, it's fairly similar to the colision code up to this part
anything that you can't see defined is probly a global
this is only a few hours of work and it doesn't work at all yet, but from what I can see in the debug spew  I'm working along the right path
oh, I'm trying method 1 first becase it sounds like it would be the easiest (I already have the rendering system and data structures set up for it)
Code: [Select]
void decal_create_tmappoly(ubyte * p)
{
mprintf(("entering decal_create_tmappoly\n"));

int i;
int nv;
model_tmap_vert *verts;

nv = dw(p+36);
if ( nv < 0 ) return;

verts = (model_tmap_vert *)(p+44);
vector temppoly[820];

for (i=0;i {
decal_poly[i] = (int)verts[i].vertnum;
temppoly[i].xyz = decal_point_list[decal_poly[i]]->xyz;
}
//poly culling
vector pcenter;
vm_vec_avg_n(&pcenter, nv, temppoly);
float pradius = 0;
float dist = 0;
for (i=0;i {
dist = vm_vec_dist(decal_point_list[decal_poly[i]], &pcenter);
if(dist>pradius){
pradius = dist;
}
}

//if it's too far to posably get near the cube get out
if(vm_vec_dist_quick(&pcenter, &decal_hit_point) >= (pradius + decal_hit_radius)){
mprintf(("leaveing becase poly is too far away\n"));
return;
}
//poly culling
int temp_poly[820];

int skip = 0, numv = 0;

mprintf(("starting to test the poly, with %d verts in it\n",nv));
for(int k = 0; k<6; k++){
//find the first point in front of the plain
int first_good = -1;
for(i = 0; ((i< nv) && (first_good == -1)); i++){
mprintf(("testing point %d with plane %d\n", i, k));
if(fvi_point_dist_plane(&decal_cube_plane[k][0], &decal_cube_plane[k][1], decal_point_list[decal_poly[i]]) > 0){
first_good = i;
mprintf(("%d is the first good point\n", i));
}
}
//first point in front of the plane is good of corse
if(first_good == -1)continue;
temp_poly[0] = first_good;
numv = 0;
//go through each point and see if there is an intersection between it the next point and the current plane
//if there is then make the intersection point the next point in the poly
//ignor all points untill there is another intersection
//other wise make the next point the next point in the poly
for(i = first_good; i < (nv + first_good); i++){
mprintf(("looking for intersections between point %d and point %d, with plane %d\n", i%nv, (i + 1)%nv, k));
if(fvi_segment_plane(&new_decal.vert[nverts], &decal_cube_plane[k][0], &decal_cube_plane[k][1], decal_point_list[decal_poly[i%nv]], decal_point_list[decal_poly[(i + 1)%nv]], 0)){
mprintf(("segment %d %d has an an itersection\n", i%nv, (i + 1)%nv));
decal_point_list[nverts] = &new_decal.vert[nverts];
mprintf(("new decal defpoint has been added as number %d at x %0.2f y %0.2f z %0.2f\n",nverts, new_decal.vert[nverts].xyz.x, new_decal.vert[nverts].xyz.y, new_decal.vert[nverts].xyz.z));
temp_poly[(i+1)%nv] = nverts++;
mprintf(("temp_poly point %d, was set to defpoint %d\n",(i+1)%nv, nverts-1));
skip = (skip+1)%2;
mprintf(("skip has been set to %d\n",skip));
numv++;
}else{
if(skip == 0){
mprintf(("segment %d %d has no itersection, copying\n", i%nv, (i + 1)%nv));
temp_poly[(i+1)%nv] = decal_poly[(i + 1)%nv];
numv++;
}else{
mprintf(("skipping segment %d %d becase it isn't in front of the plane\n", i%nv, (i + 1)%nv));
}
}
}
for(int h = 0; h < numv; h++)decal_poly[h] = temp_poly[h];
nv = numv;
}

mprintf(("copyint the poly to the decal, number %d\n", poly_num));
//copy a triangulated version of the poly to the new decal
for (i=1;i<(nv-1);i++) {
new_decal.poly[poly_num].point[0] = decal_poly[0];
new_decal.poly[poly_num].point[i] = decal_poly[i];
new_decal.poly[poly_num].point[i+1] = decal_poly[i+1];
}

poly_num++;
}

this is the first pass, so it's prety ugly

the volume I define is all ready in the models frame of reference (or it should be), and I was going to assign a diferent texture to backfaced polies (I'm useing a cube not just an infinitely extruded square, so this should only effect polys on thin model sections), also I'm useing a distance check thing to cull polys rather than bounding boxes (seemed like it would work better, or easier at least, even though it may give false positives),
assuming I'm setting the gloabals corectly I think this is almost working (for setting the geometry), I'm going to set UV coordanants baised on how far they are from the plains (sort of like a normal planer uv projection, but I was thinking about including the top and bottom of the cube so the coords are sort of baised on the distance from the center, cubic projection)
Bobboau, bringing you products that work... in theory
learn to use PCS
creator of the ProXimus Procedural Texture and Effect Generator
My latest build of PCS2, get it while it's hot!
PCS 2.0.3


DEUTERONOMY 22:11
Thou shalt not wear a garment of diverse sorts, [as] of woollen and linen together

 

Offline Galemp

  • Actual father of Samus
  • 212
  • Ask me about GORT!
    • Steam
    • User page on the FreeSpace Wiki
*reads thread*

:blah: :confused:
Eh, nice job so far, Bob. Good luck.

*goes back to work and waits for screenshots*
"Anyone can do any amount of work, provided it isn't the work he's supposed to be doing at that moment." -- Robert Benchley

Members I've personally met: RedStreblo, Goober5000, Sandwich, Splinter, Su-tehp, Hippo, CP5670, Terran Emperor, Karajorma, Dekker, McCall, Admiral Wolf, mxlm, RedSniper, Stealth, Black Wolf...

 

Offline Bobboau

  • Just a MODern kinda guy
    Just MODerately cool
    And MODest too
  • 213
ok I've gotten it nearly working, good enough to show off at least, the new decal code is still slow, but good enough for now, under most sercomstances it seems to work well (I've been testing it only on large ships, so there may be some badness on fighter sized ships) though it does seem to have a few problems near multable edges, it is like I said, good enough to show off

this has only been about three days of work, so I think I've done quite well

I would like to give a particular thanks to dave for showing me the way, thanks
:wink:
Bobboau, bringing you products that work... in theory
learn to use PCS
creator of the ProXimus Procedural Texture and Effect Generator
My latest build of PCS2, get it while it's hot!
PCS 2.0.3


DEUTERONOMY 22:11
Thou shalt not wear a garment of diverse sorts, [as] of woollen and linen together

 

Offline Bobboau

  • Just a MODern kinda guy
    Just MODerately cool
    And MODest too
  • 213
forgot the code
this is the setup function it doesn't realy do the hard part, it just sets up the globals for the decal basicly.
Code: [Select]
int decal_create(object * obj, decal_point *point, int subobject, int texture){
mprintf(("a decal is about to be made at %0.2f, %0.2f, %0.2f\n", point->pnt.xyz.x, point->pnt.xyz.y, point->pnt.xyz.z));

if(obj->type != OBJ_SHIP){
return 0;
}

vector center = point->pnt;
float rad = point->radius * 2;
if(rad <=0) rad = 10;
mprintf(("radius %f\n",rad));
vector plain_point[4];
vector cube_point[8];
//define the decals dimentions
plain_point[0] = point->orient.vec.uvec;
plain_point[1] = plain_point[0];
vm_vec_negate(&plain_point[1]);
plain_point[2] = point->orient.vec.rvec;
plain_point[3] = plain_point[2];
vm_vec_negate(&plain_point[3]);

vector topcenter;
vector bvec = point->orient.vec.fvec;
vm_vec_negate(&bvec);
vm_vec_scale_add(&topcenter, ¢er, &bvec, rad);

for(int i = 0; i < 4; i++){
vm_vec_scale_add( &cube_point[i], &topcenter, &plain_point[i], rad );
vm_vec_scale_add( &cube_point[i+4], &cube_point[i], &point->orient.vec.fvec, rad*2);
}

float max_rad = vm_vec_dist_quick(¢er, &cube_point[0]); //the cube points are all equidistant, right?
// float min_rad = rad; //the cube points are all equidistant, right?
mprintf(("decal defined\n"));

//define the decals dimentions

//set up the decal model
ship *shipp = &Ships[obj->instance];
decal *sdec = shipp->decals;

polymodel *pm = model_get(shipp->modelnum);
bsp_info * sm;
sm = &pm->submodel[subobject];
// decal_model dmod = pm->submodel[subobject].dec_model;// sm->dec_model;
// decal_model tdec; //temporary decal model for holding the culled down part of the decal

//setting up the decal cube
vector test_vec, temp1, temp2;
for(i = 0; i<8; i++)decal_cube_point[i] = cube_point[i];

decal_orient = point->orient;

decal_cube_plane[0][0] = cube_point[5];

temp1 = decal_orient.vec.uvec;
temp2 = decal_orient.vec.rvec;

vm_vec_avg(&test_vec, &temp1, &temp2);
vm_vec_normalize(&test_vec);

decal_cube_plane[0][1] = test_vec;

mprintf(("plane 0 position is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[0][0].xyz.x, decal_cube_plane[0][0].xyz.y, decal_cube_plane[0][0].xyz.z));
mprintf(("plane 0 normal is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[0][1].xyz.x, decal_cube_plane[0][1].xyz.y, decal_cube_plane[0][1].xyz.z));



decal_cube_plane[1][0] = cube_point[0];

vm_vec_negate(&test_vec);

decal_cube_plane[1][1] = test_vec;
mprintf(("plane 1 position is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[1][0].xyz.x, decal_cube_plane[1][0].xyz.y, decal_cube_plane[1][0].xyz.z));
mprintf(("plane 1 normal is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[1][1].xyz.x, decal_cube_plane[1][1].xyz.y, decal_cube_plane[1][1].xyz.z));



decal_cube_plane[2][0] = cube_point[5];

vm_vec_negate(&temp2);
vm_vec_avg(&test_vec, &temp1, &temp2);
vm_vec_normalize(&test_vec);

decal_cube_plane[2][1] = test_vec;

mprintf(("plane 2 position is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[2][0].xyz.x, decal_cube_plane[2][0].xyz.y, decal_cube_plane[2][0].xyz.z));
mprintf(("plane 2 normal is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[2][1].xyz.x, decal_cube_plane[2][1].xyz.y, decal_cube_plane[2][1].xyz.z));



decal_cube_plane[3][0] = cube_point[0];

vm_vec_negate(&test_vec);

decal_cube_plane[3][1] = test_vec;

mprintf(("plane 3 position is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[3][0].xyz.x, decal_cube_plane[3][0].xyz.y, decal_cube_plane[3][0].xyz.z));
mprintf(("plane 3 normal is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[3][1].xyz.x, decal_cube_plane[3][1].xyz.y, decal_cube_plane[3][1].xyz.z));



test_vec = decal_orient.vec.fvec;

decal_cube_plane[4][0] = cube_point[0];

decal_cube_plane[4][1] = test_vec;

mprintf(("plane 4 position is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[4][0].xyz.x, decal_cube_plane[4][0].xyz.y, decal_cube_plane[4][0].xyz.z));
mprintf(("plane 4 normal is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[4][1].xyz.x, decal_cube_plane[4][1].xyz.y, decal_cube_plane[4][1].xyz.z));



vm_vec_negate(&test_vec);
decal_cube_plane[5][0] = cube_point[5];

decal_cube_plane[5][1] = test_vec;

mprintf(("plane 5 position is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[5][0].xyz.x, decal_cube_plane[5][0].xyz.y, decal_cube_plane[5][0].xyz.z));
mprintf(("plane 5 normal is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[5][1].xyz.x, decal_cube_plane[5][1].xyz.y, decal_cube_plane[5][1].xyz.z));
//setting up the decal cube

mprintf(("cube set up\n"));

decal_hit_point = point->pnt;
decal_hit_radius = max_rad;
poly_num = 0;
nverts = 0;

//go and find decals for each submodel
// for(int z = 0; zn_models;z++){

new_decal = &shipp->decals[0];


decal_create_sub((ubyte *)pm->submodel[subobject].bsp_data);
pm->submodel[subobject].dec_model = d_model;

// }
// for(i=0; i// sdec[0].vert[i].xyz = new_decal.vert[i].xyz;
// mprintf(("decal point %d being set to x %0.2f y %0.2f z %0.2f\n", i, sdec[0].vert[i].xyz.x, sdec[0].vert[i].xyz.y, sdec[0].vert[i].xyz.z));
// }

for(i=0; i for(int k=0; k<3; k++){
sdec[0].poly[i].uv[k].u = 0.5f;
sdec[0].poly[i].uv[k].v = 0.5f;
// sdec[0].poly[i].point[k] = new_decal.poly[i].point[k];
// mprintf(("decal point %d being set to %d x %0.2f y %0.2f z %0.2f\n", i, sdec[0].poly[i].point[k], sdec[0].vert[sdec[0].poly[i].point[k]].xyz.x, sdec[0].vert[sdec[0].poly[i].point[k]].xyz.y, sdec[0].vert[sdec[0].poly[i].point[k]].xyz.z));
}
}

sdec[0].texture = texture;
sdec[0].is_valid = 1;
sdec[0].timestamp = timestamp();
sdec[0].n_poly = poly_num;

mprintf(("a decal should have been made with %d polys\n",sdec[0].n_poly));


return 1;
}

here are a few globals, some are a tiny bit bigger than they need to be, and I shall soon give them a more sane size
Code: [Select]
int poly_num = 0;

static vector decal_cube_point[8];
static vector decal_cube_plane[6][2];
static vector decal_hit_point;
static float decal_hit_radius;

static matrix decal_orient;

static vector * decal_point_list[3500];

static int decal_poly[820];

static decal * new_decal;

static int nverts;


interpeter code altered from the model colision code, the tmap_poly part is the only realy origonal part, but it is the part that does all the work

Code: [Select]
int decal_create_sub(void *model_ptr )
{

// mprintf(("plane 0 position is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[0][0].xyz.x, decal_cube_plane[0][0].xyz.y, decal_cube_plane[0][0].xyz.z));
// mprintf(("plane 0 normal is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[0][1].xyz.x, decal_cube_plane[0][1].xyz.y, decal_cube_plane[0][1].xyz.z));

// mprintf(("entering decal_create_sub\n"));

ubyte *p = (ubyte *)model_ptr;
int chunk_type, chunk_size;

chunk_type = dw(p);
chunk_size = dw(p+4);

// mprintf(("plane 0 position is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[0][0].xyz.x, decal_cube_plane[0][0].xyz.y, decal_cube_plane[0][0].xyz.z));
// mprintf(("plane 0 normal is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[0][1].xyz.x, decal_cube_plane[0][1].xyz.y, decal_cube_plane[0][1].xyz.z));


while (chunk_type != DP_EOF) {

// mprintf(( "Processing chunk type %d, len=%d\n", chunk_type, chunk_size ));
// mprintf(("plane 0 position is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[0][0].xyz.x, decal_cube_plane[0][0].xyz.y, decal_cube_plane[0][0].xyz.z));
// mprintf(("plane 0 normal is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[0][1].xyz.x, decal_cube_plane[0][1].xyz.y, decal_cube_plane[0][1].xyz.z));


switch (chunk_type) {
case DP_EOF: return 1;
case DP_DEFPOINTS: decal_create_defpoints(p); break;
case DP_FLATPOLY: break;// I don't want any of these anyway-Bobboau decal_create_flatpoly(p); break;
case DP_TMAPPOLY: decal_create_tmappoly(p); break;
case DP_SORTNORM: decal_create_sortnorm(p); break;
case DP_BOUNDBOX:
/* if (!mc_ray_boundingbox( vp(p+8), vp(p+20), &Mc_p0, &Mc_direction, NULL )) {
return 1;
}*/
break;
default:
mprintf(( "Bad chunk type %d, len=%d in decal_create_sub\n", chunk_type, chunk_size ));
Int3(); // Bad chunk type!
return 0;
}
// mprintf(( "current chunk offset %d\n", (int)p ));

p += chunk_size;
chunk_type = dw(p);
chunk_size = dw(p+4);
}


return 1;
}



Code: [Select]
void decal_create_defpoints(ubyte * p )
{
// mprintf(("entering decal decal_create_defpoints\n"));


int n;
nverts = dw(p+8);
int offset = dw(p+16);

mprintf(("%d verts\n",nverts));
ubyte * normcount = p+20;
vector *src = dvp(p+offset);

Assert( nverts < 1200 );



for (n=0; n {


decal_point_list[n] = src;
new_decal->vert[n].xyz = src->xyz;
src += normcount[n]+1;
// mprintf(("defpoint %d, x %0.2f, y %0.2f, z %0.2f\n",n,d_model.vert[n].xyz.x,d_model.vert[n].xyz.y,d_model.vert[n].xyz.z));
}

}


Code: [Select]
void decal_create_sortnorm(ubyte * p)
{
// mprintf(("entering decal_create_sortnorm\n"));
int frontlist = dw(p+36);
int backlist = dw(p+40);
int prelist = dw(p+44);
int postlist = dw(p+48);
int onlist = dw(p+52);
/*
if ( Mc_pm->version >= 2000 ) {
if (!mc_ray_boundingbox( vp(p+56), vp(p+68), &Mc_p0, &Mc_direction, NULL )) {
return;
}
}
*/
if (prelist) decal_create_sub(p+prelist);
if (backlist) decal_create_sub(p+backlist);
if (onlist) decal_create_sub(p+onlist);
if (frontlist) decal_create_sub(p+frontlist);
if (postlist) decal_create_sub(p+postlist);
}


Code: [Select]
void decal_create_tmappoly(ubyte * p)
{
mprintf(("entering decal_create_tmappoly\n"));

if(poly_num >= MAX_DECAL_POLY){
mprintf(("bugging out becase there are too many polys in the decal\n"));
}
int i;
int nv;
// uv_pair uvlist[TMAP_MAX_VERTS];
// vector points[TMAP_MAX_VERTS];
model_tmap_vert *verts;

nv = dw(p+36);
if ( nv < 0 ) return;

// int tmap_num = dw(p+40);
/*
if ( (!(Mc->flags & MC_CHECK_INVISIBLE_FACES)) && (Mc_pm->textures[tmap_num] < 0) ) {
// Don't check invisible polygons.
return;
}
*/
verts = (model_tmap_vert *)(p+44);
vector temppoly[820];

for (i=0;i {
decal_poly[i] = (int)verts[i].vertnum;
temppoly[i].xyz = decal_point_list[decal_poly[i]]->xyz;
}
//poly culling
vector pcenter;
vm_vec_avg_n(&pcenter, nv, temppoly);
float pradius = 0;
float dist = 0;
for (i=0;i {
dist = vm_vec_dist(decal_point_list[decal_poly[i]], &pcenter);
if(dist>pradius){
pradius = dist;
}
}

//if it's too far to posably get near the cube get out
if(vm_vec_dist_quick(&pcenter, &decal_hit_point) >= (pradius + decal_hit_radius)){
mprintf(("leaveing becase poly is too far away\n"));
return;
}
//poly culling
int temp_poly[820];

int skip = 0, numv = 0, valid = 0;

mprintf(("starting to test the poly, with %d verts in it\n",nv));
for(int k = 0; k<6; k++){
//find the first point in front of the plain
int first_good = -1;
for(i = 0; ((i< nv) && (first_good == -1)); i++){
mprintf(("testing point %d with plane %d\n", i, k));
mprintf(("point's position is x %0.2f y %0.2f z %0.2f\n", decal_point_list[decal_poly[i]]->xyz.x, decal_point_list[decal_poly[i]]->xyz.y, decal_point_list[decal_poly[i]]->xyz.z));
mprintf(("plane's position is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[k][0].xyz.x, decal_cube_plane[k][0].xyz.y, decal_cube_plane[k][0].xyz.z));
mprintf(("plane's normal is x %0.2f y %0.2f z %0.2f\n", decal_cube_plane[k][1].xyz.x, decal_cube_plane[k][1].xyz.y, decal_cube_plane[k][1].xyz.z));
if(fvi_point_dist_plane(&decal_cube_plane[k][0], &decal_cube_plane[k][1], decal_point_list[decal_poly[i]]) > 0){
first_good = i;
mprintf(("%d is the first good point\n", i));
}
}
if(first_good == -1){
mprintf(("all points are behind a plane, polygon is not in the cube\n"));
return;
}else{
valid = 1;
}

//first point in front of the plane is good of corse
// temp_poly[0] =  decal_poly[(first_good + nv)%nv];
numv = 0;
//go through each point and see if there is an intersection between it the next point and the current plane
//if there is then make the intersection point the next point in the poly
//ignor all points untill there is another intersection
//other wise make the next point the next point in the poly
// if(k==1)Int3();
for(i = first_good; i < (nv + first_good); i++){
mprintf(("looking for intersections between point %d and point %d, with plane %d\n", i%nv, (i + 1)%nv, k));
mprintf((" point %d, is at, x %0.2f y %0.2f z %0.2f and point %d, is at, x %0.2f y %0.2f z %0.2f\n", i%nv, decal_point_list[decal_poly[i]]->xyz.x, decal_point_list[decal_poly[i]]->xyz.y, decal_point_list[decal_poly[i]]->xyz.z,  (i + 1)%nv, decal_point_list[decal_poly[(i + 1)%nv]]->xyz.x, decal_point_list[decal_poly[(i + 1)%nv]]->xyz.y, decal_point_list[decal_poly[(i + 1)%nv]]->xyz.z));
if(fvi_segment_plane(&new_decal->vert[nverts], &decal_cube_plane[k][0], &decal_cube_plane[k][1], decal_point_list[decal_poly[i%nv]], decal_point_list[decal_poly[(i + 1)%nv]], 0)){
mprintf(("segment %d %d has an an itersection\n", i%nv, (i + 1)%nv));
decal_point_list[nverts] = &new_decal->vert[nverts];
mprintf(("new decal defpoint has been added as number %d at x %0.2f y %0.2f z %0.2f\n",nverts, new_decal->vert[nverts].xyz.x, new_decal->vert[nverts].xyz.y, new_decal->vert[nverts].xyz.z));
temp_poly[numv] = nverts++;
mprintf(("temp_poly point %d, should have been set to defpoint %d, it was set to %d\n",numv, nverts-1, temp_poly[numv]));
skip = (skip+1)%2;
mprintf(("skip has been set to %d\n",skip));
numv++;
if((skip == 0)){
mprintf(("adding point, becase it is after an intersection point\n", (i + 1)%nv));
temp_poly[numv] = decal_poly[(i + 1)%nv];
numv++;
}

}else{
if((skip == 0)){//don't copy the first point
mprintf(("segment %d %d has no itersection, copying\n", i%nv, (i + 1)%nv));
temp_poly[numv] = decal_poly[(i + 1)%nv];
numv++;
}else{
mprintf(("skipping segment %d %d becase it isn't in front of the plane\n", i%nv, (i + 1)%nv));
}
}
}

mprintf(("temp poly has %d points\n", numv));
for(int h = 0; h < numv; h++){
decal_poly[h] = temp_poly[h];
mprintf(("seting decal_poly %d to %d\n",h,temp_poly[h]));
}
nv = numv;
numv=0;
mprintf(("decal_poly now has has %d points\n", nv));
if(nv < 3)return; //if at any time we get fewer than three points this poly is dead
}

mprintf(("copying the poly to the decal\n"));
//copy a triangulated version of the poly to the new decal
if((valid == 1) && (nv > 2)){
for (i=1;i<(nv-1);i++) {
new_decal->poly[poly_num].point[0] = decal_poly[0];
new_decal->poly[poly_num].point[1] = decal_poly[i];
new_decal->poly[poly_num].point[2] = decal_poly[i+1];
mprintf(("decal poly %d, vert 0 being set to %d, vert 1 %d, and vert 2 %d\n", poly_num, new_decal->poly[poly_num].point[0], new_decal->poly[poly_num].point[1], new_decal->poly[poly_num].point[2]));
poly_num++;
}
}else{
// mprintf(("no poly, all points are out side of planes"));
}
mprintf(("there are now %d polys in the current decal\n", poly_num));


}

that last one is were the real work is done
it culls polys that couldn't posably be in the decal cube (based on the distance from the averaged center and the decal cube and poly's max radius + the cube's max radius)
then it goes plane by plane (there are six) and finds the first point that is in front of the current plane (if there are none it quits becase the poly is totaly out of the cube)
starting from that point it looks for an intersection between the curret point and the one after it. when it finds one it makes the intersection the next point and then checks for intersections until it finds another one then makes the second intersection the next point and the second point in the line segment the one after that. for every line segment that doesn't have an intersection it simply makes the second point the next poly point, untill it has gone through all points, then it does the same thing for every plane.
finaly it copys the poly to the current ship decal's poly list, by triangelateing it

I'm gona see if I can iron out some of the remaining bugs before getting into the UV calculation.

**update**
turns out that bug was real simple, I just had one line that I shouldn't have had, I fixed the bug in the posted code, and I'm updateing the test exe
« Last Edit: December 02, 2002, 03:13:04 am by 57 »
Bobboau, bringing you products that work... in theory
learn to use PCS
creator of the ProXimus Procedural Texture and Effect Generator
My latest build of PCS2, get it while it's hot!
PCS 2.0.3


DEUTERONOMY 22:11
Thou shalt not wear a garment of diverse sorts, [as] of woollen and linen together

 

Offline Sesquipedalian

  • Atankharz'ythi
  • 211
*Looks at code*
*Goes cross-eyed and starts to gibber*
*Recovers by thinking about penguins*

I am again awed, Bobboau. :yes:


Say, when you are done this, can I get you to look at making us a change-ai-level sexp?  Given the above, it ought to be a blindfolded, one-hand-behind-the-back task for you. :D
Sesqu... Sesqui... what?
Sesquipedalian, the best word in the English language.

The Scroll of Atankharzim | FS2 syntax highlighting

 

Offline Bobboau

  • Just a MODern kinda guy
    Just MODerately cool
    And MODest too
  • 213
another update, I've gotten a fairly working UV calculation up, I have updated the zip

I'm going to work on a system for getting more than one decal on a ship at a time, culling the oldest,
then I'm going to start integrateing it into the game,
I'm thinking I'm going to have the texture be an animation, when you hit the ship it will make the decal, play the animation across it and leave the last frame of the animation as the texture,
back faced polys will be given a diferen't texture than forward faced polys if you want them, otherwise they will be culled
first pass implementation, I will only give decals to type A beams, or other direct beams, becase there the only ones that can use the decal system as it is, I will make a specal system for slash beams, though I'm not sure how exactly I'm going to do it,

I'm also going to need to do a LOT of optomising, the decal code is good enough for the moment but it is intalorably slow for a final product.

the rendering needs vast improvement, the Z-buffering problems are minor (I was expecting far worse from dave's warnings) so that is more of a back burner issue,
more of a problem is I need to get them lit properly, last time I tried something like this it met with utter failure, I'm hopping to fair better this time around, finaly I am going to need some system for transparency maps, this is well out of my aria of expertese, if the decals get lit useing the normal transperency system we have now only the lightest parts will be visable, wich is quite the oposite of what it needs to be, also once lit the decals will be more see-through when darkend.
Bobboau, bringing you products that work... in theory
learn to use PCS
creator of the ProXimus Procedural Texture and Effect Generator
My latest build of PCS2, get it while it's hot!
PCS 2.0.3


DEUTERONOMY 22:11
Thou shalt not wear a garment of diverse sorts, [as] of woollen and linen together

 

Offline Galemp

  • Actual father of Samus
  • 212
  • Ask me about GORT!
    • Steam
    • User page on the FreeSpace Wiki
Very nice. :nod: Can you make decals enabled for bombs and Terran Huge and Megafunk turrets, too? Perhaps make it linked to the Huge tag in the weapons.tbl. I'd like to see bomb craters.
"Anyone can do any amount of work, provided it isn't the work he's supposed to be doing at that moment." -- Robert Benchley

Members I've personally met: RedStreblo, Goober5000, Sandwich, Splinter, Su-tehp, Hippo, CP5670, Terran Emperor, Karajorma, Dekker, McCall, Admiral Wolf, mxlm, RedSniper, Stealth, Black Wolf...