float angle_begin = -(1.0f-fabsf( player->rb.to_world[1][1] )),
angle_end = 1.0f;
+ struct grind_info grind;
+ int grind_located = 0;
+
for( int m=0;m<=15; m++ )
{
struct land_prediction *p = &s->predictions[ s->prediction_count ++ ];
co1[1] += -0.5f * k_gravity * t*t;
v3_add( launch_co, co1, co1 );
+ if( !grind_located && (launch_v[1] - k_gravity*t < 0.0f) )
+ {
+ v3f closest;
+ if( bh_closest_point( world.geo_bh, co1, closest, 1.0f ) != -1 )
+ {
+ v3f ve;
+ v3_copy( launch_v, ve );
+ ve[1] -= k_gravity * t;
+
+ if( skate_grind_scansq( closest, ve, 0.5f, &grind ) )
+ {
+ v2f v0 = { ve[0], ve[2] },
+ v1 = { grind.dir[0], grind.dir[2] };
+
+ v2_normalize( v0 );
+ v2_normalize( v1 );
+
+ float a = v2_dot( v0, v1 );
+
+ if( a >= cosf( VG_PIf * 0.125f ) )
+ {
+ grind_located = 1;
+ }
+ }
+ }
+ }
+
float t1;
v3f n;
s->prediction_count --;
}
+
+
+ if( grind_located )
+ {
+ v3f v0;
+ v3_sub( grind.co, player->rb.co, v0 );
+
+ v3f ax;
+ v3_copy( v0, ax );
+ ax[1] = 0.0f;
+ v3_normalize( ax );
+
+ v2f d = { v3_dot( v0, ax ), v0[1] },
+ v = { v3_dot( player->rb.v, ax ), player->rb.v[1] };
+
+ float a = atan2f( v[1], v[0] ),
+ m = v2_length( v ),
+
+ root = m*m*m*m - k_gravity*(k_gravity*d[0]*d[0] + 2.0f*d[1]*m*m);
+
+ if( root > 0.0f )
+ {
+ root = sqrtf( root );
+ float a0 = atanf( (m*m + root) / (k_gravity * d[0]) ),
+ a1 = atanf( (m*m - root) / (k_gravity * d[0]) );
+
+ if( fabsf(a0-a) < fabsf(a1-a) )
+ a = a0;
+ else
+ a = a1;
+ /* TODO: sweep the path before chosing the smallest dist */
+ /* TODO: Jump in normal direction not to_world[1] */
+ /* TODO: Grind require manual be pulled in correct direction */
+
+ struct land_prediction *p = &s->predictions[ s->prediction_count ++ ];
+
+ p->log_length = 0;
+ p->land_dist = 0.0f;
+ v3_zero( p->apex );
+ p->type = k_prediction_grind;
+
+ v3_muls( ax, cosf( a ) * m, p->v );
+ p->v[1] += sinf( a ) * m;
+ p->land_dist = d[0] / (cosf(a)*m);
+
+ v3_copy( grind.n, p->n );
+
+ /* add a trace */
+ for( int i=0; i<=20; i++ )
+ {
+ float t = (float)i * (1.0f/20.0f) * p->land_dist;
+
+ v3f p0;
+ v3_muls( p->v, t, p0 );
+ p0[1] += -0.5f * k_gravity * t*t;
+
+ v3_add( player->rb.co, p0, p->log[ p->log_length ++ ] );
+ }
+
+ /* determine score */
+ v3f ve;
+ v3_copy( p->v, ve );
+ ve[1] -= k_gravity * p->land_dist;
+ p->score = -v3_dot( ve, grind.n ) * 0.85f;
+ }
+ }
+
+
+
+
float score_min = INFINITY,
score_max = -INFINITY;