void lerp_frame(struct pose *out, struct pose *a, struct pose *b, float t, int n) { int i; for (i = 0; i < n; i++) { vec_lerp(out[i].position, a[i].position, b[i].position, t); quat_lerp_neighbor_normalize(out[i].rotation, a[i].rotation, b[i].rotation, t); vec_lerp(out[i].scale, a[i].scale, b[i].scale, t); } }
VECTOR* handFingerPos (ENTITY* entHand, BOOL bLeftHand, int fingerId, VECTOR* vecFingerPos, VECTOR* vecFingerDir) { VECTOR vecFinger0, vecFinger1; char* j0 = _chr((g_handBoneFarNames->pstring)[fingerId]); char* j1 = _chr((g_handBoneNearNames->pstring)[fingerId]); vec_for_bone(&vecFinger0, entHand, j0); vec_for_bone(&vecFinger1, entHand, j1); if (bLeftHand) { vec_to_ent(&vecFinger0, entHand); vecFinger0.x *= -1; vec_for_ent(&vecFinger0, entHand); vec_to_ent(&vecFinger1, entHand); vecFinger1.x *= -1; vec_for_ent(&vecFinger1, entHand); } vec_lerp(vecFingerPos, &vecFinger0, &vecFinger1, 0.5); vec_diff(vecFingerDir, &vecFinger1, &vecFinger0); return vecFingerPos; }
void pAlphaFadeFlame(PARTICLE *p) { VECTOR vecTemp; vec_lerp(vecTemp, vector(128, 50, 50), vector(200, 180, 100), p.lifespan / 10); p.blue = vecTemp.z; p.green = vecTemp.y; p.blue = vecTemp.x; p.alpha = p.lifespan / 10 * 100 * 0.3; if (p.alpha <= 0) p.lifespan = 0; }
void creditsFog () { camera.fog_start = 128; camera.fog_end = 4000; fog_color = 1; vec_set(&d3d_fogcolor1.blue, vector(162, 174, 123)); VECTOR fogColor; vec_set(&fogColor, vector(d3d_fogcolor1.blue, d3d_fogcolor1.green, d3d_fogcolor1.red)); while (!creditsFinished) { vec_lerp(d3d_fogcolor1.blue, &fogColor, &sky_color, 0.5); wait(1); } }
void ebCreateHandJoints (ENTITY* entHand) { if (entHand == NULL) return; BOOL* arr = NULL; if (entHand->skill20 == 1) // left arr = g_handChopL; else // right arr = g_handChopR; int i; for (i = 0; i < HAND_FINGERS; i++) { if (arr[i] == false) { char* j0 = _chr((g_handBoneFarNames->pstring)[i]); char* j1 = _chr((g_handBoneNearNames->pstring)[i]); VECTOR v0, v1, v; vec_for_bone(&v0, entHand, j0); vec_for_bone(&v1, entHand, j1); vec_lerp(&v, &v0, &v1, 0.5); if (entHand->skill20 != 0) { vec_to_ent(&v, entHand); v.x *= -1; vec_for_ent(&v, entHand); } ENTITY* e = ent_create("handjoint.mdl", &v, ebHandJoint); e->skill1 = i; e->skill2 = entHand; } } }
static inline Vector3 quad_interpolate(const Vector3 a, const Vector3 b, const Vector3 c, const Vector3 d, double u, double v) { Vector3 ab = vec_lerp(a, b, u); Vector3 cd = vec_lerp(c, d, u); return vec_lerp(ab, cd, v); }
/* * Hill-Reilly pucker-paramter based coloring */ void lerp_color_range(float *newcol, float val, float rmin, float rmax, float *mincol, float *maxcol) { float range = rmax-rmin; float lerpval = (val - rmin) / range; vec_lerp(newcol, mincol, maxcol, lerpval); }
void bsp_tree_create_from_solid(struct BspTree* tree, struct Solid* solid) { size_t alloc_attributes_result = bsp_tree_alloc_attributes(tree, solid->attributes_size); log_assert( alloc_attributes_result >= solid->attributes_size ); size_t num_polygons = solid->indices_size/3; size_t alloc_polygons_result = bsp_tree_alloc_polygons(tree, num_polygons); log_assert( alloc_polygons_result >= num_polygons ); size_t alloc_nodes_result = bsp_tree_alloc_nodes(tree, num_polygons); log_assert( alloc_nodes_result >= num_polygons ); int32_t* workset_polygons_front = malloc(alloc_polygons_result * sizeof(int32_t)); log_assert( workset_polygons_front != NULL ); int32_t* workset_polygons_back = malloc(alloc_polygons_result * sizeof(int32_t)); log_assert( workset_polygons_back != NULL ); float min_x = FLT_MAX; float min_y = FLT_MAX; float min_z = FLT_MAX; float max_x = -FLT_MAX; float max_y = -FLT_MAX; float max_z = -FLT_MAX; for( size_t indices_i = 0; indices_i < solid->indices_size+1; indices_i++ ) { uint32_t src_i = solid->indices[indices_i]; if( indices_i < solid->indices_size ) { VecP* src = &solid->vertices[src_i*VERTEX_SIZE]; VecP* dst = &tree->attributes.vertices[indices_i*VERTEX_SIZE]; vec_copy3f(src, dst); tree->attributes.occupied += 1; if( src[0] < min_x ) { min_x = src[0]; } if( src[1] < min_y ) { min_y = src[1]; } if( src[2] < min_z ) { min_z = src[2]; } if( src[0] > max_x ) { max_x = src[0]; } if( src[1] > max_y ) { max_y = src[1]; } if( src[2] > max_z ) { max_z = src[2]; } } if( indices_i > 0 && indices_i % 3 == 0 ) { size_t poly_i = indices_i / 3 - 1; tree->polygons.array[poly_i].start = poly_i*3*VERTEX_SIZE; tree->polygons.array[poly_i].size = 3; polygon_normal(3, VERTEX_SIZE, &tree->attributes.vertices[poly_i*3*VERTEX_SIZE], tree->polygons.array[poly_i].normal); tree->polygons.occupied += 1; workset_polygons_front[poly_i] = poly_i; } } struct BspNode* root = &tree->nodes.array[0]; bsp_node_create(root); tree->nodes.occupied = 1; root->bounds.half_width = (max_x - min_x)/2.0f; root->bounds.half_height = (max_y - min_y)/2.0f; root->bounds.half_depth = (max_z - min_z)/2.0f; root->bounds.center[0] = min_x + root->bounds.half_width; root->bounds.center[1] = min_y + root->bounds.half_height; root->bounds.center[2] = min_z + root->bounds.half_depth; root->divider = 0; bsp_select_balanced_divider(tree, root, num_polygons, workset_polygons_front, &root->divider); struct BspPoly* root_divider = &tree->polygons.array[root->divider]; const float* root_divider_polygon = &tree->attributes.vertices[root_divider->start]; draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 0, 0, 255}, 0.01f, root_divider->size, root_divider_polygon, root_divider->normal); draw_vec(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 0, 0, 255}, 0.01f, root_divider->normal, &root_divider_polygon[3], 1.0f, 0.1f); /* draw_plane(&global_static_canvas, MAX_CANVAS_LAYERS-1, (Mat)IDENTITY_MAT, (Color){120, 120, 150, 127}, root_divider->normal, &root_divider_polygon[3], 10.0f); */ for( size_t polygon_i = 0; polygon_i < num_polygons; polygon_i++ ) { size_t cuts_polygon_size = 3; const float* cuts_polygon = &tree->attributes.vertices[polygon_i*cuts_polygon_size*VERTEX_SIZE]; size_t result_size = cuts_polygon_size; struct PolygonCutPoints result_points[cuts_polygon_size]; enum PolygonCutType result_type = polygon_cut(cuts_polygon_size, VERTEX_SIZE, cuts_polygon, root_divider->normal, root_divider_polygon, result_size, result_points); Vec3f cuts_polygon_normal = {0}; polygon_normal(3, VERTEX_SIZE, cuts_polygon, cuts_polygon_normal); switch(result_type) { case POLYGON_COPLANNAR: //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 255, 255, 255}, 0.01f, result_size, cuts_polygon, cuts_polygon_normal); break; case POLYGON_FRONT: //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 0, 255, 255}, 0.01f, result_size, cuts_polygon, cuts_polygon_normal); break; case POLYGON_BACK: //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){0, 0, 255, 255}, 0.01f, result_size, cuts_polygon, cuts_polygon_normal); break; case POLYGON_SPANNING: //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 255, 0, 255}, 0.01f, result_size, cuts_polygon, cuts_polygon_normal); if( result_points[0].num_cuts > 0 ) { size_t new_poly_size = cuts_polygon_size+result_points[0].num_cuts+10; size_t front_occupied = 0; float front_vertices[new_poly_size*VERTEX_SIZE]; size_t back_occupied = 0; float back_vertices[new_poly_size*VERTEX_SIZE]; for( size_t result_i = 0; result_i < result_size; result_i++ ) { if( result_points[result_i].type == POLYGON_BACK ) { vec_copy3f(&cuts_polygon[result_i*VERTEX_SIZE], &back_vertices[back_occupied*VERTEX_SIZE]); back_occupied += 1; } else if( result_points[result_i].type == POLYGON_FRONT ) { vec_copy3f(&cuts_polygon[result_i*VERTEX_SIZE], &front_vertices[front_occupied*VERTEX_SIZE]); front_occupied += 1; } else if( result_points[result_i].type == POLYGON_COPLANNAR ) { vec_copy3f(&cuts_polygon[result_i*VERTEX_SIZE], &back_vertices[back_occupied*VERTEX_SIZE]); back_occupied += 1; vec_copy3f(&cuts_polygon[result_i*VERTEX_SIZE], &front_vertices[front_occupied*VERTEX_SIZE]); front_occupied += 1; } if( result_points[result_i].interpolation_index > -1 ) { const VecP* a = &cuts_polygon[result_i*VERTEX_SIZE]; const VecP* b = &cuts_polygon[result_points[result_i].interpolation_index*VERTEX_SIZE]; Vec3f r = {0}; vec_lerp(b, a, result_points[result_i].interpolation_value, r); vec_copy3f(r, &back_vertices[back_occupied*VERTEX_SIZE]); back_occupied += 1; vec_copy3f(r, &front_vertices[front_occupied*VERTEX_SIZE]); front_occupied += 1; } } //printf("front_occupied: %lu\n", front_occupied); //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, red, 0.01f, front_occupied, front_vertices, cuts_polygon_normal); //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, white, 0.01f, back_occupied, back_vertices, cuts_polygon_normal); } break; } } log_fail(__FILE__, __LINE__, "BUILT BSP TREE... OR NOT?\n"); }
void net_entsync(ENTITY *ent) { ent.event = net_entsync_event; ent.emask |= ENABLE_RECEIVE; ent.smask = NOSEND_ALPHA | NOSEND_AMBIENT | NOSEND_ANGLES | NOSEND_ATTACH | NOSEND_COLOR | NOSEND_FLAGS | NOSEND_FRAME | NOSEND_LIGHT | NOSEND_ORIGIN | NOSEND_SCALE | NOSEND_SKIN | NOSEND_SOUND; // Wait for network handle while(ent.client_id < 0) wait(1); ent.NET_SKILL_LERPSPEED = net_ent_default_lerpspeed; proc_mode = PROC_GLOBAL | PROC_LATE; if(ent.client_id == dplay_id) { // Controller var update = net_ent_sendrate; while(handle(ent) != NULL) { // Send entity updates update -= time_step; if(update <= 0) { // Send position if distance since last update greater the minimum send distance if(vec_dist(ent.x, ent.NET_SKILL_POS_X) > net_ent_mindist) { vec_set(ent.NET_SKILL_POS_X, ent.x); if(net_ent_flags & NET_ENT_UNRELIABLE) send_skill(ent.NET_SKILL_POS_X, SEND_VEC | SEND_ALL | SEND_UNRELIABLE); else send_skill(ent.NET_SKILL_POS_X, SEND_VEC | SEND_ALL); } if(vec_dist(ent.pan, ent.NET_SKILL_ANG_PAN) > net_ent_mindiff) { vec_set(ent.NET_SKILL_ANG_PAN, ent.pan); if(net_ent_flags & NET_ENT_UNRELIABLE) send_skill(ent.NET_SKILL_ANG_PAN, SEND_VEC | SEND_ALL | SEND_UNRELIABLE); else send_skill(ent.NET_SKILL_ANG_PAN, SEND_VEC | SEND_ALL); } update = net_ent_sendrate; } wait(1); } } else { // Receiver while(handle(ent) != NULL) { if(net_ent_lerpfactor > 0) { // Lerping vec_lerp(ent.x, ent.x, ent.NET_SKILL_POS_X, net_ent_lerpfactor); ang_lerp(ent.pan, ent.pan, ent.NET_SKILL_ANG_PAN, net_ent_lerpfactor); } else { // Linear movement VECTOR dir; vec_diff(dir, ent.NET_SKILL_POS_X, ent.x); var dist = vec_length(dir); if(dist > 0.5 * net_ent_mindist) { vec_normalize(dir, minv(ent.NET_SKILL_LERPSPEED * time_step, dist)); vec_add(ent.x, dir); } vec_set(ent.pan, ent.NET_SKILL_ANG_PAN); } wait(1); } } }
action ebWarghost () { g_entEbWarghost = my; my->material = g_mtlBossGhost; lvlLavaSuperReset (); var deadRotate = 0; var origScale = my->scale_x; var deadScale = origScale; BOOL isSpining = false; while (1) { // pos { VECTOR vecPos; vecPos.x = my->x; vecPos.y = 1024; vecPos.z = 150; if (player != NULL) { vecPos.x = player->x; vecPos.z = player->z; } vec_lerp(my->x, my->x, &vecPos, time_step * 0.025); } // ang { VECTOR vecLookAt, vecLook; vec_set(&vecLookAt, my->x); vecLookAt.y -= 1000; if (player != NULL) { vecLookAt.x = player->x; vecLookAt.y = player->y; } vec_diff(&vecLook, &vecLookAt, my->x); vec_to_angle(my->pan, &vecLook); if (!isEbWarghostAlive()) { setPlayerControls(false); setPlayerPan(my); deadRotate += 10 * time_step; deadScale += 0.3 * time_step; g_sndEbVol = clamp(g_sndEbVol - g_sndEbVolDec * time_step, 0, 100); snd_tune(g_fhLvlLavastageSong, g_sndEbVol, 3, 0); if (!isSpining) { snd_play(g_sndBossSpin, 100, 0); snd_play(g_sndBossDeadSpeech, 100, 0); isSpining = true; } } my->pan += deadRotate; my->scale_x = my->scale_y = my->scale_z = deadScale; if (my->scale_x / origScale > 3) break; } if (g_ebDoHit) ent_animate(my, "jump", g_ebDoHitPercent, ANM_CYCLE); else ent_animate(my, "attack", total_ticks % 100, ANM_CYCLE); wait(1); } snd_play(g_sndBossSplatter, 100, 0); VECTOR vecPos, vecDir; int i, j, numVerts = ent_status(my, 0); snd_play(g_sndBossDead, 100, 0); set(my, INVISIBLE); for (i = 0; i < numVerts; i++) { vec_for_vertex(&vecPos, my, i+1); vec_diff(&vecDir, &vecPos, my->x); vec_normalize(&vecDir, 1); effEbBlood(&vecPos, &vecDir, 25+random(100), false, 1, 4 + random(4)); } while (redness < 100) { redness = clamp(redness + g_rednessInc * time_step, 0, 100); g_sndEbVol = clamp(g_sndEbVol - g_sndEbVolDec * time_step, 0, 100); snd_tune(g_fhLvlLavastageSong, g_sndEbVol, 5, 0); wait(1); } wait(-1); proc_mode = PROC_GLOBAL; ptr_remove(my); creditsInit(); }
void ebHandWatch () { updateHandChopped(my); ebDoSparkle(my, 2000); snd_play(g_sndSparkle, 100, 0); set(my, PASSABLE); my->ambient = 75; var moveAnim = 10; var t = maxv(g_facTimeEbHandWatchMin, g_facTimeEbHandWatch * (5 + random(3))) * 16; vec_scale(my->scale_x, g_handScale); var ground, height; var heightSub = 32; g_ebHand = my; snd_play(g_sndHandFly, 100, 0); // move with player set(player, FLAG2); while (t > 0) { VECTOR vecBoneGround, vecTraceStart, vecTraceEnd; vec_for_bone(&vecBoneGround, my, "ground"); vec_set(&vecTraceStart, my->x); vecTraceStart.y = vecBoneGround.y; vec_set(&vecTraceEnd, &vecTraceStart); vecTraceEnd.z -= 2000; height = player->z + 250; if (c_trace(&vecTraceStart, &vecTraceEnd, IGNORE_ME | USE_POLYGON | IGNORE_FLAG2 ) > 0) { ground = hit.z; height = ground + (my->z - vecBoneGround.z); } VECTOR v; vec_set(&v, player->x); v.z = height; vec_lerp(my->x, my->x, &v, 0.25 * time_step); ent_animate(my, "idleH", 50 + sin(total_ticks * moveAnim) * 50, ANM_CYCLE); t -= time_step; doHandChopBlood(my); wait(1); } g_facTimeEbHandWatch *= g_facTimeEbHandWatchDec; reset(player, FLAG2); // drop g_handDropping = true; g_ebHand->skill1 = 1; // joints = on g_ebHand->skill2 = 1; // joints death = on g_playerDontScanFlag2 = true; g_playerNoYou = true; ebCreateHandJoints(g_ebHand); set(player, ZNEAR); t = 0; BOOL bSndHandDrop = true; while (t < 100) { VECTOR vecBoneGround; vec_for_bone(&vecBoneGround, g_ebHand, "ground"); height = ground + (g_ebHand->z - vecBoneGround.z) - heightSub; VECTOR v; vec_set(&v, g_ebHand->x); v.z = height; vec_lerp(g_ebHand->x, g_ebHand->x, &v, 0.25 * time_step); t = clamp(t + 5 * time_step, 0, 100); ent_animate(g_ebHand, "drop", t, 0); doHandChopBlood(my); if (t > 90 && bSndHandDrop) { bSndHandDrop = false; snd_play(g_sndHandDrop, 100, 0); } wait(1); } g_handDropping = false; g_ebHand->skill2 = 0; // joints death = off t = maxv(g_facTimeEbHandDroppedMin, g_facTimeEbHandDropped * (3+random(2)) * 16); g_fingerChopped = false; // wait while (t > 0 && !g_fingerChopped) { ent_animate(g_ebHand, "down", (total_ticks * 4), ANM_CYCLE); t -= time_step; doHandChopBlood(my); wait(1); } g_facTimeEbHandDropped *= g_facTimeEbHandDroppedDec; snd_play(g_sndHandUp, 100, 0); reset(player, ZNEAR); g_ebHand->skill1 = 0; // up while (t < 100) { VECTOR vecBoneGround; vec_for_bone(&vecBoneGround, g_ebHand, "ground"); height = ground + (g_ebHand->z - vecBoneGround.z) - heightSub; VECTOR v; vec_set(&v, g_ebHand->x); v.z = height; vec_lerp(g_ebHand->x, g_ebHand->x, &v, 0.25 * time_step); t = clamp(t + 2 * time_step, 0, 100); ent_animate(g_ebHand, "up", t, 0); doHandChopBlood(my); wait(1); } g_playerDontScanFlag2 = false; g_playerNoYou = false; t = 1.5 * 16; snd_play(g_sndHandBliss, 100, 0); // go away while (t > 0) { t -= time_step; g_ebHand->z += 10 * time_step; g_ebHand->y -= 20 * time_step; g_ebHand->roll += 5 * time_step; doHandChopBlood(my); wait(1); } set(g_ebHand, INVISIBLE); ebDoSparkle(g_ebHand, 2000); snd_play(g_sndSparkle, 100, 0); wait(1); ent_create(NULL, nullvector, ebHandsBgFly); ptr_remove(g_ebHand); }
void ebHandFly () { updateHandChopped(my); set(my, PASSABLE); my->ambient = 75; VECTOR startPos, targetPos; vec_set(&startPos, my->x); ebDoSparkle(my, 2000); var t = 0; var distX = 500; var moveDist = 200; var moveTime = 0.5; var moveLerp = 0.2; var moveAnim = 2; vec_scale(my->scale_x, g_handScale); var targetRoll = -90; // Stone rain var randomStoneRain = 0; var randomStoneModel = 0; while (my->skill1 == 0) { if (t <= 0) { vec_set(&targetPos, vector(25+random(moveDist), 0, 0)); vec_rotate(&targetPos, vector(random(360),random(360),random(360))); vec_add(&targetPos, &startPos); t += moveTime * 16; } else t -= time_step; VECTOR nuPos; vec_set(&nuPos, &targetPos); if (player != NULL) nuPos.x += player->x; vec_lerp(my->x, my->x, &nuPos, moveLerp * time_step); ent_animate(my, "idleH", (total_ticks * moveAnim) % 100, ANM_CYCLE); my->roll += (targetRoll - my->roll) * 0.05 * clamp(time_step, 0.001, 1); doHandChopBlood(my); if (!isEbWarghostAlive()) { startPos.z -= 10 * time_step; targetPos.z -= 10 * time_step; targetRoll -= 10 * time_step; } // Stone rain randomStoneRain = random(1000); if (randomStoneRain > 950) { randomStoneModel = integer(random(2)); switch(randomStoneModel) { case 0: ent_create("stein1.mdl", vector(player.x - 500 + random(1000), player.y, my.z + 300 + random(50)), ebHandStone); break; case 1: ent_create("stein2.mdl", vector(player.x - 500 + random(1000), player.y, my.z + 300 + random(50)), ebHandStone); break; case 2: ent_create("stein3.mdl", vector(player.x - 500 + random(1000), player.y, my.z + 300 + random(50)), ebHandStone); break; } } // -- end stone rain wait(1); } while (my->skill2 > 0) { my->skill2 -= time_step; my->z += 10 * time_step; my->y -= 20 * time_step; my->roll += 2 * time_step; doHandChopBlood(my); wait(1); } set(my, INVISIBLE); ebDoSparkle(my, 2000); wait(1); ptr_remove(my); }