Guest User

Untitled

a guest
Jul 18th, 2018
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.78 KB | None | 0 0
  1. //TODO: redo all of the angles, vectors, and math code, and look into quaternions!
  2.  
  3. typedef struct splatterPatternData_s
  4. {
  5. const splatterAttributes_t *splatter;
  6. int seed;
  7. const int *fragment_num;
  8.  
  9. float (*distribution)( struct splatterPatternData_s *data, angleIndex_t angle_index );
  10. void (*pattern)( struct splatterPatternData_s *data, vec3_t out );
  11. } splatterPatternData_t;
  12.  
  13. /*
  14. ==============
  15. BG_SplatterRandom
  16. ==============
  17. */
  18. static float BG_SplatterRandom( splatterPatternData_t *data, angleIndex_t angle_index ) {
  19. Com_Assert( data &&
  20. "BG_SplatterRandom: data is NULL" );
  21.  
  22. return Q_random( &data->seed );
  23. }
  24.  
  25. /*
  26. ==============
  27. BG_SplatterUniform
  28. ==============
  29. */
  30. static float BG_SplatterUniform( splatterPatternData_t *data, angleIndex_t angle_index ) {
  31. const int yaw_layers = data->splatter->number / data->splatter->pitchLayers;
  32.  
  33. Com_Assert( data &&
  34. "BG_SplatterUniform: data is NULL" );
  35. Com_Assert( data->fragment_num &&
  36. "BG_SplatterUniform: data->fragment_num is NULL" );
  37.  
  38. if( angle_index == YAW ) {
  39. const int yaw_layer_num = *data->fragment_num % yaw_layers;
  40. float yaw_position = ( ( data->seed & 0xffff ) / (float)0x10000 ); // start the overall pattern at a random YAW
  41.  
  42. yaw_position += ( (float)yaw_layer_num ) / ( (float)( yaw_layers ) );
  43. return yaw_position - ( (int)yaw_position );
  44. }
  45.  
  46. //at this point angle_index must be PITCH
  47. Com_Assert( ( angle_index == PITCH ) &&
  48. "BG_SplatterUniform: angle_index is invalid" );
  49.  
  50. {
  51. const int pitch_layer_num = *data->fragment_num / yaw_layers;
  52.  
  53. return ( (float)pitch_layer_num ) / ( (float)data->splatter->pitchLayers - 1 );
  54. }
  55. }
  56.  
  57. /*
  58. ==============
  59. BG_SplatterUniformAlternating
  60. ==============
  61. */
  62. static float BG_SplatterUniformAlternating( splatterPatternData_t *data, angleIndex_t angle_index ) {
  63. const int yaw_layers = data->splatter->number / data->splatter->pitchLayers;
  64.  
  65. Com_Assert( data &&
  66. "BG_SplatterUniform: data is NULL" );
  67. Com_Assert( data->fragment_num &&
  68. "BG_SplatterUniform: data->fragment_num is NULL" );
  69.  
  70. if( angle_index == YAW ) {
  71. const int pitch_layer_num = *data->fragment_num / yaw_layers;
  72. const int yaw_layer_num = *data->fragment_num % yaw_layers;
  73. float yaw_position = ( ( data->seed & 0xffff ) / (float)0x10000 ); // start the overall pattern at a random YAW
  74.  
  75. //alternate by a half yaw position between pitch layers
  76. yaw_position += 0.5 * ( ( (float)pitch_layer_num ) / ( (float)yaw_layers ) );
  77.  
  78. yaw_position += ( (float)yaw_layer_num ) / ( (float)( yaw_layers - 1 ) );
  79. return yaw_position - ( (int)yaw_position );
  80. }
  81.  
  82. //at this point angle_index must be PITCH
  83. Com_Assert( ( angle_index == PITCH ) &&
  84. "BG_SplatterUniform: angle_index is invalid" );
  85.  
  86. {
  87. const int pitch_layer_num = *data->fragment_num / yaw_layers;
  88.  
  89. return ( (float)pitch_layer_num ) / ( (float)( data->splatter->pitchLayers - 1 ) );
  90. }
  91. }
  92.  
  93. /*
  94. ==============
  95. BG_SplatterSphericalCone
  96. ==============
  97. */
  98. static void BG_SplatterSphericalCone( splatterPatternData_t *data, vec3_t out ) {
  99. vec3_t splatter_angles;
  100.  
  101. Com_Assert( data &&
  102. "BG_SplatterSphericalCone: data is NULL" );
  103. Com_Assert( data->distribution &&
  104. "BG_SplatterSphericalCone: distribution function is NULL" );
  105. Com_Assert( out &&
  106. "BG_SplatterSphericalCone: out is NULL" );
  107.  
  108. splatter_angles[PITCH] = data->distribution( data, PITCH ) * data->splatter->spread;
  109. AngleNormalize180( splatter_angles[PITCH] );
  110. splatter_angles[PITCH] -= 90; //the spread angle is in relation to pointing straight up
  111. splatter_angles[YAW] = data->distribution( data, YAW ) * 360;
  112. AngleNormalize360( splatter_angles[YAW] );
  113. splatter_angles[ROLL] = 0;
  114.  
  115. AngleVectors( splatter_angles, out, NULL, NULL );
  116. VectorNormalize( out );
  117. }
  118.  
  119. /*
  120. ==============
  121. BG_SplatterMirroredInverseSphericalCone
  122. ==============
  123. */
  124. static void BG_SplatterMirroredInverseSphericalCone( splatterPatternData_t *data, vec3_t out ) {
  125. vec3_t splatter_angles;
  126.  
  127. Com_Assert( data &&
  128. "BG_SplatterSphericalCone: data is NULL" );
  129. Com_Assert( data->distribution &&
  130. "BG_SplatterSphericalCone: distribution function is NULL" );
  131. Com_Assert( out &&
  132. "BG_SplatterSphericalCone: out is NULL" );
  133.  
  134. splatter_angles[PITCH] = data->distribution( data, PITCH ) * data->splatter->spread;
  135. AngleNormalize180( splatter_angles[PITCH] );
  136. splatter_angles[PITCH] -= ( data->splatter->spread * 0.5f ); //the spread angle is centered at the horizontal
  137. splatter_angles[YAW] = data->distribution( data, YAW ) * 360;
  138. AngleNormalize360( splatter_angles[YAW] );
  139. splatter_angles[ROLL] = 0;
  140.  
  141. AngleVectors( splatter_angles, out, NULL, NULL );
  142. VectorNormalize( out );
  143. }
  144.  
  145. /*
  146. ==============
  147. BG_SplatterPattern
  148.  
  149. For the shotgun, frag nade, acidtubes, flamer, etc...
  150. ==============
  151. */
  152. void BG_SplatterPattern( vec3_t origin2, int seed, int passEntNum,
  153. splatterData_t *data, void (*func)( splatterData_t *data ),
  154. void (*trace)( trace_t *, const vec3_t,
  155. const vec3_t, const vec3_t,
  156. const vec3_t, int, int ) ) {
  157. int i;
  158. const int modeIndex = data->weaponMode - 1;
  159. weapon_t weapon = data->weapon;
  160. vec3_t origin, forward, cross;
  161. const vec3_t up_absolute = { 0.0f, 0.0f, 1.0f };
  162. float rotation_angle, cross_length, dot;
  163. trace_t tr;
  164. splatterPatternData_t splatterData;
  165.  
  166. memset( &splatterData, 0, sizeof( splatterData ) );
  167. splatterData.splatter = &BG_Weapon( weapon )->splatter[modeIndex];
  168.  
  169. Com_Assert( modeIndex >= 0 &&
  170. modeIndex < 3 &&
  171. "BG_SplatterPattern: invalid weaponMode" );
  172. Com_Assert( trace &&
  173. "BG_SplatterPattern: trace is NULL" );
  174. Com_Assert( func &&
  175. "BG_SplatterPattern: func is NULL" );
  176. Com_Assert( splatterData.splatter &&
  177. "BG_SplatterPattern: splatterData.splatter is NULL" );
  178. Com_Assert( splatterData.splatter->spread >= 0 &&
  179. splatterData.splatter->spread <= 180 &&
  180. "BG_SplatterPattern: spread is out of range" );
  181. Com_Assert( ( splatterData.distribution == SPLATD_RANDOM ||
  182. splatterData.splatter->pitchLayers > 0 ) &&
  183. "BG_SplatterPattern: pitch layers must be greater than 0" );
  184. Com_Assert( ( splatterData.distribution == SPLATD_RANDOM ||
  185. splatterData.splatter->pitchLayers < splatterData.splatter->number ) &&
  186. "BG_SplatterPattern: pitch layers must be less than the total number of fragments" );
  187. Com_Assert( ( splatterData.distribution == SPLATD_RANDOM ||
  188. !( splatterData.splatter->number % splatterData.splatter->pitchLayers ) ) &&
  189. "BG_SplatterPattern: pitch layers must be a factor of the number of fragments for even yaw layers" );
  190.  
  191. splatterData.seed = seed;
  192.  
  193. VectorCopy( data->origin, origin );
  194.  
  195. //select the pattern type
  196. switch ( splatterData.splatter->pattern ) {
  197. case SPLATP_SPHERICAL_CONE:
  198. splatterData.pattern = BG_SplatterSphericalCone;
  199. break;
  200.  
  201. case SPLATP_MIRRORED_INVERSE_SPHERICAL_CONE:
  202. splatterData.pattern = BG_SplatterMirroredInverseSphericalCone;
  203. break;
  204. }
  205.  
  206. Com_Assert( splatterData.pattern &&
  207. "BG_SplatterPattern: pattern function not selected" );
  208.  
  209. switch( splatterData.splatter->distribution ) {
  210. case SPLATD_RANDOM:
  211. splatterData.distribution = BG_SplatterRandom;
  212. break;
  213.  
  214. case SPLATD_UNIFORM:
  215. splatterData.distribution = BG_SplatterUniform;
  216. break;
  217.  
  218. case SPLATD_UNIFORM_ALTERNATING:
  219. splatterData.distribution = BG_SplatterUniformAlternating;
  220. break;
  221. }
  222.  
  223. Com_Assert( splatterData.distribution &&
  224. "BG_SplatterPattern: distribution function not selected" );
  225.  
  226. //prepare for rotation to the facing direction
  227. VectorCopy( origin2, forward );
  228. CrossProduct( up_absolute, forward, cross );
  229. cross_length = VectorLength( cross );
  230. dot = DotProduct( up_absolute, forward );
  231.  
  232. if( cross_length > 0 ) {
  233. VectorNormalize( cross );
  234. rotation_angle = RAD2DEG( atan2( cross_length, dot) );
  235. } else if( dot > 0.0f ) {
  236. rotation_angle = 0;
  237. } else {
  238. rotation_angle = 180;
  239. }
  240.  
  241. // generate the pattern
  242. for( i = 0; i < splatterData.splatter->number; i++ ) {
  243. vec3_t dir, temp, end;
  244.  
  245. splatterData.fragment_num = &i;
  246.  
  247. //get the next pattern vector
  248. splatterData.pattern( &splatterData, temp );
  249.  
  250. //rotate toward the facing direction
  251. if( cross_length > 0 ) {
  252. RotatePointAroundVector( dir, cross, temp, rotation_angle );
  253. } else if( dot > 0.0f ){
  254. VectorCopy( temp, dir );
  255. } else {
  256. VectorScale( temp, -1.0f, dir );
  257. }
  258.  
  259. VectorMA( origin, splatterData.splatter->range, dir, end );
  260.  
  261. //apply the impact
  262. trace( &tr, origin, NULL, NULL, end, passEntNum, MASK_SHOT );
  263. data->tr = &tr;
  264. func( data );
  265. }
  266. }
Add Comment
Please, Sign In to add comment