Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ## Here's the main game loop (just the relevant parts anyway):
- ```
- //Update camera
- //BUGFIX: Stage tilt doesn't seem to take camera rotation into account, figure out why and fix
- //BUGFIX: Shadows rotate in the opposite direction as expected, figure out why and fix
- if(glm::length2(glm::vec2(p->Velocity.x,p->Velocity.z))>0.000001f) {
- float vang = atan2f(-p->Velocity.x,-p->Velocity.z);
- if(GameSubmode!=2) {
- vang = -vang;
- }
- if(vang<0) {vang+=6.283185f;}
- float delta = fmodf(vang-PrevCamAngle,6.283185f);
- vang = fmodf(2*delta,6.283185f)-delta;
- PrevCamAngle = PrevCamAngle+(vang*0.25f);
- if(PrevCamAngle<0) {PrevCamAngle+=6.283185f;}
- }
- glm::quat PrevCamRotation = glm::angleAxis(PrevCamAngle,glm::vec3(0,1,0));
- //Initialize gravity vector
- glm::vec3 gravity(0,-0.098f,0);
- //Set target to no rotation (so that goal/perfect end sequences slow down ball gradually)
- glm::quat target = glm::quat(1,0,0,0);
- glm::quat target2 = glm::quat(1,0,0,0);
- //If gameplay is active, set target according to input
- if(GameSubmode==2) {
- target = PrevCamRotation*
- glm::angleAxis(-AnalogX/2,glm::vec3(0,0,1))*
- glm::angleAxis(-AnalogY/2,glm::vec3(1,0,0));
- target2 = PrevCamRotation*
- glm::angleAxis(AnalogX/2,glm::vec3(0,0,1))*
- glm::angleAxis(AnalogY/2,glm::vec3(1,0,0));
- } else if(GameSubmode==4) {
- }
- //Update stage rotation, and rotate gravity vector accordingly
- PrevStageRotation = glm::slerp(PrevStageRotation,target,0.05f);
- PrevGravRotation = glm::slerp(PrevGravRotation,target2,0.05f);
- gravity = PrevGravRotation*gravity;
- //Clear previous collisions
- bool isColi = false;
- float minDist = 2;
- glm::vec3 coliNrm = glm::vec3(0);
- glm::vec3 coliPt;
- //Check for stage collisions
- CollisionResult * cr = new CollisionResult();
- //For each stage object
- for(int i=OBJID_STAGE; i<OBJID_GOALS; i++) {
- //If the stage object exists and has collision
- if(objBuffer[i].IsActive && objBuffer[i].HasCollision) {
- //TODO: Pre-transform player
- //Calculate collision
- objBuffer[i].ObjCollision->CollideSphere(cr,p->Position,p->Velocity);
- //If player is colliding
- if(cr->IsCollision) {
- isColi = true;
- minDist = cr->CollisionDistance;
- coliPt = cr->CollisionPoint;
- coliNrm = cr->CollisionNormal;
- }
- //TODO: Post-transform player
- }
- }
- //Check for object collisions
- //OMITTED FOR CLARITY
- //Handle rolling and friction
- //If there was a collision
- //BUGFIX: The ball is all jittery, figure out how best to fix
- if(isColi) {
- float dp = glm::dot(coliNrm,p->Velocity);
- if(dp<0) {
- p->Velocity += -1.7f*dp*coliNrm;
- //p->Position += -0.2f*(0.5f-minDist)*dp*coliNrm;
- }
- //Rotate ball against surface normal
- glm::quat rot = glm::angleAxis(glm::length(p->Velocity)*2,glm::cross(coliNrm,p->Velocity));
- p->Rotation = glm::normalize(rot*p->Rotation);
- //Adjust velocity for friction
- float d = glm::dot(coliNrm,glm::normalize(gravity));
- float fric = 0.9f*sqrtf(1.001f-(d*d));
- float d2 = glm::dot(coliNrm,p->Velocity);
- glm::vec3 proj = d2*coliNrm;
- glm::vec3 rej = p->Velocity-proj;
- p->Velocity = proj + fric*rej;
- }
- PrevColiNrm = coliNrm;
- //Update ball position
- p->Position += p->Velocity;
- //Update ball velocity
- p->Velocity += gravity;
- //Check for terminal velocity (to avoid clipping)
- if(glm::length2(p->Velocity)>1) {
- p->Velocity = glm::normalize(p->Velocity);
- }
- //TODO: animate player
- //Update object specific properties
- //OMITTED FOR CLARITY
- //Display ball
- u_CameraPos = PrevStageRotation*(p->Position+(PrevCamRotation*glm::vec3(0,2,5)));
- u_View = glm::lookAt(u_CameraPos,PrevStageRotation*p->Position,glm::vec3(0,1,0));
- objBuffer[OBJID_BALL_INNER].Position = objBuffer[OBJID_BALL_OUTER].Position = PrevStageRotation*p->Position;
- objBuffer[OBJID_MONKEY].Position = PrevStageRotation*(p->Position + glm::vec3(0,-0.5f,0));
- objBuffer[OBJID_BALL_INNER].Rotation = objBuffer[OBJID_BALL_OUTER].Rotation = glm::normalize(PrevStageRotation*p->Rotation);
- objBuffer[OBJID_MONKEY].Rotation = glm::normalize(PrevStageRotation);
- //Rotate and animate stage and objects
- for(int i=OBJID_STAGE; i<OBJID_BUTTONS; i++) {
- if(objBuffer[i].IsActive) {
- //TODO: animate objects
- //Update object position and rotation to reflect stage tilt
- objBuffer[i].Position = PrevStageRotation*objBuffer[i].TruePosition;
- objBuffer[i].Rotation = glm::normalize(PrevStageRotation*objBuffer[i].TrueRotation);
- }
- }
- ```
- ## Here are the collision routines (pretty sure these are correct, like 99%):
- ```
- void FCOL::CollideSphere(CollisionResult * result, glm::vec3 position, glm::vec3 velocity) {
- result->IsCollision = false;
- CollisionResult * cr = new CollisionResult();
- result->CollisionDistance = 2;
- for(int i=0; i<TriCount; i++) {
- if(glm::dot(velocity,Entries[i].Normal)<0) {
- Entries[i].CollideSphere(cr,position);
- if(cr->IsCollision) {
- if(result->CollisionDistance>cr->CollisionDistance) {
- result->IsCollision = true;
- result->CollisionDistance = cr->CollisionDistance;
- result->CollisionPoint = cr->CollisionPoint;
- result->CollisionNormal = Entries[i].Normal;
- }
- }
- }
- }
- return;
- }
- void FCOLTriangle::CollideSphere(CollisionResult * result, glm::vec3 position) {
- result->IsCollision = false;
- glm::vec3 ap = Points[0]-position;
- glm::vec3 bp = Points[1]-position;
- glm::vec3 cp = Points[2]-position;
- float rr = 0.25f;
- glm::vec3 v = glm::cross(bp-ap,cp-ap);
- float d = glm::dot(ap,v);
- float e = glm::dot(v,v);
- if((d*d)>(rr*e)) {return;}
- float aa = glm::dot(ap,ap);
- float ab = glm::dot(ap,bp);
- float ac = glm::dot(ap,cp);
- float bb = glm::dot(bp,bp);
- float bc = glm::dot(bp,cp);
- float cc = glm::dot(cp,cp);
- if(aa>rr && ab>aa && ac>aa) {return;}
- if(bb>rr && ab>bb && bc>bb) {return;}
- if(cc>rr && ac>cc && bc>cc) {return;}
- glm::vec3 a2b = bp-ap;
- glm::vec3 b2c = cp-bp;
- glm::vec3 c2a = ap-cp;
- float d1 = ab-aa;
- float d2 = bc-bb;
- float d3 = ac-cc;
- float e1 = glm::dot(a2b,a2b);
- float e2 = glm::dot(b2c,b2c);
- float e3 = glm::dot(c2a,c2a);
- glm::vec3 q1 = ap*e1 - d1*a2b;
- glm::vec3 q2 = bp*e2 - d2*b2c;
- glm::vec3 q3 = cp*e3 - d3*c2a;
- glm::vec3 qc = cp*e1 - q1;
- glm::vec3 qa = ap*e2 - q2;
- glm::vec3 qb = bp*e3 - q3;
- if(glm::dot(q1,q1)>(rr*e1*e1) && glm::dot(q1,qc)>0) {return;}
- if(glm::dot(q2,q2)>(rr*e2*e2) && glm::dot(q2,qa)>0) {return;}
- if(glm::dot(q3,q3)>(rr*e3*e3) && glm::dot(q3,qb)>0) {return;}
- result->IsCollision = true;
- float dist = glm::dot(ap,Normal);
- glm::vec3 pnt = position+dist*Normal;
- float dist2 = sqrtf(glm::dot(ap,ap));
- if(fabsf(dist2)<fabsf(dist)) {
- dist = dist2;
- pnt = Points[0];
- }
- dist2 = sqrtf(glm::dot(bp,bp));
- if(fabsf(dist2)<fabsf(dist)) {
- dist = dist2;
- pnt = Points[1];
- }
- dist2 = sqrtf(glm::dot(cp,cp));
- if(fabsf(dist2)<fabsf(dist)) {
- dist = dist2;
- pnt = Points[2];
- }
- dist2 = glm::length(ap-glm::dot(ap,glm::normalize(a2b))*glm::normalize(a2b));
- if(fabsf(dist2)<fabsf(dist)) {
- dist = dist2;
- pnt = position+dist*glm::normalize(a2b);
- }
- dist2 = glm::length(bp-glm::dot(bp,glm::normalize(b2c))*glm::normalize(b2c));
- if(fabsf(dist2)<fabsf(dist)) {
- dist = dist2;
- pnt = position+dist*glm::normalize(b2c);
- }
- dist2 = glm::length(cp-glm::dot(cp,glm::normalize(c2a))*glm::normalize(c2a));
- if(fabsf(dist2)<fabsf(dist)) {
- dist = dist2;
- pnt = position+dist*glm::normalize(c2a);
- }
- result->CollisionPoint = pnt;
- result->CollisionDistance = fabsf(dist);
- }
- ```
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement