Path: chuka.playstation.co.uk!news From: Robert_Swan@scee.net (Robert) Newsgroups: scee.yaroze.programming.3d_graphics Subject: race game 3 design: step 1 Date: Fri, 18 Feb 2000 20:19:33 GMT Organization: PlayStation Net Yaroze (SCEE) Lines: 258 Message-ID: <38ada944.33392524@www.netyaroze-europe.com> Reply-To: Robert_Swan@scee.net NNTP-Posting-Host: mailgate.scee.sony.co.uk X-Newsreader: Forte Free Agent 1.11/32.235 STEP ONE NOTES: 1) best read in fixed sized font (maybe turn this into html later - but this is faster to write) 2) feel free to comment on any of this and ask questions 3) feel very free to point out mistakes Overall Aim: ------------ To have a racetrack that morphs between a high detail model for close up sectinos of road and a low detail model for far away sections. Step Aim: --------- To be able to create a new section of track from a high and lo detail resolution, and be able to modify the weight to allow smooth transition from low detail to high. This is all in theory - but is worthwhile planning so that the problem can be approached in a logical manner. The idea is for a high detail model to morph into the low detail model by moving its vertices until they are where they would be if the low detail model were to have those vertices. pseudo code =========== // variables: arguments VECTOR Vhi = {Xhi, Yhi, Zhi}; // hi detail coordinate VECTOR Vlo = {Xlo, Ylo, Zlo}; // lo detail coordinate unsigned int res; // resolution of blending unsigned int c; // coefficient of blending where 0 < c < res // variables: result VECTOR Vnew; // morphed coordinate // code Vnew.vx = (Xhi * c) + (Xlo * (res-c)) / res; Vnew.vy = (Yhi * c) + (Ylo * (res-c)) / res; Vnew.vz = (Zhi * c) + (Zlo * (res-c)) / res; =========== The calculation is 6 multiplies, 3 subtractions, and 3 divides. Making res a power of 2 you get 6 multiplies, 3 subtractions, and 3 bit shifts - a fast and generally free operation. This works where a vertex exists in both the MODhi and MODlo. By definition the MODlo has less vertices so some form of interpolation must be done to create the 'assumed' Vlo for those vertices that dont exist in MODlo. There has to be some information to determine the relative position of the 'assumed' Vlo to create it from the MODlo. For quick calculation the 'assumed' Vlos it is easiest to determine that they lie somewhere on a straight line between two vertices on the MODlo as you can use a form of the above creation to compute it. pseudo code =========== // variables: arguments VECTOR Vlo1 = {Xlo1, Ylo1, Zlo1}; // lo detail coordinate VECTOR Vlo2 = {Xlo2, Ylo2, Zlo2}; // lo detail coordinate unsigned int total; // number to represent total distance from Vlo1 to Vlo2 unsigned int dist; // distance from Vlo1 to Vlo2 as fraction of total // variables: result VECTOR Va; // calculated coordinate // code Va.vx = (Xlo1 * dist) + (Xlo2 * (total-dist)) / total; Va.vy = (Ylo1 * dist) + (Ylo2 * (total-dist)) / total; Va.vz = (Zlo1 * dist) + (Zlo2 * (total-dist)) / total; =========== the idea of using any values for total and dist is used for clarity - but you end up with divides. Using powers of two makes for much neater calculations - taken to extremes assume Va is halfway between Vlo1 and Vlo2. pseudo code =========== // variables: arguments VECTOR Vlo1 = {Xlo1, Ylo1, Zlo1}; // lo detail coordinate VECTOR Vlo2 = {Xlo2, Ylo2, Zlo2}; // lo detail coordinate // variables: result VECTOR Va; // calculated coordinate // code Va.vx = (Xlo1 + Xlo2) >> 1; Va.vy = (Ylo1 + Ylo2) >> 1; Va.vz = (Zlo1 + Zlo2) >> 1; Thats pretty neat - to use this sort of equation the MODhi must have (2^n+1) times more vertices than MODlo in any one axis (see diagram below). The lowest detail a section of track can be is 1x1, so I'll pick the resolution of MODhi to be 9x5 vertices. This allows enough detail for the track and also for any side detail that needs to be modelled and subject to what will be high subdivision. So given a MODlo and a MODhi, a place to create MODmorph and a morphing constant you get two steps:- 1) use MODlo to create data for a MODtemp - this is basically the MODlo expanded to have vertices that will correspond to the MODhi 2) use the MODtemp and MODhi to create your MODmorph. Step 1 can have its result placed in MODmorph - which has the results of step 2 written over it pseudo code =========== // numbering of vertices in Vlo (subject to change) // 00 ------------------------------------ 01 // | | // | | // | | // | | // | | // | | // | | // 02 ------------------------------------ 03 // numbering of vertices in Vhi amd Vmorph arrays (subject to change) // 00 - 01 - 02 - 03 - 04 - 05 - 06 - 07 - 08 // | | | | | | | | | // 09 - 10 - 11 - 12 - 13 - 14 - 15 - 16 - 17 // | | | | | | | | | // 18 - 19 - 20 - 21 - 22 - 23 - 24 - 25 - 26 // | | | | | | | | | // 27 - 28 - 29 - 30 - 31 - 32 - 33 - 34 - 35 // | | | | | | | | | // 36 - 37 - 38 - 39 - 40 - 41 - 42 - 43 - 44 // defines to make things a bit easier on the eye #define VECTOR_AVERAGE( target, source1, source2) \ (target)->vx = ((source1)->vx + (source2)->vx) >> 1; \ (target)->vy = ((source1)->vy + (source2)->vy) >> 1; \ (target)->vz = ((source1)->vz + (source2)->vz) >> 1; // variables: arguments (assume they are already set) VECTOR Vlo[4]; // variables: result VECTOR Vmorph[9*5]; VECTOR *pV; int i; // code // copy the Vlo corners - they are same Vmorph[00] = Vlo[00]; Vmorph[08] = Vlo[01]; Vmorph[36] = Vlo[02]; Vmorph[44] = Vlo[03]; // use Vlo to create the points between the corners VECTOR_AVERAGE( *Vmorph[03], *Vlo[00], *Vlo[08]); VECTOR_AVERAGE( *Vmorph[40], *Vlo[02], *Vlo[03]); VECTOR_AVERAGE( *Vmorph[18], *Vlo[00], *Vlo[02]); VECTOR_AVERAGE( *Vmorph[26], *Vlo[01], *Vlo[03]); // use the generated Vmorph points to create the top and bottom row pV = &Vmorph[0]; for( i=0; i<2; i++, pV+=36) { VECTOR_AVERAGE( pV+2, pV+0, pV+4); VECTOR_AVERAGE( pV+6, pV+0, pV+2); VECTOR_AVERAGE( pV+1, pV+4, pV+2); VECTOR_AVERAGE( pV+3, pV+4, pV+8); VECTOR_AVERAGE( pV+5, pV+4, pV+6); VECTOR_AVERAGE( pV+7, pV+6, pV+8); } // use the generated Vmorph points to create each column pV = &Vmorph[0]; for( i=0; i<7; i++, vP+=1) { VECTOR_AVERAGE( pV+18, pV+00, pV+36); VECTOR_AVERAGE( pV+09, pV+00, pV+18); VECTOR_AVERAGE( pV+27, pV+36, pV+18); } =========== ok - so now Vmorph holds the equivalent shape of MODlo but with the resoltuion of MODhi. It can now be used for step 2. NOTE - using integer maths in this way will probably lead to pretty inaccurate Vmorph vertices - conceptually its fine - there may be many better ways of speeding it up/ increasing its efficency later. pseudo code =========== // variables: arguments (assume they are already set) unsigned int ratio; // out of 32 VECTOR *pVmorph, *pVhi; // code pVmorph = &Vmorpg[0]; pVhi = &Vhi[0]; int i; for( i=0; i<45; i++, pVmorph++, pVhi++) { pVmorph->vx = ((pVmorph->vx * ratio) + (pVhi->vx * 32-ratio)) / 32; pVmorph->vy = ((pVmorph->vy * ratio) + (pVhi->vy * 32-ratio)) / 32; pVmorph->vz = ((pVmorph->vz * ratio) + (pVhi->vz * 32-ratio)) / 32; } =========== So - given a MODlo, a MODhi, and a ratio you can create a morphed section of track in MODmorph. Further refinement of these ideas should allow for more control and greater smoothing. Disclaimer: Anything I say has no direct relation to where I work (Sony), is not an official voice of where I work (Sony) and Sony doesn't even exist as far as I'm concerned.