terrain.cpp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. /*
  19. Todo:
  20. immediate:
  21. Texture placement
  22. New map format
  23. q3map
  24. later:
  25. Smoothing brush
  26. Stitching terrains together
  27. Cross terrain selection
  28. Terrain_ApplyMatrix
  29. UpdateTerrainInspector
  30. */
  31. #include "stdafx.h"
  32. #include "qe3.h"
  33. #include "DialogInfo.h"
  34. #include "assert.h"
  35. //random in the range [0, 1]
  36. #define random() ((rand () & 0x7fff) / ((float)0x7fff))
  37. //random in the range [-1, 1]
  38. #define crandom() (2.0 * (random() - 0.5))
  39. typedef struct {
  40. int index;
  41. vec3_t xyz;
  42. vec4_t rgba;
  43. vec2_t tc;
  44. } terravert_t;
  45. /*
  46. ==============
  47. Terrain_SetEpair
  48. sets an epair for the given patch
  49. ==============
  50. */
  51. void Terrain_SetEpair( terrainMesh_t *p, const char *pKey, const char *pValue ) {
  52. if ( g_qeglobals.m_bBrushPrimitMode ) {
  53. SetKeyValue( p->epairs, pKey, pValue );
  54. }
  55. }
  56. /*
  57. =================
  58. Terrain_GetKeyValue
  59. =================
  60. */
  61. const char *Terrain_GetKeyValue( terrainMesh_t *p, const char *pKey ) {
  62. if ( g_qeglobals.m_bBrushPrimitMode ) {
  63. return ValueForKey( p->epairs, pKey );
  64. }
  65. return "";
  66. }
  67. /*
  68. ==================
  69. Terrain_MemorySize
  70. ==================
  71. */
  72. int Terrain_MemorySize( terrainMesh_t *p ) {
  73. return _msize( p );
  74. }
  75. void Terrain_GetVert( terrainMesh_t *pm, int x, int y, float s, float t, terravert_t *v, qtexture_t *texture = NULL ) {
  76. terrainVert_t *cell;
  77. v->index = x + y * pm->width;
  78. cell = &pm->heightmap[ v->index ];
  79. v->xyz[ 0 ] = pm->origin[ 0 ] + x * pm->scale_x;
  80. v->xyz[ 1 ] = pm->origin[ 1 ] + y * pm->scale_y;
  81. v->xyz[ 2 ] = pm->origin[ 2 ] + cell->height;
  82. VectorCopy( cell->rgba, v->rgba );
  83. if ( !texture || ( texture == cell->tri.texture ) ) {
  84. v->rgba[ 3 ] = 1.0f;
  85. } else {
  86. v->rgba[ 3 ] = 0.0f;
  87. }
  88. v->tc[ 0 ] = s;
  89. v->tc[ 1 ] = t;
  90. }
  91. void Terrain_GetTriangles( terrainMesh_t *pm, int x, int y, terravert_t *a0, terravert_t *a1, terravert_t *a2, terravert_t *b0, terravert_t *b1, terravert_t *b2, qtexture_t *texture ) {
  92. if ( ( x + y ) & 1 ) {
  93. // first tri
  94. Terrain_GetVert( pm, x, y, 1.0f, 1.0f, a0, texture );
  95. Terrain_GetVert( pm, x, y + 1, 1.0f, 0.0f, a1, texture );
  96. Terrain_GetVert( pm, x + 1, y + 1, 0.0f, 0.0f, a2, texture );
  97. // second tri
  98. *b0 = *a2;
  99. Terrain_GetVert( pm, x + 1, y, 0.0f, 1.0f, b1, texture );
  100. *b2 = *a0;
  101. } else {
  102. // first tri
  103. Terrain_GetVert( pm, x, y, 1.0f, 1.0f, a0, texture );
  104. Terrain_GetVert( pm, x, y + 1, 1.0f, 0.0f, a1, texture );
  105. Terrain_GetVert( pm, x + 1, y, 0.0f, 1.0f, a2, texture );
  106. // second tri
  107. *b0 = *a2;
  108. *b1 = *a1;
  109. Terrain_GetVert( pm, x + 1, y + 1, 0.0f, 0.0f, b2, texture );
  110. }
  111. }
  112. void Terrain_GetTriangle( terrainMesh_t *pm, int index, terravert_t *a0, terravert_t *a1, terravert_t *a2 ) {
  113. int x;
  114. int y;
  115. int which;
  116. which = index & 1;
  117. index >>= 1;
  118. y = index / pm->width;
  119. x = index % pm->width;
  120. if ( ( x + y ) & 1 ) {
  121. if ( !which ) {
  122. // first tri
  123. Terrain_GetVert( pm, x, y, 1.0f, 1.0f, a0 );
  124. Terrain_GetVert( pm, x, y + 1, 1.0f, 0.0f, a1 );
  125. Terrain_GetVert( pm, x + 1, y + 1, 0.0f, 0.0f, a2 );
  126. } else {
  127. Terrain_GetVert( pm, x + 1, y + 1, 0.0f, 0.0f, a0 );
  128. Terrain_GetVert( pm, x + 1, y, 0.0f, 1.0f, a1 );
  129. Terrain_GetVert( pm, x, y, 1.0f, 1.0f, a2 );
  130. }
  131. } else {
  132. if ( !which ) {
  133. // first tri
  134. Terrain_GetVert( pm, x, y, 1.0f, 1.0f, a0 );
  135. Terrain_GetVert( pm, x, y + 1, 1.0f, 0.0f, a1 );
  136. Terrain_GetVert( pm, x + 1, y, 0.0f, 1.0f, a2 );
  137. } else {
  138. Terrain_GetVert( pm, x + 1, y, 0.0f, 1.0f, a0 );
  139. Terrain_GetVert( pm, x, y + 1, 1.0f, 0.0f, a1 );
  140. Terrain_GetVert( pm, x + 1, y + 1, 0.0f, 0.0f, a2 );
  141. }
  142. }
  143. }
  144. void Terrain_Delete( terrainMesh_t *p ) {
  145. if ( p->pSymbiot ) {
  146. p->pSymbiot->pTerrain = NULL;
  147. p->pSymbiot->terrainBrush = false;
  148. }
  149. free( p );
  150. p = NULL;
  151. UpdateTerrainInspector();
  152. }
  153. void Terrain_AddTexture( terrainMesh_t *pm, qtexture_t *texture ) {
  154. int i;
  155. if ( !texture ) {
  156. return;
  157. }
  158. for( i = 0; i < pm->numtextures; i++ ) {
  159. if ( pm->textures[ i ] == texture ) {
  160. return;
  161. }
  162. }
  163. if ( pm->numtextures >= MAX_TERRAIN_TEXTURES ) {
  164. Warning( "Too many textures on terrain" );
  165. return;
  166. }
  167. pm->textures[ pm->numtextures++ ] = texture;
  168. }
  169. void Terrain_RemoveTexture( terrainMesh_t *p, qtexture_t *texture ) {
  170. int i;
  171. for( i = 0; i < p->numtextures; i++ ) {
  172. if ( p->textures[ i ] == texture ) {
  173. break;
  174. }
  175. }
  176. if ( i < p->numtextures ) {
  177. // shift all textures down to remove the texture from the list
  178. p->numtextures--;
  179. for( ; i < p->numtextures; i++ ) {
  180. p->textures[ i ] = p->textures[ i + 1 ];
  181. }
  182. }
  183. }
  184. terrainMesh_t *MakeNewTerrain( int width, int height, qtexture_t *texture ) {
  185. int h;
  186. int w;
  187. terrainMesh_t *pm;
  188. size_t size;
  189. size_t heightmapsize;
  190. terrainVert_t *vert;
  191. int index;
  192. heightmapsize = sizeof( terrainVert_t ) * width * height;
  193. size = sizeof( terrainMesh_t ) + heightmapsize;
  194. pm = reinterpret_cast< terrainMesh_t * >( qmalloc( size ) );
  195. memset( pm, 0x00, size );
  196. pm->numtextures = 0;
  197. pm->width = width;
  198. pm->height = height;
  199. pm->heightmap = reinterpret_cast< terrainVert_t * >( pm + 1 );
  200. if ( texture ) {
  201. Terrain_AddTexture( pm, texture );
  202. }
  203. index = 0;
  204. vert = pm->heightmap;
  205. for( h = 0; h < pm->height; h++ ) {
  206. for( w = 0; w < pm->width; w++, vert++ ) {
  207. vert->tri.index = index++;
  208. vert->tri.texture = texture;
  209. if ( texture ) {
  210. vert->tri.texdef.SetName( texture->name );
  211. }
  212. vert->height = 0;
  213. VectorClear( vert->normal );
  214. VectorSet( vert->rgba, 1.0f, 1.0f, 1.0f );
  215. vert->rgba[ 3 ] = 1.0f;
  216. }
  217. }
  218. return pm;
  219. }
  220. brush_t *AddBrushForTerrain( terrainMesh_t *pm, bool bLinkToWorld ) {
  221. int j;
  222. vec3_t vMin;
  223. vec3_t vMax;
  224. brush_t *b;
  225. face_t *f;
  226. // calculate the face normals
  227. Terrain_CalcNormals( pm );
  228. // find the farthest points in x,y,z
  229. Terrain_CalcBounds( pm, vMin, vMax );
  230. for( j = 0; j < 3; j++ ) {
  231. if ( vMin[ j ] == vMax[ j ] ) {
  232. vMin[ j ] -= 4;
  233. vMax[ j ] += 4;
  234. }
  235. }
  236. b = Brush_Create( vMin, vMax, &pm->heightmap->tri.texdef );
  237. for( f = b->brush_faces; f != NULL; f = f->next ) {
  238. // copy the texdef to the brush faces texdef
  239. f->texdef = pm->heightmap->tri.texdef;
  240. }
  241. // FIXME: this entire type of linkage needs to be fixed
  242. b->pTerrain = pm;
  243. b->terrainBrush = true;
  244. pm->pSymbiot = b;
  245. pm->bSelected = false;
  246. pm->bDirty = true;
  247. pm->nListID = -1;
  248. if ( bLinkToWorld ) {
  249. Brush_AddToList( b, &active_brushes );
  250. Entity_LinkBrush( world_entity, b );
  251. Brush_Build( b, true );
  252. }
  253. return b;
  254. }
  255. terrainMesh_t *Terrain_Duplicate( terrainMesh_t *pFrom ) {
  256. terrainMesh_t *p;
  257. int w;
  258. int h;
  259. int index;
  260. p = MakeNewTerrain( pFrom->width, pFrom->height );
  261. VectorCopy( pFrom->origin, p->origin );
  262. VectorCopy( pFrom->mins, p->mins );
  263. VectorCopy( pFrom->maxs, p->maxs );
  264. p->scale_x = pFrom->scale_x;
  265. p->scale_y = pFrom->scale_y;
  266. p->pSymbiot = pFrom->pSymbiot;
  267. for( index = 0; index < pFrom->numtextures; index++ ) {
  268. Terrain_AddTexture( p, pFrom->textures[ index ] );
  269. }
  270. index = 0;
  271. for( h = 0; h < p->height; h++ ) {
  272. for( w = 0; w < p->width; w++, index++ ) {
  273. p->heightmap[ index ] = pFrom->heightmap[ index ];
  274. }
  275. }
  276. p->bSelected = false;
  277. p->bDirty = true;
  278. p->nListID = -1;
  279. AddBrushForTerrain( p );
  280. return p;
  281. }
  282. void Terrain_BrushToMesh( void ) {
  283. brush_t *b;
  284. terrainMesh_t *p;
  285. if ( !QE_SingleBrush() ) {
  286. return;
  287. }
  288. b = selected_brushes.next;
  289. if ( g_qeglobals.d_terrainWidth < 1 ) {
  290. g_qeglobals.d_terrainWidth = 1;
  291. }
  292. if ( g_qeglobals.d_terrainHeight < 1 ) {
  293. g_qeglobals.d_terrainHeight = 1;
  294. }
  295. p = MakeNewTerrain( g_qeglobals.d_terrainWidth + 1, g_qeglobals.d_terrainHeight + 1, b->brush_faces->d_texture );
  296. p->scale_x = ( b->maxs[ 0 ] - b->mins[ 0 ] ) / float( p->width - 1 );
  297. p->scale_y = ( b->maxs[ 1 ] - b->mins[ 1 ] ) / float( p->height - 1 );
  298. VectorCopy( b->mins, p->origin );
  299. b = AddBrushForTerrain( p );
  300. Select_Delete();
  301. Select_Brush( b );
  302. }
  303. terrainFace_t *Terrain_ParseFace( terrainFace_t *f ) {
  304. // read the texturename
  305. GetToken( false );
  306. f->texdef.SetName( token );
  307. // Load the texture, and set the face to that texture's defaults
  308. f->texture = Texture_ForName( f->texdef.Name() );
  309. // read the texturedef
  310. GetToken( false );
  311. f->texdef.shift[ 0 ] = ( float )atoi( token );
  312. GetToken( false );
  313. f->texdef.shift[ 1 ] = ( float )atoi( token );
  314. GetToken( false );
  315. f->texdef.rotate = atof( token );
  316. GetToken( false );
  317. f->texdef.scale[ 0 ] = atof( token );
  318. GetToken( false );
  319. f->texdef.scale[ 1 ] = atof( token );
  320. // the flags and value field aren't necessarily present
  321. //f->texture = Texture_ForName( f->texdef.Name() );
  322. f->texdef.flags = f->texture->flags;
  323. f->texdef.value = f->texture->value;
  324. f->texdef.contents = f->texture->contents;
  325. if ( TokenAvailable () ) {
  326. GetToken (false);
  327. f->texdef.contents = atoi(token);
  328. GetToken (false);
  329. f->texdef.flags = atoi(token);
  330. GetToken (false);
  331. f->texdef.value = atoi(token);
  332. }
  333. return f;
  334. }
  335. brush_t *Terrain_Parse( void ) {
  336. terrainMesh_t *pm;
  337. terrainVert_t *vert;
  338. int w;
  339. int h;
  340. GetToken( true );
  341. if ( strcmp( token, "{" ) ) {
  342. return NULL;
  343. }
  344. // get width
  345. GetToken( false );
  346. w = atoi( token );
  347. // get height
  348. GetToken( false );
  349. h = atoi( token );
  350. pm = MakeNewTerrain( w, h );
  351. // get scale_x
  352. GetToken( false );
  353. pm->scale_x = atoi( token );
  354. // get scale_y
  355. GetToken( false );
  356. pm->scale_y = atoi( token );
  357. // get origin
  358. GetToken( true );
  359. pm->origin[ 0 ] = atoi( token );
  360. GetToken( false );
  361. pm->origin[ 1 ] = atoi( token );
  362. GetToken( false );
  363. pm->origin[ 2 ] = atoi( token );
  364. // get the height map
  365. vert = pm->heightmap;
  366. for( h = 0; h < pm->height; h++ ) {
  367. for( w = 0; w < pm->width; w++, vert++ ) {
  368. GetToken( true );
  369. vert->height = atoi( token );
  370. if ( !Terrain_ParseFace( &vert->tri ) ) {
  371. Terrain_Delete( pm );
  372. return NULL;
  373. }
  374. Terrain_AddTexture( pm, vert->tri.texture );
  375. }
  376. }
  377. GetToken( true );
  378. if ( strcmp( token, "}" ) ) {
  379. Terrain_Delete( pm );
  380. return NULL;
  381. }
  382. return AddBrushForTerrain( pm, false );
  383. }
  384. CString Terrain_SurfaceString( terrainFace_t *face ) {
  385. char temp[ 1024 ];
  386. CString text;
  387. const char *pname;
  388. pname = face->texdef.Name();
  389. if ( pname[ 0 ] == 0 ) {
  390. pname = "unnamed";
  391. }
  392. sprintf( temp, "%s %i %i %.2f ", pname, ( int )face->texdef.shift[ 0 ], ( int )face->texdef.shift[ 1 ], face->texdef.rotate );
  393. text += temp;
  394. if ( face->texdef.scale[ 0 ] == ( int )face->texdef.scale[ 0 ] ) {
  395. sprintf( temp, "%i ", ( int )face->texdef.scale[ 0 ] );
  396. } else {
  397. sprintf( temp, "%f ", ( float )face->texdef.scale[ 0 ] );
  398. }
  399. text += temp;
  400. if ( face->texdef.scale[ 1 ] == (int)face->texdef.scale[ 1 ] ) {
  401. sprintf( temp, "%i", ( int )face->texdef.scale[ 1 ] );
  402. } else {
  403. sprintf( temp, "%f", ( float )face->texdef.scale[ 1 ] );
  404. }
  405. text += temp;
  406. // only output flags and value if not default
  407. sprintf( temp, " %i %i %i ", face->texdef.contents, face->texdef.flags, face->texdef.value );
  408. text += temp;
  409. return text;
  410. }
  411. void Terrain_Write( terrainMesh_t *p, CMemFile *file ) {
  412. int w;
  413. int h;
  414. terrainVert_t *vert;
  415. MemFile_fprintf( file, " {\n terrainDef\n {\n" );
  416. MemFile_fprintf( file, " %d %d %f %f\n", p->width, p->height, p->scale_x, p->scale_y );
  417. MemFile_fprintf( file, " %f %f %f\n", p->origin[ 0 ], p->origin[ 1 ], p->origin[ 2 ] );
  418. vert = p->heightmap;
  419. for( h = 0; h < p->height; h++ ) {
  420. for( w = 0; w < p->width; w++, vert++ ) {
  421. MemFile_fprintf( file, " %f %s\n", vert->height, ( const char * )Terrain_SurfaceString( &vert->tri ) );
  422. }
  423. }
  424. MemFile_fprintf( file, " }\n }\n" );
  425. }
  426. void Terrain_Write( terrainMesh_t *p, FILE *file ) {
  427. int w;
  428. int h;
  429. terrainVert_t *vert;
  430. fprintf( file, " {\n terrainDef\n {\n" );
  431. fprintf( file, " %d %d %f %f\n", p->width, p->height, p->scale_x, p->scale_y );
  432. fprintf( file, " %f %f %f\n", p->origin[ 0 ], p->origin[ 1 ], p->origin[ 2 ] );
  433. vert = p->heightmap;
  434. for( h = 0; h < p->height; h++ ) {
  435. for( w = 0; w < p->width; w++, vert++ ) {
  436. fprintf( file, " %f %s\n", vert->height, ( const char * )Terrain_SurfaceString( &vert->tri ) );
  437. }
  438. }
  439. fprintf( file, " }\n }\n" );
  440. }
  441. void Terrain_Select( terrainMesh_t *p ) {
  442. p->bSelected = true;
  443. }
  444. void Terrain_Deselect( terrainMesh_t *p ) {
  445. p->bSelected = false;
  446. }
  447. void Terrain_Move( terrainMesh_t *pm, const vec3_t vMove, bool bRebuild ) {
  448. pm->bDirty = true;
  449. VectorAdd( pm->origin, vMove, pm->origin );
  450. if ( bRebuild ) {
  451. vec3_t vMin;
  452. vec3_t vMax;
  453. Terrain_CalcBounds( pm, vMin, vMax );
  454. }
  455. UpdateTerrainInspector();
  456. }
  457. void UpdateTerrainInspector( void ) {
  458. // not written yet
  459. }
  460. void Terrain_CalcBounds( terrainMesh_t *p, vec3_t &vMin, vec3_t &vMax ) {
  461. int w;
  462. int h;
  463. float f;
  464. terrainVert_t *vert;
  465. vMin[ 0 ] = p->origin[ 0 ];
  466. vMin[ 1 ] = p->origin[ 1 ];
  467. vMin[ 2 ] = MAX_WORLD_COORD;
  468. vMax[ 0 ] = p->origin[ 0 ] + ( p->width - 1 ) * p->scale_x;
  469. vMax[ 1 ] = p->origin[ 1 ] + ( p->height - 1 ) * p->scale_y;
  470. vMax[ 2 ] = MIN_WORLD_COORD;
  471. p->bDirty = true;
  472. vert = p->heightmap;
  473. for( h = 0; h < p->height; h++ ) {
  474. for( w = 0; w < p->width; w++, vert++ ) {
  475. f = p->origin[ 2 ] + vert->height;
  476. if ( f < vMin[ 2 ] ) {
  477. vMin[ 2 ] = f;
  478. }
  479. if ( f > vMax[ 2 ] ) {
  480. vMax[ 2 ] = f;
  481. }
  482. }
  483. }
  484. }
  485. void CalcTriNormal( const vec3_t a, const vec3_t b, const vec3_t c, vec3_t o ) {
  486. vec3_t a1;
  487. vec3_t b1;
  488. VectorSubtract( b, a, a1 );
  489. VectorNormalize( a1 );
  490. VectorSubtract( c, a, b1 );
  491. VectorNormalize( b1 );
  492. CrossProduct( a1, b1, o );
  493. VectorNormalize( o );
  494. }
  495. inline void Terrain_CalcVertPos( terrainMesh_t *p, int x, int y, vec3_t vert ) {
  496. int index;
  497. index = x + y * p->width;
  498. vert[ 0 ] = p->origin[ 0 ] + x * p->scale_x;
  499. vert[ 1 ] = p->origin[ 1 ] + y * p->scale_y;
  500. vert[ 2 ] = p->origin[ 2 ] + p->heightmap[ index ].height;
  501. VectorCopy( vert, p->heightmap[ index ].xyz );
  502. }
  503. void Terrain_CalcNormals( terrainMesh_t *p ) {
  504. int x;
  505. int y;
  506. int width;
  507. int num;
  508. terrainVert_t *vert;
  509. vec3_t norm;
  510. terravert_t a0;
  511. terravert_t a1;
  512. terravert_t a2;
  513. terravert_t b0;
  514. terravert_t b1;
  515. terravert_t b2;
  516. p->bDirty = true;
  517. num = p->height * p->width;
  518. vert = p->heightmap;
  519. //for( x = 0; x < num; x++, vert++ ) {
  520. for( y = 0; y < p->height - 1; y++ ) {
  521. for( x = 0; x < p->width - 1; x++, vert++ ) {
  522. VectorClear( vert->normal );
  523. Terrain_CalcVertPos( p, x, y, norm );
  524. }
  525. }
  526. width = p->width;
  527. vert = p->heightmap;
  528. for( y = 0; y < p->height - 1; y++ ) {
  529. for( x = 0; x < width - 1; x++ ) {
  530. Terrain_GetTriangles( p, x, y, &a0, &a1, &a2, &b0, &b1, &b2, NULL );
  531. CalcTriNormal( a0.xyz, a2.xyz, a1.xyz, norm );
  532. VectorAdd( vert[ a0.index ].normal, norm, vert[ a0.index ].normal );
  533. VectorAdd( vert[ a1.index ].normal, norm, vert[ a1.index ].normal );
  534. VectorAdd( vert[ a2.index ].normal, norm, vert[ a2.index ].normal );
  535. CalcTriNormal( b0.xyz, b2.xyz, b1.xyz, norm );
  536. VectorAdd( vert[ b0.index ].normal, norm, vert[ b0.index ].normal );
  537. VectorAdd( vert[ b1.index ].normal, norm, vert[ b1.index ].normal );
  538. VectorAdd( vert[ b2.index ].normal, norm, vert[ b2.index ].normal );
  539. }
  540. }
  541. for( x = 0; x < num; x++, vert++ ) {
  542. VectorNormalize( vert->normal );
  543. //FIXME
  544. vert->normal[ 2 ] += 0.5;
  545. VectorNormalize( vert->normal );
  546. assert( vert->normal[ 2 ] > 0 );
  547. VectorSet( vert->rgba, vert->normal[ 2 ], vert->normal[ 2 ], vert->normal[ 2 ] );
  548. vert->rgba[ 3 ] = 1.0f;
  549. }
  550. }
  551. void Terrain_FindReplaceTexture( terrainMesh_t *p, const char *pFind, const char *pReplace, bool bForce ) {
  552. int w;
  553. int h;
  554. terrainVert_t *vert;
  555. qtexture_t *texture;
  556. texture = Texture_ForName( pReplace );
  557. vert = p->heightmap;
  558. for( h = 0; h < p->height; h++ ) {
  559. for( w = 0; w < p->width; w++, vert++ ) {
  560. if ( bForce || strcmpi( vert->tri.texture->name, pFind ) == 0 ) {
  561. vert->tri.texture = texture;
  562. vert->tri.texdef.SetName( texture->name );
  563. }
  564. }
  565. }
  566. if ( bForce ) {
  567. p->numtextures = 0;
  568. Terrain_AddTexture( p, Texture_ForName( pReplace ) );
  569. } else {
  570. Terrain_RemoveTexture( p, Texture_ForName( pFind ) );
  571. Terrain_AddTexture( p, texture );
  572. }
  573. }
  574. bool Terrain_HasTexture( terrainMesh_t *p, const char *name ) {
  575. int w;
  576. int h;
  577. terrainVert_t *vert;
  578. vert = p->heightmap;
  579. for( h = 0; h < p->height; h++ ) {
  580. for( w = 0; w < p->width; w++, vert++ ) {
  581. if ( strcmpi( vert->tri.texture->name, name ) == 0 ) {
  582. return true;
  583. }
  584. }
  585. }
  586. return false;
  587. }
  588. void Terrain_ReplaceQTexture( terrainMesh_t *p, qtexture_t *pOld, qtexture_t *pNew ) {
  589. int w;
  590. int h;
  591. terrainVert_t *vert;
  592. vert = p->heightmap;
  593. for( h = 0; h < p->height; h++ ) {
  594. for( w = 0; w < p->width; w++, vert++ ) {
  595. if ( vert->tri.texture == pOld ) {
  596. vert->tri.texture = pNew;
  597. vert->tri.texdef.SetName( pNew->name );
  598. }
  599. }
  600. }
  601. Terrain_RemoveTexture( p, pOld );
  602. Terrain_AddTexture( p, pNew );
  603. }
  604. void Terrain_SetTexture( terrainMesh_t *p, texdef_t *tex_def ) {
  605. int w;
  606. int h;
  607. qtexture_t *newtex;
  608. terrainVert_t *vert;
  609. p->bDirty = 1;
  610. newtex = Texture_ForName( tex_def->name );
  611. p->numtextures = 0;
  612. Terrain_AddTexture( p, newtex );
  613. vert = p->heightmap;
  614. for( h = 0; h < p->height; h++ ) {
  615. for( w = 0; w < p->width; w++, vert++ ) {
  616. vert->tri.texture = newtex;
  617. vert->tri.texdef.SetName( newtex->name );
  618. }
  619. }
  620. UpdateTerrainInspector();
  621. }
  622. void Terrain_Scale( terrainMesh_t *p, const vec3_t vOrigin, const vec3_t vAmt, bool bRebuild ) {
  623. int w;
  624. int h;
  625. vec3_t pos;
  626. terrainVert_t *vert;
  627. vec3_t vMin;
  628. vec3_t vMax;
  629. vert = p->heightmap;
  630. for( h = 0; h < p->height; h++ ) {
  631. pos[ 1 ] = p->origin[ 1 ] + h * p->scale_y;
  632. for( w = 0; w < p->width; w++, vert++ ) {
  633. pos[ 0 ] = p->origin[ 0 ] + w * p->scale_x;
  634. pos[ 2 ] = vert->height;
  635. if ( ( g_qeglobals.d_select_mode == sel_terrainpoint ) && ( Terrain_PointInMoveList( vert ) == -1 ) ) {
  636. continue;
  637. }
  638. vert->height -= vOrigin[ 2 ] - p->origin[ 2 ];
  639. vert->height *= vAmt[ 2 ];
  640. vert->height += vOrigin[ 2 ] - p->origin[ 2 ];
  641. }
  642. }
  643. if ( g_qeglobals.d_select_mode != sel_terrainpoint ) {
  644. p->scale_x *= vAmt[ 0 ];
  645. p->scale_y *= vAmt[ 1 ];
  646. p->origin[ 0 ] -= vOrigin[ 0 ];
  647. p->origin[ 0 ] *= vAmt[ 0 ];
  648. p->origin[ 0 ] += vOrigin[ 0 ];
  649. p->origin[ 1 ] -= vOrigin[ 1 ];
  650. p->origin[ 1 ] *= vAmt[ 1 ];
  651. p->origin[ 1 ] += vOrigin[ 1 ];
  652. }
  653. if ( bRebuild ) {
  654. Terrain_CalcBounds( p, vMin, vMax );
  655. Terrain_CalcNormals( p );
  656. Brush_RebuildBrush( p->pSymbiot, vMin, vMax );
  657. }
  658. UpdateTerrainInspector();
  659. }
  660. bool Terrain_DragScale( terrainMesh_t *p, vec3_t vAmt, vec3_t vMove ) {
  661. vec3_t vMin;
  662. vec3_t vMax;
  663. vec3_t vScale;
  664. vec3_t vTemp;
  665. vec3_t vMid;
  666. int i;
  667. Terrain_CalcBounds( p, vMin, vMax );
  668. VectorSubtract( vMax, vMin, vTemp );
  669. // if we are scaling in the same dimension the terrain has no depth
  670. for( i = 0; i < 3; i++ ) {
  671. if ( ( vTemp[ i ] == 0 ) && ( vMove[ i ] != 0 ) ) {
  672. return false;
  673. }
  674. }
  675. for( i = 0; i < 3; i++ ) {
  676. vMid[ i ] = ( vMin[ i ] + vMax[ i ] ) / 2;
  677. }
  678. for( i = 0; i < 3; i++ ) {
  679. if ( vAmt[ i ] != 0 ) {
  680. vScale[i] = 1.0 + vAmt[i] / vTemp[i];
  681. } else {
  682. vScale[i] = 1.0;
  683. }
  684. }
  685. Terrain_Scale( p, vMid, vScale, false );
  686. VectorSubtract( vMax, vMin, vTemp );
  687. Terrain_CalcBounds( p, vMin, vMax );
  688. VectorSubtract( vMax, vMin, vMid );
  689. VectorSubtract( vMid, vTemp, vTemp );
  690. VectorScale( vTemp, 0.5f, vTemp );
  691. // abs of both should always be equal
  692. if ( !VectorCompare( vMove, vAmt ) ) {
  693. for( i = 0; i < 3; i++ ) {
  694. if ( vMove[ i ] != vAmt[ i ] ) {
  695. vTemp[ i ] = -vTemp[ i ];
  696. }
  697. }
  698. }
  699. Terrain_CalcNormals( p );
  700. Terrain_Move( p, vTemp );
  701. return true;
  702. }
  703. void Terrain_ApplyMatrix( terrainMesh_t *p, const vec3_t vOrigin, const vec3_t vMatrix[ 3 ], bool bSnap ) {
  704. }
  705. void Terrain_DrawFace( brush_t *brush, terrainFace_t *terraface ) {
  706. terrainMesh_t *pm;
  707. terravert_t a0;
  708. terravert_t a1;
  709. terravert_t a2;
  710. pm = brush->pTerrain;
  711. Terrain_GetTriangle( pm, terraface->index, &a0, &a1, &a2 );
  712. qglBindTexture( GL_TEXTURE_2D, terraface->texture->texture_number );
  713. qglBegin( GL_TRIANGLES );
  714. // first tri
  715. qglColor4fv( a0.rgba );
  716. qglTexCoord2fv( a0.tc );
  717. qglVertex3fv( a0.xyz );
  718. qglColor4fv( a1.rgba );
  719. qglTexCoord2fv( a1.tc );
  720. qglVertex3fv( a1.xyz );
  721. qglColor4fv( a2.rgba );
  722. qglTexCoord2fv( a2.tc );
  723. qglVertex3fv( a2.xyz );
  724. qglEnd ();
  725. }
  726. void DrawTerrain( terrainMesh_t *pm, bool bPoints, bool bShade ) {
  727. int i;
  728. int w;
  729. int h;
  730. int x;
  731. int y;
  732. //int n;
  733. //float x1;
  734. //float y1;
  735. float scale_x;
  736. float scale_y;
  737. //vec3_t pSelectedPoints[ MAX_TERRA_POINTS ];
  738. //int nIndex;
  739. terravert_t a0;
  740. terravert_t a1;
  741. terravert_t a2;
  742. terravert_t b0;
  743. terravert_t b1;
  744. terravert_t b2;
  745. terrainVert_t *vert;
  746. qtexture_t *texture;
  747. h = pm->height - 1;
  748. w = pm->width - 1;
  749. scale_x = pm->scale_x;
  750. scale_y = pm->scale_y;
  751. qglShadeModel (GL_SMOOTH);
  752. if ( bShade ) {
  753. for( i = 0; i < pm->numtextures; i++ ) {
  754. texture = pm->textures[ i ];
  755. qglBindTexture( GL_TEXTURE_2D, texture->texture_number );
  756. vert = pm->heightmap;
  757. for( y = 0; y < h; y++ ) {
  758. qglBegin( GL_TRIANGLES );
  759. for( x = 0; x < w; x++, vert++ ) {
  760. Terrain_GetTriangles( pm, x, y, &a0, &a1, &a2, &b0, &b1, &b2, texture );
  761. // first tri
  762. if ( a0.rgba[ 3 ] || a1.rgba[ 3 ] || a2.rgba[ 3 ] ) {
  763. qglColor4fv( a0.rgba );
  764. qglTexCoord2fv( a0.tc );
  765. qglVertex3fv( a0.xyz );
  766. qglColor4fv( a1.rgba );
  767. qglTexCoord2fv( a1.tc );
  768. qglVertex3fv( a1.xyz );
  769. qglColor4fv( a2.rgba );
  770. qglTexCoord2fv( a2.tc );
  771. qglVertex3fv( a2.xyz );
  772. }
  773. // second tri
  774. if ( b0.rgba[ 3 ] || b1.rgba[ 3 ] || b2.rgba[ 3 ] ) {
  775. qglColor4fv( b0.rgba );
  776. qglTexCoord2fv( b0.tc );
  777. qglVertex3fv( b0.xyz );
  778. qglColor4fv( b1.rgba );
  779. qglTexCoord2fv( b1.tc );
  780. qglVertex3fv( b1.xyz );
  781. qglColor4fv( b2.rgba );
  782. qglTexCoord2fv( b2.tc );
  783. qglVertex3fv( b2.xyz );
  784. }
  785. }
  786. qglEnd ();
  787. }
  788. }
  789. } else {
  790. for( i = 0; i < pm->numtextures; i++ ) {
  791. texture = pm->textures[ i ];
  792. qglBindTexture( GL_TEXTURE_2D, texture->texture_number );
  793. vert = pm->heightmap;
  794. for( y = 0; y < h; y++ ) {
  795. qglBegin( GL_TRIANGLES );
  796. for( x = 0; x < w; x++, vert++ ) {
  797. Terrain_GetTriangles( pm, x, y, &a0, &a1, &a2, &b0, &b1, &b2, texture );
  798. // first tri
  799. if ( a0.rgba[ 3 ] || a1.rgba[ 3 ] || a2.rgba[ 3 ] ) {
  800. qglColor4fv( a0.rgba );
  801. qglTexCoord2fv( a0.tc );
  802. qglVertex3fv( a0.xyz );
  803. qglColor4fv( a1.rgba );
  804. qglTexCoord2fv( a1.tc );
  805. qglVertex3fv( a1.xyz );
  806. qglColor4fv( a2.rgba );
  807. qglTexCoord2fv( a2.tc );
  808. qglVertex3fv( a2.xyz );
  809. }
  810. // second tri
  811. if ( b0.rgba[ 3 ] || b1.rgba[ 3 ] || b2.rgba[ 3 ] ) {
  812. qglColor4fv( b0.rgba );
  813. qglTexCoord2fv( b0.tc );
  814. qglVertex3fv( b0.xyz );
  815. qglColor4fv( b1.rgba );
  816. qglTexCoord2fv( b1.tc );
  817. qglVertex3fv( b1.xyz );
  818. qglColor4fv( b2.rgba );
  819. qglTexCoord2fv( b2.tc );
  820. qglVertex3fv( b2.xyz );
  821. }
  822. }
  823. qglEnd ();
  824. }
  825. }
  826. }
  827. qglPushAttrib( GL_CURRENT_BIT );
  828. bool bDisabledLighting = qglIsEnabled( GL_LIGHTING );
  829. if ( bDisabledLighting ) {
  830. qglDisable( GL_LIGHTING );
  831. }
  832. #if 0
  833. terrainVert_t *currentrow;
  834. terrainVert_t *nextrow;
  835. float x2;
  836. float y2;
  837. // Draw normals
  838. qglDisable( GL_TEXTURE_2D );
  839. qglDisable( GL_BLEND );
  840. qglColor3f( 1, 1, 1 );
  841. qglBegin( GL_LINES );
  842. y2 = pm->origin[ 1 ];
  843. nextrow = pm->heightmap;
  844. for( y = 0; y < h; y++ ) {
  845. y1 = y2;
  846. y2 += scale_y;
  847. x2 = pm->origin[ 0 ];
  848. currentrow = nextrow;
  849. nextrow = currentrow + pm->width;
  850. for( x = 0; x < w; x++ ) {
  851. x1 = x2;
  852. x2 += scale_x;
  853. // normals
  854. qglVertex3f( x1, y1, pm->origin[ 2 ] + currentrow[ x ].height );
  855. qglVertex3f( x1 + currentrow[ x ].normal[ 0 ] * 16.0f, y1 + currentrow[ x ].normal[ 1 ] * 16.0f, pm->origin[ 2 ] + currentrow[ x ].height + currentrow[ x ].normal[ 2 ] * 16.0f );
  856. qglVertex3f( x2, y1, pm->origin[ 2 ] + currentrow[ x + 1 ].height );
  857. qglVertex3f( x2 + currentrow[ x + 1 ].normal[ 0 ] * 16.0f, y1 + currentrow[ x + 1 ].normal[ 1 ] * 16.0f, pm->origin[ 2 ] + currentrow[ x + 1 ].height + currentrow[ x + 1 ].normal[ 2 ] * 16.0f );
  858. qglVertex3f( x1, y2, pm->origin[ 2 ] + nextrow[ x ].height );
  859. qglVertex3f( x1 + nextrow[ x ].normal[ 0 ] * 16.0f, y2 + nextrow[ x ].normal[ 1 ] * 16.0f, pm->origin[ 2 ] + nextrow[ x ].height + nextrow[ x ].normal[ 2 ] * 16.0f );
  860. qglVertex3f( x2, y2, pm->origin[ 2 ] + nextrow[ x + 1 ].height );
  861. qglVertex3f( x2 + nextrow[ x + 1 ].normal[ 0 ] * 16.0f, y2 + nextrow[ x + 1 ].normal[ 1 ] * 16.0f, pm->origin[ 2 ] + nextrow[ x + 1 ].height + nextrow[ x + 1 ].normal[ 2 ] * 16.0f );
  862. }
  863. }
  864. qglEnd ();
  865. qglEnable( GL_TEXTURE_2D );
  866. #endif
  867. #if 0
  868. if ( bPoints && ( g_qeglobals.d_select_mode == sel_terrainpoint || g_qeglobals.d_select_mode == sel_area ) ) {
  869. qglPointSize( 6 );
  870. qglDisable( GL_TEXTURE_2D );
  871. qglDisable( GL_BLEND );
  872. qglBegin( GL_POINTS );
  873. nIndex = 0;
  874. qglColor4f( 1, 0, 1, 1 );
  875. y1 = pm->origin[ 1 ];
  876. for ( y = 0; y < pm->height; y++, y1 += pm->scale_y ) {
  877. x1 = pm->origin[ 0 ];
  878. for( x = 0; x < pm->width; x++, x1 += pm->scale_x ) {
  879. // FIXME: need to not do loop lookups inside here
  880. n = Terrain_PointInMoveList( &pm->heightmap[ x + y * pm->width ] );
  881. if ( n >= 0 ) {
  882. VectorSet( pSelectedPoints[ nIndex ], x1, y1, pm->heightmap[ x + y * pm->width ].height + pm->origin[ 2 ] );
  883. nIndex++;
  884. } else {
  885. qglVertex3f( x1, y1, pm->origin[ 2 ] + pm->heightmap[ x + y * pm->width ].height );
  886. }
  887. }
  888. }
  889. qglEnd();
  890. qglEnable( GL_TEXTURE_2D );
  891. if ( nIndex > 0 ) {
  892. qglBegin( GL_POINTS );
  893. qglColor4f( 0, 0, 1, 1 );
  894. while( nIndex-- > 0 ) {
  895. qglVertex3fv( pSelectedPoints[ nIndex ] );
  896. }
  897. qglEnd();
  898. }
  899. }
  900. #endif
  901. if ( g_qeglobals.d_numterrapoints && ( ( g_qeglobals.d_select_mode == sel_terrainpoint ) || ( g_qeglobals.d_select_mode == sel_terraintexture ) ) ) {
  902. #if 0
  903. qglPointSize( 6 );
  904. qglDisable( GL_TEXTURE_2D );
  905. qglDisable( GL_BLEND );
  906. qglBegin( GL_POINTS );
  907. qglColor4f( 1, 0, 1, 1 );
  908. for( i = 0; i < g_qeglobals.d_numterrapoints; i++ ) {
  909. qglVertex3fv( g_qeglobals.d_terrapoints[ i ]->xyz );
  910. }
  911. qglEnd();
  912. qglEnable( GL_TEXTURE_2D );
  913. #endif
  914. brush_t *pb;
  915. terrainMesh_t *pm;
  916. pm = NULL;
  917. for( pb = active_brushes .next; pb != &active_brushes; pb = pb->next ) {
  918. if ( pb->terrainBrush ) {
  919. pm = pb->pTerrain;
  920. break;
  921. }
  922. }
  923. if ( pm ) {
  924. qglDisable( GL_TEXTURE_2D );
  925. qglBegin( GL_TRIANGLES );
  926. qglEnable( GL_BLEND );
  927. qglColor4f( 0.25, 0.5, 1, 0.35 );
  928. for( i = 0; i < g_qeglobals.d_numterrapoints; i++ ) {
  929. terravert_t a0;
  930. terravert_t a1;
  931. terravert_t a2;
  932. qglColor4f( 0.25, 0.5, 1, g_qeglobals.d_terrapoints[ i ]->scale * 0.75 + 0.25 );
  933. Terrain_GetTriangle( pm, g_qeglobals.d_terrapoints[ i ]->tri.index * 2, &a0, &a1, &a2 );
  934. qglVertex3fv( a0.xyz );
  935. qglVertex3fv( a1.xyz );
  936. qglVertex3fv( a2.xyz );
  937. Terrain_GetTriangle( pm, g_qeglobals.d_terrapoints[ i ]->tri.index * 2 + 1, &a0, &a1, &a2 );
  938. qglVertex3fv( a0.xyz );
  939. qglVertex3fv( a1.xyz );
  940. qglVertex3fv( a2.xyz );
  941. }
  942. qglEnd();
  943. qglDisable( GL_BLEND );
  944. qglEnable( GL_TEXTURE_2D );
  945. }
  946. }
  947. }
  948. void Terrain_DrawCam( terrainMesh_t *pm ) {
  949. qglColor3f( 1,1,1 );
  950. qglPushAttrib( GL_ALL_ATTRIB_BITS );
  951. if ( g_bPatchWireFrame ) {
  952. if( pm->bSelected ) {
  953. qglLineWidth( 2 );
  954. } else {
  955. qglLineWidth( 1 );
  956. }
  957. qglDisable( GL_CULL_FACE );
  958. qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
  959. qglDisable( GL_TEXTURE_2D );
  960. if ( g_PrefsDlg.m_bGLLighting ) {
  961. qglDisable( GL_LIGHTING );
  962. }
  963. DrawTerrain( pm, pm->bSelected, true );
  964. if ( g_PrefsDlg.m_bGLLighting ) {
  965. qglEnable( GL_LIGHTING );
  966. }
  967. qglEnable( GL_CULL_FACE );
  968. qglLineWidth( 1 );
  969. } else {
  970. qglEnable( GL_CULL_FACE );
  971. qglCullFace( GL_FRONT );
  972. // draw the textured polys
  973. DrawTerrain( pm, pm->bSelected, true );
  974. // if selected, draw the red tint on the polys
  975. if( pm->bSelected ) { // && ( g_qeglobals.d_savedinfo.include & INCLUDE_CAMERATINT ) ) {
  976. qglColor4f( 1.0, 0.0, 0.0, 0.3 );
  977. qglEnable( GL_BLEND );
  978. qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
  979. qglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
  980. DrawTerrain( pm, pm->bSelected );
  981. qglColor3f( 1, 1, 1 );
  982. }
  983. // draw the backside poly outlines
  984. qglCullFace( GL_BACK );
  985. qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
  986. qglDisable( GL_BLEND );
  987. DrawTerrain( pm, pm->bSelected, true );
  988. }
  989. qglPopAttrib();
  990. }
  991. void Terrain_DrawXY( terrainMesh_t *pm, entity_t *owner ) {
  992. qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
  993. if ( pm->bSelected ) {
  994. qglColor3fv( g_qeglobals.d_savedinfo.colors[ COLOR_SELBRUSHES ] );
  995. } else if ( owner != world_entity && _stricmp( owner->eclass->name, "func_group" ) ) {
  996. qglColor3fv( owner->eclass->color );
  997. } else {
  998. //FIXME
  999. qglColor3fv( g_qeglobals.d_savedinfo.colors[ COLOR_BRUSHES ] );
  1000. }
  1001. qglLineWidth( 1 );
  1002. DrawTerrain( pm, pm->bSelected );
  1003. qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
  1004. }
  1005. bool OnlyTerrainSelected( void ) {
  1006. brush_t *pb;
  1007. //if ( numselfaces || selected_brushes.next == &selected_brushes )
  1008. if ( selected_brushes.next == &selected_brushes ) {
  1009. return false;
  1010. }
  1011. for( pb = selected_brushes.next; pb != &selected_brushes; pb = pb->next ) {
  1012. if ( !pb->terrainBrush ) {
  1013. return false;
  1014. }
  1015. }
  1016. return true;
  1017. }
  1018. bool AnyTerrainSelected( void ) {
  1019. brush_t *pb;
  1020. //if ( numselfaces || selected_brushes.next == &selected_brushes )
  1021. if ( selected_brushes.next == &selected_brushes ) {
  1022. return false;
  1023. }
  1024. for( pb = selected_brushes.next; pb != &selected_brushes; pb = pb->next ) {
  1025. if ( pb->terrainBrush ) {
  1026. return true;
  1027. }
  1028. }
  1029. return false;
  1030. }
  1031. terrainMesh_t *SingleTerrainSelected( void ) {
  1032. if ( selected_brushes.next->terrainBrush ) {
  1033. return selected_brushes.next->pTerrain;
  1034. }
  1035. return NULL;
  1036. }
  1037. void Terrain_Edit( void ) {
  1038. //brush_t *pb;
  1039. //terrainMesh_t *p;
  1040. //int i;
  1041. //int j;
  1042. // g_qeglobals.d_numpoints = 0;
  1043. g_qeglobals.d_numterrapoints = 0;
  1044. #if 0
  1045. for( pb = selected_brushes.next; pb != &selected_brushes ; pb = pb->next ) {
  1046. if ( pb->terrainBrush ) {
  1047. p = pb->pTerrain;
  1048. if ( ( g_qeglobals.d_numpoints + p->width * p->height ) > MAX_POINTS ) {
  1049. Warning( "Too many points on terrain\n" );
  1050. continue;
  1051. }
  1052. for( i = 0; i < p->width; i++ ) {
  1053. for( j = 0; j < p->height; j++ ) {
  1054. Terrain_CalcVertPos( p, i, j, g_qeglobals.d_points[ g_qeglobals.d_numpoints ] );
  1055. g_qeglobals.d_numpoints++;
  1056. }
  1057. }
  1058. }
  1059. }
  1060. #endif
  1061. g_qeglobals.d_select_mode = sel_terrainpoint;
  1062. }
  1063. void Terrain_SelectPointByRay( vec3_t org, vec3_t dir, int buttons ) {
  1064. float bestd;
  1065. terrainFace_t *face;
  1066. terrainFace_t *bestface;
  1067. brush_t *pb;
  1068. float dist;
  1069. vec3_t vec;
  1070. // find the point closest to the ray
  1071. bestface = NULL;
  1072. bestd = WORLD_SIZE * 4;
  1073. for( pb = selected_brushes.next; pb != &selected_brushes; pb = pb->next ) {
  1074. if ( pb->terrainBrush ) {
  1075. face = Terrain_Ray( org, dir, pb, &dist );
  1076. if ( face && ( dist < bestd ) ) {
  1077. bestface = face;
  1078. bestd = dist;
  1079. }
  1080. }
  1081. }
  1082. for( pb = active_brushes .next; pb != &active_brushes; pb = pb->next ) {
  1083. if ( pb->terrainBrush ) {
  1084. face = Terrain_Ray( org, dir, pb, &dist );
  1085. if ( face && ( dist < bestd ) ) {
  1086. bestface = face;
  1087. bestd = dist;
  1088. }
  1089. }
  1090. }
  1091. if ( !bestface ) {
  1092. return;
  1093. }
  1094. VectorMA( org, bestd, dir, vec );
  1095. Terrain_AddMovePoint( vec, buttons & MK_CONTROL, buttons & MK_SHIFT, buttons );
  1096. }
  1097. void Terrain_AddMovePoint( vec3_t v, bool bMulti, bool bFull, int buttons ) {
  1098. brush_t *pb;
  1099. terrainMesh_t *p;
  1100. terrainVert_t *vert;
  1101. int x;
  1102. int y;
  1103. int x1, y1;
  1104. float dx, dy;
  1105. float dist;
  1106. float pd;
  1107. if ( !g_bSameView && !bMulti && !bFull ) {
  1108. g_bSameView = true;
  1109. return;
  1110. }
  1111. g_qeglobals.d_numterrapoints = 0;
  1112. for( pb = active_brushes .next; pb != &active_brushes; pb = pb->next ) {
  1113. //for( pb = selected_brushes.next; pb != &selected_brushes; pb = pb->next ) {
  1114. if ( pb->terrainBrush ) {
  1115. p = pb->pTerrain;
  1116. x = ( v[ 0 ] - p->origin[ 0 ] ) / p->scale_x;
  1117. y = ( v[ 1 ] - p->origin[ 1 ] ) / p->scale_x;
  1118. if ( ( x < 0 ) || ( x >= p->width ) || ( y < 0 ) || ( y >= p->height ) ) {
  1119. continue;
  1120. }
  1121. vert = p->heightmap;
  1122. for( y1 = 0; y1 < p->height; y1++ ) {
  1123. for( x1 = 0; x1 < p->width; x1++, vert++ ) {
  1124. if ( g_qeglobals.d_terrainBrush == TERRAIN_BRUSH_CIRCLE ) {
  1125. dx = x1 - x;
  1126. dy = y1 - y;
  1127. dist = sqrt( dx * dx + dy * dy );
  1128. } else {
  1129. dx = abs( x1 - x );
  1130. dy = abs( y1 - y );
  1131. if ( dx > dy ) {
  1132. dist = dx;
  1133. } else {
  1134. dist = dy;
  1135. }
  1136. }
  1137. pd = dist * 2.0f / g_qeglobals.d_terrainBrushSize;
  1138. if ( fabs( pd ) <= 1.0f ) {
  1139. Terrain_AddPoint( p, vert );
  1140. if ( ( buttons & MK_LBUTTON ) && ( g_qeglobals.d_select_mode == sel_terraintexture ) ) {
  1141. vert->tri.texture = Texture_ForName( g_qeglobals.d_texturewin.texdef.name );
  1142. vert->tri.texdef.SetName( vert->tri.texture->name );
  1143. Terrain_AddTexture( p, vert->tri.texture );
  1144. continue;
  1145. }
  1146. if ( g_qeglobals.d_terrainFalloff == TERRAIN_FALLOFF_CURVED ) {
  1147. if ( g_qeglobals.d_terrainBrush == TERRAIN_BRUSH_CIRCLE ) {
  1148. vert->scale = ( 0.5f + cos( pd * M_PI ) * 0.5f );
  1149. } else {
  1150. vert->scale = ( 0.5f + cos( dx/ g_qeglobals.d_terrainBrushSize * M_PI ) * 0.5f ) * ( 0.5f + cos( dy/ g_qeglobals.d_terrainBrushSize * M_PI ) * 0.5f ) - 0.25;
  1151. }
  1152. } else {
  1153. vert->scale = 1.0f - pd;
  1154. }
  1155. switch( g_qeglobals.d_terrainNoiseType ) {
  1156. case NOISE_PLUS :
  1157. vert->scale *= crandom();
  1158. break;
  1159. case NOISE_PLUSMINUS :
  1160. vert->scale *= random();
  1161. break;
  1162. }
  1163. }
  1164. }
  1165. }
  1166. }
  1167. }
  1168. }
  1169. void Terrain_UpdateSelected( vec3_t vMove ) {
  1170. int i;
  1171. brush_t *pb;
  1172. terrainMesh_t *p;
  1173. vec3_t vMin;
  1174. vec3_t vMax;
  1175. if ( g_qeglobals.d_select_mode == sel_terrainpoint ) {
  1176. for( i = 0; i < g_qeglobals.d_numterrapoints; i++ ) {
  1177. g_qeglobals.d_terrapoints[ i ]->height += vMove[ 2 ] * g_qeglobals.d_terrapoints[ i ]->scale;
  1178. }
  1179. }
  1180. for( pb = active_brushes .next; pb != &active_brushes; pb = pb->next ) {
  1181. // for( pb = selected_brushes.next; pb != &selected_brushes; pb = pb->next ) {
  1182. if ( pb->terrainBrush ) {
  1183. p = pb->pTerrain;
  1184. Terrain_CalcBounds( p, vMin, vMax );
  1185. Terrain_CalcNormals( p );
  1186. Brush_RebuildBrush( p->pSymbiot, vMin, vMax );
  1187. }
  1188. }
  1189. }
  1190. int Terrain_PointInMoveList( terrainVert_t *pf ) {
  1191. int i;
  1192. for( i = 0; i < g_qeglobals.d_numterrapoints; i++ ) {
  1193. if ( pf == g_qeglobals.d_terrapoints[ i ] ) {
  1194. return i;
  1195. }
  1196. }
  1197. return -1;
  1198. }
  1199. void Terrain_RemovePointFromMoveList( terrainVert_t *v ) {
  1200. int n;
  1201. int i;
  1202. while( ( n = Terrain_PointInMoveList( v ) ) >= 0 ) {
  1203. for( i = n; i < g_qeglobals.d_numterrapoints - 1; i++ ) {
  1204. g_qeglobals.d_terrapoints[ i ] = g_qeglobals.d_terrapoints[ i + 1 ];
  1205. }
  1206. g_qeglobals.d_numterrapoints--;
  1207. }
  1208. }
  1209. void Terrain_AddPoint( terrainMesh_t *p, terrainVert_t *v ) {
  1210. if ( g_qeglobals.d_numterrapoints < MAX_TERRA_POINTS ) {
  1211. g_qeglobals.d_terrapoints[ g_qeglobals.d_numterrapoints++ ] = v;
  1212. }
  1213. }
  1214. void Terrain_SelectAreaPoints( void ) {
  1215. brush_t *pb;
  1216. terrainMesh_t *p;
  1217. int x;
  1218. int y;
  1219. vec3_t vec;
  1220. g_qeglobals.d_numterrapoints = 0;
  1221. g_nPatchClickedView = -1;
  1222. for( pb = selected_brushes.next; pb != &selected_brushes; pb = pb->next ) {
  1223. if ( pb->terrainBrush ) {
  1224. p = pb->pTerrain;
  1225. for( x = 0; x < p->width; x++ ) {
  1226. for( y = 0; y < p->height; y++ ) {
  1227. Terrain_CalcVertPos( p, x, y, vec );
  1228. if ( within( vec, g_qeglobals.d_vAreaTL, g_qeglobals.d_vAreaBR ) ) {
  1229. if ( g_qeglobals.d_numterrapoints < MAX_TERRA_POINTS ) {
  1230. g_qeglobals.d_terrapoints[ g_qeglobals.d_numterrapoints++ ] = &p->heightmap[ x + y * p->width ];
  1231. }
  1232. }
  1233. }
  1234. }
  1235. }
  1236. }
  1237. }
  1238. #define EPSILON 0.0001
  1239. bool RayTriangleIntersect( vec3_t orig, vec3_t dir, vec3_t vert1, vec3_t vert2, vec3_t vert3, float *t ) {
  1240. float u;
  1241. float v;
  1242. vec3_t edge1;
  1243. vec3_t edge2;
  1244. vec3_t tvec;
  1245. vec3_t pvec;
  1246. vec3_t qvec;
  1247. float det;
  1248. VectorSubtract( vert2, vert1, edge1 );
  1249. VectorSubtract( vert3, vert1, edge2 );
  1250. // begin calculating determinant - also used to calculate U parameter
  1251. CrossProduct( dir, edge2, pvec );
  1252. // if determinant is near zero, ray lies in plane of triangle
  1253. det = DotProduct( edge1, pvec );
  1254. if ( det < EPSILON ) {
  1255. return false;
  1256. }
  1257. // calculate distance from vert1 to ray origin
  1258. VectorSubtract( orig, vert1, tvec );
  1259. // calculate U parameter and test bounds
  1260. u = DotProduct( tvec, pvec );
  1261. if ( ( u < 0.0f ) || ( u > det ) ) {
  1262. return false;
  1263. }
  1264. // prepare to test V parameter
  1265. CrossProduct( tvec, edge1, qvec );
  1266. // calculate V parameter and test bounds
  1267. v = DotProduct( dir, qvec );
  1268. if ( ( v < 0.0f ) || ( u + v > det ) ) {
  1269. return false;
  1270. }
  1271. // calculate t, scale parameters, ray intersects triangle
  1272. *t = DotProduct( edge2, qvec ) / det;
  1273. return true;
  1274. }
  1275. /*
  1276. ==============
  1277. Terrain_Ray
  1278. Itersects a ray with a terrain
  1279. Returns the face hit and the distance along the ray the intersection occured at
  1280. Returns NULL and 0 if not hit at all
  1281. ==============
  1282. */
  1283. terrainFace_t *Terrain_Ray( vec3_t origin, vec3_t dir, brush_t *b, float *dist ) {
  1284. terrainMesh_t *pm;
  1285. int h;
  1286. int w;
  1287. int x;
  1288. int y;
  1289. float best_t;
  1290. float t;
  1291. terravert_t a0;
  1292. terravert_t a1;
  1293. terravert_t a2;
  1294. terravert_t b0;
  1295. terravert_t b1;
  1296. terravert_t b2;
  1297. terrainVert_t *vert;
  1298. terrainFace_t *best;
  1299. best = NULL;
  1300. best_t = WORLD_SIZE * 2;
  1301. pm = b->pTerrain;
  1302. h = pm->height - 1;
  1303. w = pm->width - 1;
  1304. vert = pm->heightmap;
  1305. for( y = 0; y < h; y++, vert++ ) {
  1306. for( x = 0; x < w; x++, vert++ ) {
  1307. Terrain_GetTriangles( pm, x, y, &a0, &a1, &a2, &b0, &b1, &b2, NULL );
  1308. t = WORLD_SIZE * 2;
  1309. if ( RayTriangleIntersect( origin, dir, a2.xyz, a1.xyz, a0.xyz, &t ) ) {
  1310. if ( ( t >= 0 ) && ( t < best_t ) ) {
  1311. best = &vert->tri;
  1312. best_t = t;
  1313. }
  1314. }
  1315. t = WORLD_SIZE * 2;
  1316. if ( RayTriangleIntersect( origin, dir, b2.xyz, b1.xyz, b0.xyz, &t ) ) {
  1317. if ( ( t >= 0 ) && ( t < best_t ) ) {
  1318. best = &vert->tri;
  1319. best_t = t;
  1320. }
  1321. }
  1322. }
  1323. }
  1324. if ( !best ) {
  1325. *dist = 0;
  1326. return NULL;
  1327. }
  1328. *dist = best_t;
  1329. return best;
  1330. }
  1331. /*
  1332. ============
  1333. Select_TerrainFace
  1334. Select the face
  1335. ============
  1336. */
  1337. void Select_TerrainFace ( brush_t * brush, terrainFace_t *terraface ) {
  1338. #if 0
  1339. UnSelect_Brush( brush );
  1340. if( numselfaces < MAX_SEL_FACES ) {
  1341. selfaces[numselfaces].face = NULL;
  1342. selfaces[numselfaces].brush = brush;
  1343. selfaces[numselfaces].terraface = terraface;
  1344. numselfaces++;
  1345. }
  1346. #endif
  1347. }
  1348. void Select_TerrainFacesFromBrush( brush_t *brush ) {
  1349. terrainMesh_t *pm;
  1350. int h;
  1351. int w;
  1352. int x;
  1353. int y;
  1354. pm = brush->pTerrain;
  1355. h = pm->height - 1;
  1356. w = pm->width - 1;
  1357. for( y = 0; y < h; y++ ) {
  1358. for( x = 0; x < w; x++ ) {
  1359. Select_TerrainFace( brush, &brush->pTerrain->heightmap[ x + y * pm->width ].tri );
  1360. }
  1361. }
  1362. }
  1363. void SetTerrainTexdef( brush_t *brush, terrainFace_t *face, texdef_t *texdef ) {
  1364. int oldFlags;
  1365. int oldContents;
  1366. oldFlags = face->texdef.flags;
  1367. oldContents = face->texdef.contents;
  1368. face->texdef = *texdef;
  1369. face->texdef.flags = ( face->texdef.flags & ~SURF_KEEP ) | ( oldFlags & SURF_KEEP );
  1370. face->texdef.contents = ( face->texdef.contents & ~CONTENTS_KEEP ) | ( oldContents & CONTENTS_KEEP );
  1371. face->texture = Texture_ForName( texdef->name );
  1372. //Terrain_AddTexture( face->texture );
  1373. }
  1374. void RotateTerrainFaceTexture( terrainFace_t *vert, int nAxis, float fDeg ) {
  1375. }
  1376. void TerrainFace_FitTexture( terrainFace_t *vert ) {
  1377. }
  1378. void Terrain_Init( void ) {
  1379. g_qeglobals.d_terrainWidth = 64;
  1380. g_qeglobals.d_terrainHeight = 64;
  1381. g_qeglobals.d_terrainBrushSize = 12;
  1382. g_qeglobals.d_terrainNoiseType = NOISE_NONE;
  1383. //g_qeglobals.d_terrainFalloff = TERRAIN_FALLOFF_LINEAR;
  1384. g_qeglobals.d_terrainFalloff = TERRAIN_FALLOFF_CURVED;
  1385. g_qeglobals.d_terrainBrush = TERRAIN_BRUSH_CIRCLE;
  1386. //g_qeglobals.d_terrainBrush = TERRAIN_BRUSH_SQUARE;
  1387. }