/// //Rotates the runner controller // obj: A pointer to the game object to rotate // state: A pointer to the runner controller rotating the object void State_RunnerController_Rotate(GObject* obj, State* state) { // create a camera object Camera* cam = RenderingManager_GetRenderingBuffer()->camera; //Grab the state members struct State_RunnerController_Members* members = (struct State_RunnerController_Members*)state->members; // if player's mouse is locked if(InputManager_GetInputBuffer().mouseLock) { int deltaMouseX = (InputManager_GetInputBuffer().mousePosition[0] - InputManager_GetInputBuffer().previousMousePosition[0]); int deltaMouseY = (InputManager_GetInputBuffer().mousePosition[1] - InputManager_GetInputBuffer().previousMousePosition[1]); Vector* axis = Vector_Allocate(); Vector_Initialize(axis,3); if(deltaMouseX != 0) { axis->components[1] = 1.0f; // rotate the camera Camera_ChangeYaw(cam, members->angularVelocity * deltaMouseX); axis->components[1] = 0.0f; } if (deltaMouseY != 0) { Vector forwardVector; Vector_INIT_ON_STACK(forwardVector, 3); Matrix_SliceRow(&forwardVector, cam->rotationMatrix, 2, 0, 3); // Keep camera from overextending it's boundaries. if (deltaMouseY > 0) { if (Vector_DotProduct(&forwardVector, &Vector_E2) < 0.7f) { axis->components[0] = 1.0f; Camera_ChangePitch(cam, members->angularVelocity * deltaMouseY); axis->components[0] = 0.0f; } } else if (deltaMouseY < 0) { if (Vector_DotProduct(&forwardVector, &Vector_E2) > -0.7f) { axis->components[0] = 1.0f; Camera_ChangePitch(cam, members->angularVelocity * deltaMouseY); axis->components[0] = 0.0f; } } } } }
static void PVS_Add(struct map *map, struct pvs *pvs, struct node *node) { int i; float d; struct plane *plane; unsigned char *lpvs; while(1) { if (node->contents < 0) { if (node->contents != CONTENTS_SOLID) { lpvs = LEAF_PVS(map, (struct leaf *)node); for (i=0; i<pvs->bytes; i++) pvs->pvs [i] |= lpvs[i]; } return; } plane = node->plane; d = Vector_DotProduct(pvs->origin, plane->normal) - plane->dist; if (d>8) node = node->children[0]; else if (d<-8) node = node->children[1]; else { PVS_Add(map, pvs, node->children[0]); node = node->children[1]; } } }
//************************************************************************************* // Apply spring force on two physical vertexes //************************************************************************************* void ApplySpring(EERIE_3DOBJ * obj, long k, long l, float PHYSICS_constant, float PHYSICS_Damp) { EERIE_3D deltaP, deltaV, springforce; PHYSVERT * pv_k = &obj->pbox->vert[k]; PHYSVERT * pv_l = &obj->pbox->vert[l]; float Dterm, Hterm; float restlength = TRUEEEDistance3D(&obj->pbox->vert[k].initpos, &obj->pbox->vert[l].initpos); //Computes Spring Magnitude deltaP.x = pv_k->pos.x - pv_l->pos.x; // Vector distance deltaP.y = pv_k->pos.y - pv_l->pos.y; // Vector distance deltaP.z = pv_k->pos.z - pv_l->pos.z; // Vector distance float dist = (float)TRUEsqrt(deltaP.x * deltaP.x + deltaP.y * deltaP.y + deltaP.z * deltaP.z); // Magnitude of delta float divdist = 1.f / dist; Hterm = (dist - restlength) * PHYSICS_constant; deltaV.x = pv_k->velocity.x - pv_l->velocity.x; deltaV.y = pv_k->velocity.y - pv_l->velocity.y; deltaV.z = pv_k->velocity.z - pv_l->velocity.z; // Delta Velocity Vector Dterm = (Vector_DotProduct(&deltaV, &deltaP) * PHYSICS_Damp) * divdist; // Damping Term Dterm = (-(Hterm + Dterm)); divdist *= Dterm; springforce.x = deltaP.x * divdist; // Normalize Distance Vector springforce.y = deltaP.y * divdist; // & Calc Force springforce.z = deltaP.z * divdist; pv_k->force.x += springforce.x; // + force on particle 1 pv_k->force.y += springforce.y; pv_k->force.z += springforce.z; pv_l->force.x -= springforce.x; // - force on particle 2 pv_l->force.y -= springforce.y; pv_l->force.z -= springforce.z; }
void Matrix_Apply(const Matrix *m,const Vector *b,Vector *a) { uint r; assert( a && b && m ); assert( a->length == b->length && a->length == m->dimension ); assert( a != b ); for(r=0;r<m->dimension;r++) { a->element[r] = Vector_DotProduct(b,m->rows[r]); } }
/// //Accelerates the runner controller // //PArameters: // obj: A pointer to the game object to accelerate // state: A pointer to rhe runner controller state which is accelerating this object void State_RunnerController_Accelerate(GObject* obj, State* state) { //Grab the state members struct State_RunnerController_Members* members = (struct State_RunnerController_Members*)state->members; //Grab the forward vector from the camera Camera* cam = RenderingManager_GetRenderingBuffer()->camera; Vector forward; Vector_INIT_ON_STACK(forward, 3); Matrix_SliceRow(&forward, cam->rotationMatrix, 2, 0, 3); //Project the forward vector onto the XY Plane Vector perp; Vector_INIT_ON_STACK(perp, 3); Vector_GetProjection(&perp, &forward, &Vector_E2); Vector_Decrement(&forward, &perp); //Scale the vector to the acceleration Vector_Normalize(&forward); Vector_Scale(&forward, -members->acceleration); //Only apply the impulse if the velocity is less than the max speed if(Vector_GetMag(obj->body->velocity) - fabs(Vector_DotProduct(obj->body->velocity, &Vector_E2)) < members->maxVelocity) { //Apply the impulse RigidBody_ApplyForce(obj->body, &forward, &Vector_ZERO); } else { printf("Value:\t%f\n", Vector_GetMag(obj->body->velocity) - fabs(Vector_DotProduct(obj->body->velocity, &Vector_E2))); } }
/// //Allows the runner controller to wallrun if necessary conditions are met // //Parameters: // obj: A pointer to the object which is running on walls // state: A pointer to the runner controller state which is allowing the object to wallrun void State_RunnerController_Wallrun(GObject* obj, State* state) { //Get the members of this state struct State_RunnerController_Members* members = (struct State_RunnerController_Members*)state->members; //Get the first collision this object is involved in Collision* first = (Collision*)obj->collider->currentCollisions->head->data; //If we are not wallrunning yet if(members->horizontalRunning == 0 && members->verticalRunning == 0) { //Make sure this is a wall if(first->minimumTranslationVector->components[0] != 0.0 || first->minimumTranslationVector->components[2] != 0.0f) { //Save the normal Vector_Copy(members->wallNormal, first->minimumTranslationVector); if(first->obj1 != obj) { Vector_Scale(members->wallNormal, -1.0f); } //Determine what kind of wallrun is occurring //First get the forward vector of the camera Camera* cam = RenderingManager_GetRenderingBuffer()->camera; Vector forward; Vector_INIT_ON_STACK(forward, 3); Matrix_SliceRow(&forward, cam->rotationMatrix, 2, 0, 3); //Project the forward vector onto the XY Plane Vector perp; Vector_INIT_ON_STACK(perp, 3); Vector_GetProjection(&perp, &forward, &Vector_E2); Vector_Decrement(&forward, &perp); Vector_Normalize(&forward); //Get dot product of forward vector and collision normal float dotProd = fabs(Vector_DotProduct(&forward, first->minimumTranslationVector)); //If the dot product is closer to 0 we are horizontal running, else we are vertical running if(dotProd < 0.75) { members->horizontalRunning = 1; } else { members->verticalRunning = 1; } } } //If we are horizontal running if(members->horizontalRunning == 1) { printf("Horizontal Wallrunnin\n"); //combat the force of gravity Vector antiGravity; Vector_INIT_ON_STACK(antiGravity, 3); antiGravity.components[1] = 9.81f; RigidBody_ApplyForce(obj->body, &antiGravity, &Vector_ZERO); //Zero downward velocity if(obj->body->velocity->components[1] < 0.0f) { Vector_Copy(&antiGravity, &Vector_ZERO); antiGravity.components[1] = -obj->body->velocity->components[1]; RigidBody_ApplyImpulse(obj->body, &antiGravity, &Vector_ZERO); } State_RunnerController_Accelerate(obj, state); } else if(members->verticalRunning == 1) { printf("Vertical Wallrunnin\n"); //combat the force of gravity Vector antiGravity; Vector_INIT_ON_STACK(antiGravity, 3); Vector_Copy(&antiGravity, &Vector_E2); //go up! Vector_Scale(&antiGravity, 9.81); RigidBody_ApplyForce(obj->body, &antiGravity, &Vector_ZERO); //If we aren't jumping too fast yet if(Vector_DotProduct(obj->body->velocity, &Vector_E2) < members->maxVelocity) { Vector_Copy(&antiGravity, &Vector_E2); Vector_Scale(&antiGravity, members->acceleration); RigidBody_ApplyForce(obj->body, &antiGravity, &Vector_ZERO); } } }
int Trace_RecursiveHullTrace(struct trace_local *tl, int num, float p1f, float p2f, const vec3_t p1, const vec3_t p2) { struct plane *plane; float t1, t2, frac, midf; struct clipnode *node; int i, nearside, check, oldcheck; vec3_t mid; struct hull *hull = tl->hull; struct trace *trace = tl->trace; while (1) { if (num < 0) { tl->leafs_count++; if (num == CONTENTS_SOLID) { if (tl->leafs_count == 1) trace->startsolid = true; return TR_SOLID; } else { if (num == CONTENTS_EMPTY) trace->inopen = true; else trace->inwater = true; return TR_EMPTY; } } node = hull->clipnodes + num; plane = hull->planes + node->planenum; //printf("t_rht: %p %p %i %i %f ", node, plane, node->planenum, plane->type, plane->dist); //PRINT_VEC(plane->normal); if (plane->type < 3) { t1 = p1[plane->type] - plane->dist; t2 = p2[plane->type] - plane->dist; //printf("t_rht 1: t1, t2, plane->dist %f %f %f\n", t1, t2, plane->dist); } else { t1 = Vector_DotProduct(plane->normal, p1) - plane->dist; t2 = Vector_DotProduct(plane->normal, p2) - plane->dist; //printf("t_rht 2: t1, t2, plane->dist %f %f %f\n", t1, t2, plane->dist); } if (t1 >= 0 && t2 >= 0) { num = node->children[0]; continue; } if (t1 < 0 && t2 < 0) { num = node->children[1]; continue; } frac = t1 / (t1 - t2); frac = bound(0, frac, 1); midf = p1f + (p2f - p1f) * frac; for (i=0; i<3; i++) mid[i] = p1[i] + frac * (p2[i] - p1[i]); nearside = (t1 < t2) ? 1 : 0; //printf("doing trace 1 %f %f\n", frac, midf); check = Trace_RecursiveHullTrace(tl, node->children[nearside], p1f, midf, p1, mid); if (check == TR_BLOCKED) { return check; } if (check == TR_SOLID && (trace->inopen || trace->inwater)) { return check; } oldcheck = check; //printf("doing trace 2\n"); check = Trace_RecursiveHullTrace(tl, node->children[1 - nearside], midf, p2f, mid, p2); if (check == TR_EMPTY || check == TR_BLOCKED) { return check; } if (oldcheck != TR_EMPTY) { return check; } if (!nearside) { Vector_Copy(trace->plane.normal, plane->normal); trace->plane.dist = plane->dist; } else { Vector_Negate(trace->plane.normal, plane->normal); trace->plane.dist = -plane->dist; } if (t1 < t2) frac = (t1 + DIST_EPSILON) / (t1 - t2); else frac = (t1 - DIST_EPSILON) / (t1 - t2); frac = bound(0, frac, 1); midf = p1f + (p2f - p1f) * frac; for (i=0; i<3; i++) mid[i] = p1[i] + frac * (p2[i] - p1[i]); trace->fraction = midf; //printf("fraction: %f\n", midf); Vector_Copy(trace->endpos, mid); return TR_BLOCKED; } #warning maybe return smth else here return TR_BLOCKED; }
/// //Allows the parkour controller to run up a wall // //Parameters: // obj: A pointer to the object attached to the parkourController state // state: The parkourController state updating the object static void State_ParkourController_Wallrun(GObject* obj, State* state) { //Get the members of this state struct State_ParkourController_Members* members = (struct State_ParkourController_Members*)state->members; //If we are not vertical wallrunning yet if(members->verticalRunning == 0 && members->horizontalRunning == 0) { //Loop through the list of collisions this object was involved in struct LinkedList_Node* currentNode = obj->collider->currentCollisions->head; while(currentNode != NULL) { //Get the current collision struct Collision* current = (struct Collision*)currentNode->data; //Make sure this collision is with a wall //TODO: Epsilon check!!! if(current->minimumTranslationVector->components[0] != 0.0f || current->minimumTranslationVector->components[2] != 0.0f) { //Make a copy of the collision normal in case of manipulation Vector currentNormal; Vector_INIT_ON_STACK(currentNormal, 3); Vector_Copy(¤tNormal, current->minimumTranslationVector); //Make sure the normal is pointing toward this object if(current->obj1 != obj) { Vector_Scale(¤tNormal, -1.0f); } //Next we must determine what kind of wallrun is happening //Start by getting for forward vector of the camera Camera* cam = RenderingManager_GetRenderingBuffer()->camera; Vector forward; Vector_INIT_ON_STACK(forward, 3); Matrix_SliceRow(&forward, cam->rotationMatrix, 2, 0, 3); //Project the forward vector onto the XY plane Vector perp; Vector_INIT_ON_STACK(perp, 3); Vector_GetProjection(&perp, &forward, &Vector_E2); Vector_Decrement(&forward, &perp); Vector_Normalize(&forward); //Get the dot product of the forward vector and collision normal float dotProduct = Vector_DotProduct(&forward, ¤tNormal); //If the dot product is closer to 1, we are starting to vertically wallrun if(dotProduct > 0.75f) { members->verticalRunning = 1; //Vertical wall running always has higher precedence than horizontal wall running members->horizontalRunning = 0; //SEt the wall normal of state Vector_Copy(members->wallNormal, ¤tNormal); break; } else if(dotProduct > 0.0f) { members->horizontalRunning = 1; //Set the wall normal of state Vector_Copy(members->wallNormal, ¤tNormal); } } currentNode = currentNode->next; } } //If we are vertical wall running if(members->verticalRunning) { State_ParkourController_VerticalWallrun(obj, state); } //else If we are horizontal wall running else if(members->horizontalRunning) { State_ParkourController_HorizontalWallrun(obj, state); } }
/// //Allows the parkour controller to horizontally wallrun // //Parameters: // obj: A pointer to the object attached to the parkourController state // state: The parkourController state updating the object static void State_ParkourController_HorizontalWallrun(GObject* obj, State* state) { printf("Horizontal\n"); //Get the members of this state struct State_ParkourController_Members* members = (struct State_ParkourController_Members*)state->members; //Zero downward velocity if(obj->body->velocity->components[1] < 0.0f) { Vector impulse; Vector_INIT_ON_STACK(impulse, 3); impulse.components[1] = -obj->body->velocity->components[1]; RigidBody_ApplyImpulse(obj->body, &impulse, &Vector_ZERO); } //Accelerate along wall //Get the projection of the forward vector onto the wall's plane //Start by getting for forward vector of the camera Camera* cam = RenderingManager_GetRenderingBuffer()->camera; Vector forward; Vector_INIT_ON_STACK(forward, 3); Matrix_SliceRow(&forward, cam->rotationMatrix, 2, 0, 3); //Forward of camera is back of object... Vector_Scale(&forward, -1.0f); //Project the forward vector onto the wall plane Vector perp; Vector_INIT_ON_STACK(perp, 3); Vector_GetProjection(&perp, &forward, members->wallNormal); Vector_Decrement(&forward, &perp); //Set the Y component to 0 to get horizontal vector along wall! forward.components[1] = 0.0f; Vector_Normalize(&forward); //MAke sure the velocity in this direction is not too much float magVelAlongWall = Vector_DotProduct(&forward, obj->body->velocity); if(magVelAlongWall < members->maxVelocity) { RigidBody_ApplyImpulse(obj->body, &forward, &Vector_ZERO); } //Apply a cohesive force to the wall to make sure you do not fall off float mag = Vector_DotProduct(obj->body->velocity, members->wallNormal); Vector cohesive; Vector_INIT_ON_STACK(cohesive, 3); if(mag > FLT_EPSILON) { Vector_GetScalarProduct(&cohesive, members->wallNormal, -mag); } else if(mag < FLT_EPSILON) { Vector_GetScalarProduct(&cohesive, members->wallNormal, mag); } RigidBody_ApplyImpulse(obj->body, &cohesive, members->wallNormal); }