// Person simulation and visualization // Copyright (C) 2002 David Rosen // Copyright (C) 2021 Nguyễn Gia Phong // // This file is part of Black Shades. // // Black Shades is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Black Shades is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Black Shades. If not, see . #include #include "Person.h" extern float multiplier; extern unsigned int gSourceID[100]; extern unsigned int gSampleSet[100]; extern Animation animation[30]; extern int thirdperson; extern int visions; extern Camera camera; extern float rad2deg; extern Model gunmodels[10]; extern Model skeletonmodels[10]; extern Sprites sprites; extern float soundscalefactor; extern int slomo; extern int forwardskey; extern int backwardskey; extern int leftkey; extern int rightkey; extern int aimkey; extern int psychicaimkey; extern int psychickey; extern Model skeletonmodels[10]; extern Costume costume[10]; HitStruct Person::BulletCollideWithPlayer(int who, XYZ start, XYZ end){ XYZ tempbulletloc[2]; XYZ collisionpoint; GLfloat M[16]; int collide; XYZ average; int howmany; float distancemax; HitStruct hitstruct; hitstruct.collision=0; //Make bounding sphere average=0; howmany=0; for(int j=0;jdistancemax){ distancemax=findDistancefast(average,skeleton.joints[j].position); } } distancemax=sqrt(distancemax); //Collide with player if(skeleton.free<1){ start=start-playercoords; end=end-playercoords; if(playerrotation)start=DoRotation(start,0,-playerrotation,0); if(playerrotation)end=DoRotation(end,0,-playerrotation,0); } tempbulletloc[0]=start; tempbulletloc[1]=end; if(sphere_line_intersection(tempbulletloc[0].x,tempbulletloc[0].y,tempbulletloc[0].z, tempbulletloc[1].x,tempbulletloc[1].y,tempbulletloc[1].z, average.x, average.y, average.z, distancemax)){ for(int j=0;jposition.x)/2), (-(skeleton.joints[j].position.y+skeleton.joints[j].parent->position.y)/2), (-(skeleton.joints[j].position.z+skeleton.joints[j].parent->position.z)/2)); glTranslatef(tempbulletloc[0].x,tempbulletloc[0].y,tempbulletloc[0].z); glGetFloatv(GL_MODELVIEW_MATRIX,M); tempbulletloc[0].x=M[12]; tempbulletloc[0].y=M[13]; tempbulletloc[0].z=M[14]; glPopMatrix(); glPushMatrix(); glLoadIdentity(); glScalef(1,1/skeleton.joints[j].length,1); glRotatef(skeleton.joints[j].rotate2-90,0,0,1); glRotatef(skeleton.joints[j].rotate1-90,0,1,0); glTranslatef( (-(skeleton.joints[j].position.x+skeleton.joints[j].parent->position.x)/2), (-(skeleton.joints[j].position.y+skeleton.joints[j].parent->position.y)/2), (-(skeleton.joints[j].position.z+skeleton.joints[j].parent->position.z)/2)); glTranslatef(tempbulletloc[1].x,tempbulletloc[1].y,tempbulletloc[1].z); glGetFloatv(GL_MODELVIEW_MATRIX,M); tempbulletloc[1].x=M[12]; tempbulletloc[1].y=M[13]; tempbulletloc[1].z=M[14]; glPopMatrix(); collide=skeletonmodels[skeleton.joints[j].modelnum].LineCheck(tempbulletloc[0],tempbulletloc[1],&collisionpoint); if(collide!=-1) { glPushMatrix(); glLoadIdentity(); glTranslatef( (skeleton.joints[j].position.x+skeleton.joints[j].parent->position.x)/2, (skeleton.joints[j].position.y+skeleton.joints[j].parent->position.y)/2, (skeleton.joints[j].position.z+skeleton.joints[j].parent->position.z)/2); glRotatef(-skeleton.joints[j].rotate1+90,0,1,0); glRotatef(-skeleton.joints[j].rotate2+90,0,0,1); glScalef(1,skeleton.joints[j].length,1); glTranslatef(collisionpoint.x,collisionpoint.y,collisionpoint.z); glGetFloatv(GL_MODELVIEW_MATRIX,M); collisionpoint.x=M[12]; collisionpoint.y=M[13]; collisionpoint.z=M[14]; glPopMatrix(); hitstruct.collision=1; hitstruct.hitlocation=collisionpoint; hitstruct.joint1=&skeleton.joints[j]; hitstruct.joint2=skeleton.joints[j].parent; } } } for(int j=0;jposition.x+skeleton.muscles[j].parent2->position.x)/2), (-(skeleton.muscles[j].parent1->position.y+skeleton.muscles[j].parent2->position.y)/2), (-(skeleton.muscles[j].parent1->position.z+skeleton.muscles[j].parent2->position.z)/2)); glTranslatef(tempbulletloc[0].x,tempbulletloc[0].y,tempbulletloc[0].z); glGetFloatv(GL_MODELVIEW_MATRIX,M); tempbulletloc[0].x=M[12]; tempbulletloc[0].y=M[13]; tempbulletloc[0].z=M[14]; glPopMatrix(); glPushMatrix(); glLoadIdentity(); glScalef(1,1/skeleton.muscles[j].length,1); glRotatef(skeleton.muscles[j].rotate3,0,1,0); glRotatef(skeleton.muscles[j].rotate2-90,0,0,1); glRotatef(skeleton.muscles[j].rotate1-90,0,1,0); glTranslatef( (-(skeleton.muscles[j].parent1->position.x+skeleton.muscles[j].parent2->position.x)/2), (-(skeleton.muscles[j].parent1->position.y+skeleton.muscles[j].parent2->position.y)/2), (-(skeleton.muscles[j].parent1->position.z+skeleton.muscles[j].parent2->position.z)/2)); glTranslatef(tempbulletloc[1].x,tempbulletloc[1].y,tempbulletloc[1].z); glGetFloatv(GL_MODELVIEW_MATRIX,M); tempbulletloc[1].x=M[12]; tempbulletloc[1].y=M[13]; tempbulletloc[1].z=M[14]; glPopMatrix(); collide=skeletonmodels[skeleton.muscles[j].parent1->modelnum].LineCheck(tempbulletloc[0],tempbulletloc[1],&collisionpoint); if(collide!=-1) { glPushMatrix(); glLoadIdentity(); glTranslatef( (skeleton.muscles[j].parent1->position.x+skeleton.muscles[j].parent2->position.x)/2, (skeleton.muscles[j].parent1->position.y+skeleton.muscles[j].parent2->position.y)/2, (skeleton.muscles[j].parent1->position.z+skeleton.muscles[j].parent2->position.z)/2); glRotatef(-skeleton.muscles[j].rotate1+90,0,1,0); glRotatef(-skeleton.muscles[j].rotate2+90,0,0,1); glRotatef(-skeleton.muscles[j].rotate3,0,1,0); glScalef(1,findDistance(skeleton.muscles[j].parent1->position,skeleton.muscles[j].parent2->position),1); glTranslatef(collisionpoint.x,collisionpoint.y,collisionpoint.z); glGetFloatv(GL_MODELVIEW_MATRIX,M); collisionpoint.x=M[12]; collisionpoint.y=M[13]; collisionpoint.z=M[14]; glPopMatrix(); hitstruct.collision=1; hitstruct.hitlocation=collisionpoint; hitstruct.joint1=skeleton.muscles[j].parent1; hitstruct.joint2=skeleton.muscles[j].parent2; } } } } if(skeleton.free<1){ if(playerrotation)hitstruct.hitlocation=DoRotation(hitstruct.hitlocation,0,playerrotation,0); hitstruct.hitlocation=hitstruct.hitlocation+playercoords; } return hitstruct; } extern float camerashake; extern int cycle; void Person::DoAnimations(int who) { if (target > 1 && !skeleton.free) { // Footstep sounds if (!slomo && !visions && (onground || abs(velocity.y) < 1) && (targetanimation == joganim || targetanimation == walkanim) && (targetframe == 0 || targetframe == 8) && who == 0) { auto soundsrc = (playercoords - camera.position) / soundscalefactor; ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z}; int whichsound = footstepsound + abs(Random()) % 5; alSourcefv(gSourceID[whichsound], AL_POSITION, gLoc); alSourcePlay(gSourceID[whichsound]); } if (targetanimation == zombieeatanim && targetframe == 3) { auto& joints = skeleton.joints; auto& jointlabels = skeleton.jointlabels; auto head_joint = joints[jointlabels[head]]; auto soundsrc = (DoRotation(head_joint.position, 0, playerrotation, 0) + playercoords - camera.position) / soundscalefactor; ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z}; alSourcefv(gSourceID[bodyhitsound], AL_POSITION, gLoc); alSourcePlay(gSourceID[bodyhitsound]); bleeding = 1; bleeddelay = 1; bjoint1 = &head_joint; bjoint2 = joints + jointlabels[neck]; } currentanimation = targetanimation; targetframe = currentframe + (backwardsanim ? -1 : 1); if (targetframe >= animation[currentanimation].numframes) targetframe = 0; else if (targetframe < 0) targetframe = animation[currentanimation].numframes - 1; target = 0; if ((currentanimation == getupfrontanim || currentanimation == getupbackanim) && targetframe == 0) targetanimation = idleanim; if (targetanimation == diveanim && currentanimation == diveanim && targetframe == 0) { targetanimation = getupfrontanim; auto& joints = skeleton.joints; auto& jointlabels = skeleton.jointlabels; auto head_joint = joints[jointlabels[head]]; auto soundsrc = (DoRotation(head_joint.position, 0, playerrotation, 0) + playercoords - camera.position) / soundscalefactor; ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z}; alSourcefv(gSourceID[bodywhacksound], AL_POSITION, gLoc); alSourcePlay(gSourceID[bodywhacksound]); } if (currentanimation == throwanim && targetframe == 0) targetanimation = idleanim; if (currentanimation == thrownanim && targetframe == 0) { skeleton.offset = 0; skeleton.free = 1; longdead = 1; for (auto& joint : skeleton.joints) { joint.position = playercoords + DoRotation(joint.position + joint.offset, 0, playerrotation, 0); joint.realoldposition = joint.position; joint.velocity = DoRotation(joint.velocity, 0, playerrotation, 0); } } } if(!skeleton.free){ if(currentanimation!=lyinganim){ if(animation[targetanimation].speed[currentframe]>animation[currentanimation].speed[currentframe]) target+=multiplier*animation[targetanimation].speed[currentframe]*speed; if(animation[targetanimation].speed[currentframe]<=animation[currentanimation].speed[currentframe]) target+=multiplier*animation[currentanimation].speed[currentframe]*speed; } if(currentanimation==lyinganim){ target+=multiplier*animation[targetanimation].speed[targetframe]*speed; } if(((currentanimation==crouchanim)&&(targetanimation!=crouchanim))||((currentanimation!=crouchanim)&&(targetanimation==crouchanim)))target+=multiplier*animation[crouchanim].speed[0]*2; if(currentanimation==idleanim&&targetanimation==idleanim)target-=multiplier*animation[idleanim].speed[0]/2; if(target>1)currentframe=targetframe; for(int i=0;i0||whichgun==grenade)&&whichgun!=nogun){ if(aiming&&targetanimation!=joganim){ if(aimamount<1)aimamount+=multiplier*4; if(aimamount>1)aimamount=1; } if(!aiming||targetanimation==joganim){ if(aimamount>0)aimamount-=multiplier*4; if(aimamount<0)aimamount=0; } if(grenphase==1){ if(grenamount<1)grenamount+=multiplier*4; if(grenamount>1)grenamount=1; } if(grenphase==0){ if(grenamount>0)grenamount-=multiplier*4; if(grenamount<0)grenamount=0; } rotatearound=skeleton.joints[skeleton.jointlabels[neck]].position; for(int i=0;i0){ oldpos=skeleton.joints[i].position; skeleton.joints[i].position=animation[grenadechargeanim].position[i][0]; if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position-=(animation[idleanim].position[skeleton.jointlabels[neck]][0]-skeleton.joints[skeleton.jointlabels[neck]].position); skeleton.joints[i].position=skeleton.joints[i].position*(grenamount)+oldpos*(1-grenamount); } if(thirdperson||who!=0)skeleton.joints[i].position+=facingdown*.4; if(currentanimation!=crouchanim)skeleton.joints[i].position-=facinghalf*recoil*.35; if(currentanimation==crouchanim)skeleton.joints[i].position-=facinghalf*recoil*.1; } } } //Whack if(attackframe>-1&&whichgun!=grenade){ for(int i=0;i0&&attackframe0)attacktarget+=multiplier*animation[riflehitanim].speed[attackframe-1]*2; if(attacktarget>1){ attacktarget=0; attackframe++; if(attackframe>animation[riflehitanim].numframes)attackframe=-1; } } //Throw grenade if(attackframe>-1&&whichgun==grenade&&ammo>0){ for(int i=0;i0&&attackframe0)attacktarget+=multiplier*animation[grenadethrowanim].speed[attackframe-1]*2; if(attacktarget>1){ attacktarget=0; attackframe++; if(attackframe>animation[grenadethrowanim].numframes){ attackframe=-1; } if(attackframe==animation[grenadethrowanim].numframes-1&&ammo>0){ ammo=-1; sprites.MakeSprite(grenadesprite, 1, 1, 1, 1, DoRotation(skeleton.joints[skeleton.jointlabels[righthand]].position,0,playerrotation,0)+playercoords, DoRotation(facing,0,playerrotation,0)*30+velocity, 1); sprites.MakeSprite(spoonsprite, 1, 1, 1, 1, DoRotation(skeleton.joints[skeleton.jointlabels[righthand]].position,0,playerrotation,0)+playercoords, DoRotation(facing,0,playerrotation,0)*10+velocity, 1); sprites.MakeSprite(pinsprite, 1, 1, 1, 1, DoRotation(skeleton.joints[skeleton.jointlabels[lefthand]].position,0,playerrotation,0)+playercoords, facing*.1+velocity, 1); XYZ soundsrc = (DoRotation(skeleton.joints[skeleton.jointlabels[righthand]].position, 0, playerrotation, 0) + playercoords - camera.position) / soundscalefactor; ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z}; alSourcefv(gSourceID[grenadethrowsound], AL_POSITION, gLoc); alSourcePlay(gSourceID[grenadethrowsound]); } } } rotatearound=skeleton.joints[skeleton.jointlabels[abdomen]].position; if(who==0) for(int i=0;i 0) { aiming = 0; reloading -= multiplier; } if(ammo < 0 && reloads[whichgun] > 0 && reloading <= 0) { ALint tempint; alGetSourcei(gSourceID[reloadsound], AL_SOURCE_STATE, &tempint); if (whichgun != grenade && tempint != AL_PLAYING) { auto soundsrc = (playercoords - camera.position) / soundscalefactor; ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z}; alSourcefv(gSourceID[reloadsound], AL_POSITION, gLoc); alSourcePlay(gSourceID[reloadsound]); } reloading = 3; aiming = 0; switch (whichgun) { case sniperrifle: ammo = 5; break; case shotgun: ammo = 6; break; case assaultrifle: ammo = 25; break; case handgun1: ammo = 12; break; case handgun2: ammo = 16; break; case grenade: ammo = 1; reloading = 1; break; } reloads[whichgun]--; } if (reloads[whichgun] == 0 && whichgun == grenade && ammo <= 0) whichgun = nogun; if (reloading < 0) { reloading = 0; aiming = 1; } } } } void Person::DoAnimationslite(int who) { if (skeleton.free) return; if (target > 1) { // Footstep sounds if (who == 0 && !visions && (onground || abs(velocity.y) < 1) && (targetanimation == joganim || targetanimation == walkanim) && (targetframe == 0 || targetframe == 8)) { auto soundsrc = (playercoords - camera.position) / soundscalefactor; ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z}; int whichsound = footstepsound + abs(Random()) % 5; alSourcefv(gSourceID[whichsound], AL_POSITION, gLoc); alSourcePlay(gSourceID[whichsound]); } if (targetanimation == zombieeatanim && targetframe == 3) { auto& joints = skeleton.joints; auto& jointlabels = skeleton.jointlabels; auto head_joint = joints[jointlabels[head]]; auto soundsrc = (DoRotation(head_joint.position, 0, playerrotation, 0) + playercoords - camera.position) / soundscalefactor; ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z}; alSourcefv(gSourceID[bodyhitsound], AL_POSITION, gLoc); alSourcePlay(gSourceID[bodyhitsound]); bleeding = 1; bleeddelay = 1; bjoint1 = &head_joint; bjoint2 = joints + jointlabels[neck]; } currentanimation = targetanimation; targetframe = currentframe + (backwardsanim ? -1 : 1); if (targetframe >= animation[currentanimation].numframes) targetframe = 0; else if (targetframe < 0) targetframe = animation[currentanimation].numframes - 1; target = 0; if ((currentanimation == getupfrontanim || currentanimation == getupbackanim) && targetframe == 0) targetanimation = idleanim; } if (currentanimation == lyinganim) target += speed * multiplier * animation[targetanimation].speed[targetframe]; else target += speed * multiplier * max(animation[currentanimation].speed[currentframe], animation[targetanimation].speed[currentframe]); if ((currentanimation == crouchanim) ^ (targetanimation == crouchanim)) target += *animation[crouchanim].speed * multiplier * 2; if (currentanimation == idleanim && targetanimation == idleanim) target -= *animation[idleanim].speed * multiplier / 2; if (target > 1) currentframe = targetframe; } void Person::DoStuff(int who){ int moveanim; if((targetanimation!=idleanim&&targetanimation!=crouchanim)||visions==1)playerlowrotation=playerrotation; if(targetanimation!=crouchanim&¤tanimation!=crouchanim){ if(playerrotation>playerlowrotation+50){playerlowrotation=playerrotation-50; targetanimation=walkanim; targetframe=0; target=0;} if(playerrotationplayerlowrotation+70){playerrotation=playerlowrotation+70;} if(playerrotationtemppoint2.x)gunrotate1=360-gunrotate1; tempforward=target-start; tempforward=DoRotation(tempforward,-90,0,0); tempforward=DoRotation(tempforward,0,gunrotate1-90,0); tempforward=DoRotation(tempforward,0,0,gunrotate2-90); tempforward.y=0; Normalise(&tempforward); gunrotate3=acos(0-tempforward.z)*rad2deg; if(0>tempforward.x)gunrotate3=360-gunrotate3; } float* determine_color(int model, int who, int whichcostume) { switch (model) { case 0: if (who != 0 || thirdperson) return costume[whichcostume].headcolor; break; case 1: if (who != 0 || thirdperson) return costume[whichcostume].chestcolor; break; case 2: return costume[whichcostume].abdomencolor; case 3: return costume[whichcostume].upperarmcolor; case 4: return costume[whichcostume].lowerarmcolor; case 5: return costume[whichcostume].handcolor; case 6: return costume[whichcostume].upperlegcolor; case 7: return costume[whichcostume].lowerlegcolor; case 8: return costume[whichcostume].footcolor; } return nullptr; } void draw_joint(Joint& joint, int who, int whichcostume) { if (!joint.hasparent || !joint.visible) return; glPushMatrix(); glTranslatef((joint.position.x + joint.parent->position.x) / 2, (joint.position.y + joint.parent->position.y) / 2, (joint.position.z + joint.parent->position.z) / 2); glRotatef(90 - joint.rotate1, 0, 1, 0); glRotatef(90 - joint.rotate2, 0, 0, 1); glRotatef(-joint.rotate3, 0, 1, 0); auto& model = joint.modelnum; if (auto color = determine_color(model, who, whichcostume)) skeletonmodels[model].draw(*color, color[1], color[2]); if (model == 0 && who == 0 && thirdperson) skeletonmodels[9].draw(); glPopMatrix(); } void draw_muscle(Muscle& mus, int who, int whichcostume) { if (!mus.visible) return; auto& pos1 = mus.parent1->position; auto& pos2 = mus.parent2->position; glPushMatrix(); glTranslatef((pos1.x + pos2.x) / 2, (pos1.y + pos2.y) / 2, (pos1.z + pos2.z) / 2); glRotatef(90 - mus.rotate1, 0, 1, 0); glRotatef(90 - mus.rotate2, 0, 0, 1); glRotatef(-mus.rotate3, 0, 1, 0); auto& model = mus.parent1->modelnum; if (auto color = determine_color(model, who, whichcostume)) skeletonmodels[model].draw(*color, color[1], color[2]); if (model == 0 && who == 0 && thirdperson) skeletonmodels[9].draw(); glPopMatrix(); } int Person::DrawSkeleton(int who) { auto& left_hand = skeleton.jointlabels[lefthand]; auto& left_wrist = skeleton.joints[left_hand].position; auto& right_hand = skeleton.jointlabels[righthand]; auto& right_wrist = skeleton.joints[right_hand].position; auto& head_pos = skeleton.joints[skeleton.jointlabels[head]].position; auto& neck_pos = skeleton.joints[skeleton.jointlabels[neck]].position; switch (whichgun) { case sniperrifle: FindRotationGun(right_wrist, left_wrist); glPushMatrix(); glTranslatef(right_wrist.x, right_wrist.y, right_wrist.z); glRotatef(90 - gunrotate1, 0, 1, 0); glRotatef(90 - gunrotate2, 0, 0, 1); glRotatef(-gunrotate3, 0, 1, 0); gunmodels[sniperriflemodel].draw(); glPopMatrix(); break; case shotgun: FindRotationGun(right_wrist, left_wrist); glPushMatrix(); glTranslatef(right_wrist.x, right_wrist.y, right_wrist.z); glRotatef(2, 1, 0, 0); glRotatef(90 + 1 - gunrotate1, 0, 1, 0); glRotatef(90 - gunrotate2, 0, 0, 1); glRotatef(-gunrotate3, 0, 1, 0); glTranslatef(0, -0.4, 0); gunmodels[shotgunmodel].draw(); glPopMatrix(); break; case assaultrifle: FindRotationGun(right_wrist, left_wrist); glPushMatrix(); glTranslatef(right_wrist.x, right_wrist.y, right_wrist.z); glRotatef(90 - gunrotate1, 0, 1, 0); glRotatef(90 - gunrotate2, 0, 0, 1); glRotatef(-gunrotate3, 0, 1, 0); gunmodels[assaultriflemodel].draw(); glPopMatrix(); break; case handgun1: case handgun2: if (who || thirdperson) FindRotationGun(right_wrist, head_pos * 0.35 + neck_pos * 0.65); else FindRotationGun(right_wrist, head_pos * 0.65 + neck_pos * 0.35); glPushMatrix(); glTranslatef(right_wrist.x, right_wrist.y, right_wrist.z); glRotatef(90 - 1.5 - gunrotate1, 0, 1, 0); glRotatef(90 - gunrotate2, 0, 0, 1); glRotatef(-gunrotate3, 0, 1, 0); glTranslatef(0, 0, 0.15); if (whichgun == handgun1) gunmodels[handgunbasemodel].draw(); else gunmodels[handgun2basemodel].draw(); glTranslatef(0, recoil * -0.3, 0); if (whichgun == handgun1) gunmodels[handgunslidemodel].draw(); else gunmodels[handgun2slidemodel].draw(); glPopMatrix(); break; case grenade: glPushMatrix(); glTranslatef(right_wrist.x, right_wrist.y, right_wrist.z); glRotatef(-90, 1, 0, 0); glTranslatef(0, 0, 0.05); if (reloading <= 0) { gunmodels[grenadebasemodel].draw(); if (grenphase == 0) gunmodels[grenadepinmodel].draw(); glTranslatef(0, 0, 0.005); gunmodels[grenadespoonmodel].draw(); } glPopMatrix(); glPushMatrix(); glTranslatef(left_wrist.x, left_wrist.y, left_wrist.z); glRotatef(-90, 1, 0, 0); glTranslatef(0, 0, -0.15); if (reloading <= 0 && grenphase == 1) gunmodels[grenadepinmodel].draw(); glPopMatrix(); break; case knife: auto& wrist = skeleton.joints[skeleton.jointlabels[righthand]]; glPushMatrix(); glTranslatef(wrist.position.x, wrist.position.y, wrist.position.z); glRotatef(90 - 1.5 - wrist.rotate1, 0, 1, 0); glRotatef(90 - wrist.rotate2, 0, 0, 1); glRotatef(-wrist.rotate3, 0, 1, 0); glTranslatef(0, -0.2, 0); gunmodels[knifemodel].draw(); glPopMatrix(); break; } if (litup) { GLfloat LightAmbient[] {0, 0, 0, 1.0f}; GLfloat LightDiffuse[] {1, 1, 1, 1.0f}; auto& hand = skeleton.jointlabels[lefthand]; XYZ lightpoint = skeleton.joints[hand].position; GLfloat LightPosition[] {lightpoint.x, lightpoint.y, lightpoint.z, 0}; glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); glEnable(GL_LIGHT1); litup = 0; } else { glDisable(GL_LIGHT1); } //Find forward vectors if (!who || skeleton.free || skeleton.offset || whichgun != nogun || currentanimation == lyinganim || ((currentanimation == getupfrontanim || currentanimation == getupbackanim) && targetanimation == idleanim)) { if (skeleton.free != 1 || longdead > 0) { if (skeleton.offset && skeleton.free < 1) { XYZ normal; skeleton.offset = 0; for (int i = 0; i < skeleton.num_joints; i++) { auto& joint = skeleton.joints[i]; joint.oldposition = joint.position; joint.position += joint.offset; if (findLengthfast(joint.offset) >= multiplier * multiplier * 25) { normal = joint.offset; Normalise(&normal); skeleton.offset = 1; joint.offset -= normal * multiplier * 5; } else { joint.offset=0; } } skeleton.DoConstraints(); } auto& fwdjoints = skeleton.forwardjoints; CrossProduct(skeleton.joints[fwdjoints[1]].position - skeleton.joints[fwdjoints[0]].position, skeleton.joints[fwdjoints[2]].position - skeleton.joints[fwdjoints[0]].position, &skeleton.forward); Normalise(&skeleton.forward); auto& lowfwd = skeleton.lowforwardjoints; CrossProduct(skeleton.joints[lowfwd[1]].position - skeleton.joints[lowfwd[0]].position, skeleton.joints[lowfwd[2]].position - skeleton.joints[lowfwd[0]].position, &skeleton.lowforward); Normalise(&skeleton.lowforward); // Special forwards auto specialfwd = skeleton.specialforward; *specialfwd++ = skeleton.forward; auto& right_shoulder = skeleton.jointlabels[rightshoulder]; auto& right_elbow = skeleton.jointlabels[rightelbow]; *specialfwd = skeleton.joints[right_elbow].position - skeleton.joints[right_shoulder].position / 2 - right_wrist / 2 + skeleton.forward * 0.2; Normalise(specialfwd++); auto& left_shoulder = skeleton.jointlabels[leftshoulder]; auto& left_elbow = skeleton.jointlabels[leftelbow]; *specialfwd = skeleton.joints[left_elbow].position - skeleton.joints[left_shoulder].position / 2 - left_wrist / 2 + skeleton.forward * 0.2; Normalise(specialfwd++); if(!who && aimamount > 0 && health == 100 && whichgun != nogun) { //Facing XYZ facing {0}; facing.z = 1; facing = DoRotation(facing, camera.rotation2, 0, 0); XYZ facingdown = DoRotation(facing, 90, 0, 0); skeleton.specialforward[1] *= 1 - aimamount; skeleton.specialforward[1] += facingdown * aimamount; skeleton.specialforward[2] *= 1 - aimamount; skeleton.specialforward[2] += facingdown * aimamount; } auto& right_hip = skeleton.jointlabels[righthip]; auto& right_ankle = skeleton.jointlabels[rightankle]; auto& right_knee = skeleton.jointlabels[rightknee]; *specialfwd = skeleton.joints[right_hip].position / 2 + skeleton.joints[right_ankle].position / 2 - skeleton.joints[right_knee].position + skeleton.lowforward * 0.2; Normalise(specialfwd++); auto& left_hip = skeleton.jointlabels[lefthip]; auto& left_ankle = skeleton.jointlabels[leftankle]; auto& left_knee = skeleton.jointlabels[leftknee]; *specialfwd = skeleton.joints[left_hip].position / 2 + skeleton.joints[left_ankle].position / 2 - skeleton.joints[left_knee].position + skeleton.lowforward * 0.2; Normalise(specialfwd++); for(int i = 0; i < skeleton.num_joints; i++) if (skeleton.joints[i].hasparent && skeleton.joints[i].visible) skeleton.FindRotationJoint(i); for(int i = 0; i < skeleton.num_muscles; i++) if (skeleton.muscles[i].visible) skeleton.FindRotationMuscle(i); } } for (int i = 0; i < skeleton.num_joints; i++) draw_joint(skeleton.joints[i], who, whichcostume); for (int i = 0; i < skeleton.num_muscles; i++) draw_muscle(skeleton.muscles[i], who, whichcostume); if (skeleton.offset && skeleton.free < 1) for (int i = 0; i < skeleton.num_joints; i++) { auto& joint = skeleton.joints[i]; joint.position = joint.oldposition; } glDisable(GL_LIGHT1); return 0; }