// 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 "Person.h" extern double 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(who==0&&slomo==0&&(targetanimation==joganim||targetanimation==walkanim)&&(targetframe==0||targetframe==8)&&visions==0&&(onground||abs(velocity.y)<1)){ float gLoc[3]; gLoc[0]=playercoords.x/soundscalefactor; gLoc[1]=playercoords.y/soundscalefactor; gLoc[2]=playercoords.z/soundscalefactor; int whichsound = footstepsound+abs(Random())%5; alSourcefv(gSourceID[whichsound], AL_POSITION, gLoc); alSourcePlay(gSourceID[whichsound]); } if(targetanimation==zombieeatanim&&(targetframe==3)){ float gLoc[3]; XYZ soundpoint=(DoRotation(skeleton.joints[skeleton.jointlabels[head]].position,0,playerrotation,0)+playercoords); gLoc[0]=soundpoint.x/soundscalefactor; gLoc[1]=soundpoint.y/soundscalefactor; gLoc[2]=soundpoint.z/soundscalefactor; alSourcefv(gSourceID[bodyhitsound], AL_POSITION, gLoc); alSourcePlay(gSourceID[bodyhitsound]); bleeding=1; bleeddelay=1; bjoint1=&skeleton.joints[skeleton.jointlabels[head]]; bjoint2=&skeleton.joints[skeleton.jointlabels[neck]]; } targetframe=currentframe; currentanimation=targetanimation; if(!backwardsanim){targetframe++; if(targetframe>animation[currentanimation].numframes-1)targetframe=0;} if(backwardsanim){targetframe--; if(targetframe<0)targetframe=animation[currentanimation].numframes-1;} target=0; if((currentanimation==getupfrontanim||currentanimation==getupbackanim)&&targetframe==0){ targetanimation=idleanim; } if(targetanimation==diveanim&¤tanimation==diveanim&&targetframe==0){ targetanimation=getupfrontanim; float gLoc[3]; XYZ soundpoint=(DoRotation(skeleton.joints[skeleton.jointlabels[head]].position,0,playerrotation,0)+playercoords); gLoc[0]=soundpoint.x/soundscalefactor; gLoc[1]=soundpoint.y/soundscalefactor; gLoc[2]=soundpoint.z/soundscalefactor; 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(int j=0;janimation[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 soundsource=DoRotation(skeleton.joints[skeleton.jointlabels[righthand]].position,0,playerrotation,0)+playercoords; float gLoc[3]; gLoc[0]=soundsource.x/soundscalefactor; gLoc[1]=soundsource.y/soundscalefactor; gLoc[2]=soundsource.z/soundscalefactor; alSourcefv(gSourceID[grenadethrowsound], AL_POSITION, gLoc); alSourcePlay(gSourceID[grenadethrowsound]); } } } rotatearound=skeleton.joints[skeleton.jointlabels[abdomen]].position; if(who==0) for(int i=0;i0){ aiming=0; reloading-=multiplier; } if(ammo<0&&reloads[whichgun]>0&&reloading<=0){ if(whichgun!=grenade){ float gLoc[3]; ALint tempint; gLoc[0]=playercoords.x/soundscalefactor; gLoc[1]=playercoords.y/soundscalefactor; gLoc[2]=playercoords.z/soundscalefactor; alGetSourcei(gSourceID[reloadsound], AL_SOURCE_STATE, &tempint); if (tempint != AL_PLAYING){ alSourcefv(gSourceID[reloadsound], AL_POSITION, gLoc); alSourcePlay(gSourceID[reloadsound]); } } reloading=3; aiming=0; if(whichgun==sniperrifle)ammo=5; if(whichgun==assaultrifle)ammo=25; if(whichgun==handgun1)ammo=12; if(whichgun==handgun2)ammo=16; if(whichgun==grenade){ammo=1; reloading=1;} if(whichgun==shotgun)ammo=6; 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(target>1&&!skeleton.free){ //Footstep sounds if(who==0&&(targetanimation==joganim||targetanimation==walkanim)&&(targetframe==0||targetframe==8)&&visions==0&&(onground||abs(velocity.y)<1)){ float gLoc[3]; gLoc[0]=playercoords.x/soundscalefactor; gLoc[1]=playercoords.y/soundscalefactor; gLoc[2]=playercoords.z/soundscalefactor; int whichsound = footstepsound+abs(Random())%5; alSourcefv(gSourceID[whichsound], AL_POSITION, gLoc); alSourcePlay(gSourceID[whichsound]); } if(targetanimation==zombieeatanim&&(targetframe==3)){ float gLoc[3]; XYZ soundpoint=(DoRotation(skeleton.joints[skeleton.jointlabels[head]].position,0,playerrotation,0)+playercoords); gLoc[0]=soundpoint.x/soundscalefactor; gLoc[1]=soundpoint.y/soundscalefactor; gLoc[2]=soundpoint.z/soundscalefactor; alSourcefv(gSourceID[bodyhitsound], AL_POSITION, gLoc); alSourcePlay(gSourceID[bodyhitsound]); bleeding=1; bleeddelay=1; bjoint1=&skeleton.joints[skeleton.jointlabels[head]]; bjoint2=&skeleton.joints[skeleton.jointlabels[neck]]; } targetframe=currentframe; currentanimation=targetanimation; if(!backwardsanim){targetframe++; if(targetframe>animation[currentanimation].numframes-1)targetframe=0;} if(backwardsanim){targetframe--; if(targetframe<0)targetframe=animation[currentanimation].numframes-1;} target=0; if((currentanimation==getupfrontanim||currentanimation==getupbackanim)&&targetframe==0){ targetanimation=idleanim; } } 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; } } 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 || thirdperson) return costume[whichcostume].headcolor; else if (!who && thirdperson) return nullptr; case 1: if (who || thirdperson) return costume[whichcostume].chestcolor; 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; default: 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[joint.modelnum].draw(*color, color[1], color[2]); else 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]); else 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; }