Lots of micro-optimizations and depth fixes for emscripten.

sigonasr2 5 months ago
parent 14296e2e63
commit 599114ca02
  1. 3
      src/Checkpoint.cpp
  2. 3
      src/FloatingText.cpp
  3. 35
      src/Hamster.cpp
  4. 2
      src/Hamster.h
  5. 47
      src/HamsterGame.cpp
  6. 29
      src/HamsterJet.cpp
  7. 6
      src/HamsterJet.h
  8. 291
      src/olcPGEX_Graphics3D.h
  9. 38
      src/olcPGEX_Viewport.h
  10. 24
      src/olcPixelGameEngine.h

@ -72,9 +72,12 @@ void Checkpoint::DrawCheckpoints(TransformedView&tv){
const Animate2D::Frame&frame{checkpoint.animation.GetFrame(checkpoint.internal_animState)}; const Animate2D::Frame&frame{checkpoint.animation.GetFrame(checkpoint.internal_animState)};
if(checkpoint.animation.GetState(checkpoint.internal_animState)!=AnimationState::DEFAULT){ if(checkpoint.animation.GetState(checkpoint.internal_animState)!=AnimationState::DEFAULT){
HamsterGame::Game().SetDecalMode(DecalMode::ADDITIVE); HamsterGame::Game().SetDecalMode(DecalMode::ADDITIVE);
HamsterGame::Game().SetZ(0.007f);
tv.DrawPartialRotatedDecal(checkpoint.pos,frame.GetSourceImage()->Decal(),0.f,frame.GetSourceRect().size/2,frame.GetSourceRect().pos,frame.GetSourceRect().size,{1.1f,1.1f}); tv.DrawPartialRotatedDecal(checkpoint.pos,frame.GetSourceImage()->Decal(),0.f,frame.GetSourceRect().size/2,frame.GetSourceRect().pos,frame.GetSourceRect().size,{1.1f,1.1f});
HamsterGame::Game().SetZ(0.009f);
HamsterGame::Game().SetDecalMode(DecalMode::NORMAL); HamsterGame::Game().SetDecalMode(DecalMode::NORMAL);
} }
HamsterGame::Game().SetZ(0.009f);
tv.DrawPartialRotatedDecal(checkpoint.pos,frame.GetSourceImage()->Decal(),0.f,frame.GetSourceRect().size/2,frame.GetSourceRect().pos,frame.GetSourceRect().size); tv.DrawPartialRotatedDecal(checkpoint.pos,frame.GetSourceImage()->Decal(),0.f,frame.GetSourceRect().size/2,frame.GetSourceRect().pos,frame.GetSourceRect().size);
geom2d::line<float>playerToCheckpointLine{geom2d::line<float>(Hamster::GetPlayer().GetPos(),checkpoint.pos)}; geom2d::line<float>playerToCheckpointLine{geom2d::line<float>(Hamster::GetPlayer().GetPos(),checkpoint.pos)};

@ -73,12 +73,13 @@ void FloatingText::Draw(TransformedView&tv){
uint8_t alpha{uint8_t(util::lerp(0U,255U,lifetime/4.f))}; uint8_t alpha{uint8_t(util::lerp(0U,255U,lifetime/4.f))};
HamsterGame::Game().SetZ(0.014f);
for(int y:std::ranges::iota_view(-1,2)){ for(int y:std::ranges::iota_view(-1,2)){
for(int x:std::ranges::iota_view(-1,2)){ for(int x:std::ranges::iota_view(-1,2)){
tv.DrawRotatedStringDecal(pos+vi2d{x,y},text,0.f,strSize/2,{0,0,0,alpha},scale); tv.DrawRotatedStringDecal(pos+vi2d{x,y},text,0.f,strSize/2,{0,0,0,alpha},scale);
} }
} }
HamsterGame::Game().SetZ(0.01f); HamsterGame::Game().SetZ(0.015f);
tv.DrawRotatedStringDecal(pos,text,0.f,strSize/2,{currentCol.r,currentCol.g,currentCol.b,uint8_t(currentCol.a*(alpha/255.f))},scale); tv.DrawRotatedStringDecal(pos,text,0.f,strSize/2,{currentCol.r,currentCol.g,currentCol.b,uint8_t(currentCol.a*(alpha/255.f))},scale);
HamsterGame::Game().SetZ(0.f); HamsterGame::Game().SetZ(0.f);
} }

@ -67,10 +67,18 @@ void Hamster::UpdateHamsters(const float fElapsedTime){
h.HandleCollision(); h.HandleCollision();
switch(h.state){ switch(h.state){
case NORMAL:{ case NORMAL:{
if(h.bumpTimer<=0.f&&!h.CollectedAllCheckpoints()){ if(h.CanMove()){
if(h.IsPlayerControlled){ if(h.IsPlayerControlled){
h.HandlePlayerControls(); h.HandlePlayerControls();
}else{ }else{
if(!h.hamsterJet.has_value()){
h.ObtainPowerup(Powerup::JET);
Powerup tempJetPowerup{{},Powerup::JET};
tempJetPowerup.OnPowerupObtain(h);
h.SetState(FLYING);
h.lastSafeLocation.reset();
h.hamsterJet.emplace(h);
}
//TODO: NPC controls. //TODO: NPC controls.
} }
} }
@ -181,17 +189,17 @@ void Hamster::DrawHamsters(TransformedView&tv){
yHopAmt=-abs(sin(geom2d::pi*(animCycle/0.35f)))*12.f; yHopAmt=-abs(sin(geom2d::pi*(animCycle/0.35f)))*12.f;
} }
if(h.hamsterJet.has_value())h.hamsterJet.value().Draw(); if(h.hamsterJet.has_value())h.hamsterJet.value().Draw();
HamsterGame::Game().SetZ(h.z); HamsterGame::Game().SetZ(h.z+0.02f);
tv.DrawRotatedDecal(h.pos+vf2d{0.f,h.drawingOffsetY},HamsterGame::GetGFX("shadow.png").Decal(),0.f,HamsterGame::GetGFX("shadow.png").Sprite()->Size()/2); tv.DrawRotatedDecal(h.pos+vf2d{0.f,h.drawingOffsetY},HamsterGame::GetGFX("shadow.png").Decal(),0.f,HamsterGame::GetGFX("shadow.png").Sprite()->Size()/2);
HamsterGame::Game().SetZ(h.z+0.005f); HamsterGame::Game().SetZ(h.z+0.025f);
tv.DrawPartialRotatedDecal(h.pos+vf2d{0.f,h.drawingOffsetY+yHopAmt},img.GetSourceImage()->Decal(),0.f,img.GetSourceRect().size/2,img.GetSourceRect().pos,img.GetSourceRect().size,vf2d{1.f,1.f}*h.imgScale*vf2d{facingXScale,1.f},PixelLerp(h.shrinkEffectColor,WHITE,h.imgScale)); tv.DrawPartialRotatedDecal(h.pos+vf2d{0.f,h.drawingOffsetY+yHopAmt},img.GetSourceImage()->Decal(),0.f,img.GetSourceRect().size/2,img.GetSourceRect().pos,img.GetSourceRect().size,vf2d{1.f,1.f}*h.imgScale*vf2d{facingXScale,1.f},PixelLerp(h.shrinkEffectColor,WHITE,h.imgScale));
HamsterGame::Game().SetZ(h.z); HamsterGame::Game().SetZ(0.f);
}else{ }else{
if(h.hamsterJet.has_value())h.hamsterJet.value().Draw(); if(h.hamsterJet.has_value())h.hamsterJet.value().Draw();
HamsterGame::Game().SetZ(h.z); HamsterGame::Game().SetZ(h.z+0.02f);
if(h.HasPowerup(Powerup::WHEEL))tv.DrawPartialRotatedDecal(h.pos+vf2d{0.f,h.drawingOffsetY},wheelBottomImg.GetSourceImage()->Decal(),h.rot,wheelBottomImg.GetSourceRect().size/2,wheelBottomImg.GetSourceRect().pos,wheelBottomImg.GetSourceRect().size,vf2d{1.f,1.f}*h.imgScale,PixelLerp(h.shrinkEffectColor,WHITE,h.imgScale)); if(h.HasPowerup(Powerup::WHEEL))tv.DrawPartialRotatedDecal(h.pos+vf2d{0.f,h.drawingOffsetY},wheelBottomImg.GetSourceImage()->Decal(),h.rot,wheelBottomImg.GetSourceRect().size/2,wheelBottomImg.GetSourceRect().pos,wheelBottomImg.GetSourceRect().size,vf2d{1.f,1.f}*h.imgScale,PixelLerp(h.shrinkEffectColor,WHITE,h.imgScale));
tv.DrawPartialRotatedDecal(h.pos+vf2d{0.f,h.drawingOffsetY},img.GetSourceImage()->Decal(),h.rot,img.GetSourceRect().size/2,img.GetSourceRect().pos,img.GetSourceRect().size,vf2d{1.f,1.f}*h.imgScale,PixelLerp(h.shrinkEffectColor,WHITE,h.imgScale)); tv.DrawPartialRotatedDecal(h.pos+vf2d{0.f,h.drawingOffsetY},img.GetSourceImage()->Decal(),h.rot,img.GetSourceRect().size/2,img.GetSourceRect().pos,img.GetSourceRect().size,vf2d{1.f,1.f}*h.imgScale,PixelLerp(h.shrinkEffectColor,WHITE,h.imgScale));
HamsterGame::Game().SetZ(h.z+0.01f); HamsterGame::Game().SetZ(h.z+0.025f);
if(h.HasPowerup(Powerup::WHEEL))tv.DrawPartialRotatedDecal(h.pos+vf2d{0.f,h.drawingOffsetY},wheelTopImg.GetSourceImage()->Decal(),h.rot,wheelTopImg.GetSourceRect().size/2,wheelTopImg.GetSourceRect().pos,wheelTopImg.GetSourceRect().size,vf2d{1.f,1.f}*h.imgScale,PixelLerp(h.shrinkEffectColor,{255,255,255,192},h.imgScale)); if(h.HasPowerup(Powerup::WHEEL))tv.DrawPartialRotatedDecal(h.pos+vf2d{0.f,h.drawingOffsetY},wheelTopImg.GetSourceImage()->Decal(),h.rot,wheelTopImg.GetSourceRect().size/2,wheelTopImg.GetSourceRect().pos,wheelTopImg.GetSourceRect().size,vf2d{1.f,1.f}*h.imgScale,PixelLerp(h.shrinkEffectColor,{255,255,255,192},h.imgScale));
HamsterGame::Game().SetZ(0.f); HamsterGame::Game().SetZ(0.f);
} }
@ -363,7 +371,7 @@ const float Hamster::GetRadius()const{
} }
const Terrain::TerrainType Hamster::GetTerrainStandingOn()const{ const Terrain::TerrainType Hamster::GetTerrainStandingOn()const{
if(state==FLYING)return Terrain::ROCK; if(FlyingInTheAir())return Terrain::ROCK;
return HamsterGame::Game().GetTerrainTypeAtPos(GetPos()); return HamsterGame::Game().GetTerrainTypeAtPos(GetPos());
} }
@ -381,7 +389,7 @@ const float Hamster::GetTimeToMaxSpeed()const{
else if(!HasPowerup(Powerup::SWAMP)&&GetTerrainStandingOn()==Terrain::SWAMP)finalTimeToMaxSpd*=1.25; else if(!HasPowerup(Powerup::SWAMP)&&GetTerrainStandingOn()==Terrain::SWAMP)finalTimeToMaxSpd*=1.25;
if(hamsterJet.has_value()){ if(hamsterJet.has_value()){
if(hamsterJet.value().GetState()==HamsterJet::LANDING)finalTimeToMaxSpd*=2.f; if(hamsterJet.value().GetState()==HamsterJet::LANDING)finalTimeToMaxSpd*=2.f;
else if(state==FLYING)finalTimeToMaxSpd*=3.f; else if(FlyingInTheAir())finalTimeToMaxSpd*=3.f;
} }
return finalTimeToMaxSpd; return finalTimeToMaxSpd;
} }
@ -417,7 +425,7 @@ const float Hamster::GetMaxSpeed()const{
if(HasPowerup(Powerup::WHEEL))finalMaxSpd*=1.5f; if(HasPowerup(Powerup::WHEEL))finalMaxSpd*=1.5f;
if(hamsterJet.has_value()){ if(hamsterJet.has_value()){
if(hamsterJet.value().GetState()==HamsterJet::LANDING)finalMaxSpd*=1.5f; if(hamsterJet.value().GetState()==HamsterJet::LANDING)finalMaxSpd*=1.5f;
else if(state==FLYING)finalMaxSpd*=8.f; else if(FlyingInTheAir())finalMaxSpd*=8.f;
} }
return finalMaxSpd; return finalMaxSpd;
} }
@ -427,7 +435,7 @@ const float Hamster::GetFriction()const{
else if(!HasPowerup(Powerup::SWAMP)&&GetTerrainStandingOn()==Terrain::SWAMP)finalFriction*=0.6f; else if(!HasPowerup(Powerup::SWAMP)&&GetTerrainStandingOn()==Terrain::SWAMP)finalFriction*=0.6f;
if(hamsterJet.has_value()){ if(hamsterJet.has_value()){
if(hamsterJet.value().GetState()==HamsterJet::LANDING)finalFriction*=1.5f; if(hamsterJet.value().GetState()==HamsterJet::LANDING)finalFriction*=1.5f;
else if(state==FLYING)finalFriction*=8.f; else if(FlyingInTheAir())finalFriction*=8.f;
} }
return finalFriction; return finalFriction;
} }
@ -589,3 +597,10 @@ const Hamster::HamsterState&Hamster::GetState()const{
const bool Hamster::BurnedOrDrowned()const{ const bool Hamster::BurnedOrDrowned()const{
return GetState()==WAIT; return GetState()==WAIT;
} }
const bool Hamster::CanMove()const{
return bumpTimer<=0.f&&!CollectedAllCheckpoints();
}
const bool Hamster::FlyingInTheAir()const{
return GetState()==FLYING&&hamsterJet.value().GetZ()>0.5f&&GetZ()>0.5f;
}

@ -162,4 +162,6 @@ public:
static const std::vector<Hamster>&GetHamsters(); static const std::vector<Hamster>&GetHamsters();
const HamsterState&GetState()const; const HamsterState&GetState()const;
const bool BurnedOrDrowned()const; const bool BurnedOrDrowned()const;
const bool CanMove()const;
const bool FlyingInTheAir()const;
}; };

@ -32,7 +32,7 @@ bool HamsterGame::OnUserCreate(){
renderer.SetProjection(90.0f, (float)SCREEN_FRAME.size.x/(float)SCREEN_FRAME.size.y, 0.1f, 1000.0f, 0, SCREEN_FRAME.pos.y, 512, SCREEN_FRAME.size.y); renderer.SetProjection(90.0f, (float)SCREEN_FRAME.size.x/(float)SCREEN_FRAME.size.y, 0.1f, 1000.0f, 0, SCREEN_FRAME.pos.y, 512, SCREEN_FRAME.size.y);
std::vector<vf2d>radarCircle; std::vector<vf2d>radarCircle;
for(int i=360;i>=0;i-=4){ for(int i=360;i>=0;i-=20){
float angle=util::degToRad(float(i))-geom2d::pi/2; float angle=util::degToRad(float(i))-geom2d::pi/2;
if(i==360){radarCircle.push_back(vf2d{cos(angle),sin(angle)}*43+vf2d{43,44});} if(i==360){radarCircle.push_back(vf2d{cos(angle),sin(angle)}*43+vf2d{43,44});}
radarCircle.push_back(vf2d{cos(angle),sin(angle)}*43+vf2d{43,44}); radarCircle.push_back(vf2d{cos(angle),sin(angle)}*43+vf2d{43,44});
@ -184,11 +184,12 @@ void HamsterGame::UpdateGame(const float fElapsedTime){
} }
void HamsterGame::DrawGame(){ void HamsterGame::DrawGame(){
SetZ(-0.001f); SetZ(-0.01f);
tv.DrawPartialDecal({-3200,-3200},currentMap.value().GetData().GetMapData().MapSize*16+vf2d{6400,6400},animatedWaterTile.Decal(),{0,0},currentMap.value().GetData().GetMapData().MapSize*16+vf2d{6400,6400}); tv.DrawPartialDecal({-3200,-3200},currentMap.value().GetData().GetMapData().MapSize*16+vf2d{6400,6400},animatedWaterTile.Decal(),{0,0},currentMap.value().GetData().GetMapData().MapSize*16+vf2d{6400,6400});
SetZ(0.f); SetZ(-0.0005f);
DrawLevelTiles(); DrawLevelTiles();
Checkpoint::DrawCheckpoints(tv); Checkpoint::DrawCheckpoints(tv);
SetZ(0.01f);
Powerup::DrawPowerups(tv); Powerup::DrawPowerups(tv);
Hamster::DrawHamsters(tv); Hamster::DrawHamsters(tv);
SetZ(3.f); SetZ(3.f);
@ -322,11 +323,9 @@ bool HamsterGame::OnUserUpdate(float fElapsedTime){
} }
const Renderable&HamsterGame::GetGFX(const std::string&img){ const Renderable&HamsterGame::GetGFX(const std::string&img){
if(!GFX.count(img))throw std::runtime_error{std::format("Image {} does not exist!",img)};
return GFX[img]; return GFX[img];
} }
const Animate2D::Animation<AnimationState::AnimationState>&HamsterGame::GetAnimations(const std::string&img){ const Animate2D::Animation<AnimationState::AnimationState>&HamsterGame::GetAnimations(const std::string&img){
if(!ANIMATIONS.count(img))throw std::runtime_error{std::format("Animations for {} does not exist!",img)};
return ANIMATIONS[img]; return ANIMATIONS[img];
} }
@ -433,25 +432,38 @@ void HamsterGame::Apply3DTransform(std::vector<DecalInstance>&decals){
renderer.SetTransform(matWorld); renderer.SetTransform(matWorld);
float zIncrementer{0.f};
for(DecalInstance&decal:oldDecals){ for(DecalInstance&decal:oldDecals){
SetDecalMode(decal.mode); SetDecalMode(decal.mode);
if(decal.transform==GFX3DTransform::NO_TRANSFORM)foregroundDecals.emplace_back(decal); if(decal.transform==GFX3DTransform::NO_TRANSFORM){
foregroundDecals.emplace_back(decal);
}
else else
if(decal.points==3){ if(decal.points==3){
GFX3D::triangle tri{{{decal.pos[0].x,decal.pos[0].y,decal.z[0],1.f},{decal.pos[1].x,decal.pos[1].y,decal.z[1],1.f},{decal.pos[2].x,decal.pos[2].y,decal.z[2],1.f}},{{decal.uv[0].x,decal.uv[0].y,0.f},{decal.uv[1].x,decal.uv[1].y,0.f},{decal.uv[2].x,decal.uv[2].y,0.f}},{decal.tint[0],decal.tint[1],decal.tint[2]}}; GFX3D::triangle tri{{{decal.pos[0].x,decal.pos[0].y,decal.z[0],1.f},{decal.pos[1].x,decal.pos[1].y,decal.z[1],1.f},{decal.pos[2].x,decal.pos[2].y,decal.z[2],1.f}},{{decal.uv[0].x,decal.uv[0].y,0.f},{decal.uv[1].x,decal.uv[1].y,0.f},{decal.uv[2].x,decal.uv[2].y,0.f}},{decal.tint[0],decal.tint[1],decal.tint[2]}};
tri.p[0].z+=zIncrementer;
tri.p[1].z+=zIncrementer;
tri.p[2].z+=zIncrementer;
renderer.Render({tri},decal.decal,GFX3D::RENDER_TEXTURED|GFX3D::RENDER_DEPTH); renderer.Render({tri},decal.decal,GFX3D::RENDER_TEXTURED|GFX3D::RENDER_DEPTH);
if(decal.z[0]>0.1f||decal.z[1]>0.1f||decal.z[2]>0.1f){ if(decal.z[0]>0.1f||decal.z[1]>0.1f||decal.z[2]>0.1f){
tri.col[0]=tri.col[1]=tri.col[2]={0,0,0,uint8_t(util::lerp(0,160,(1/std::pow(decal.z[0]/10.f+1,4))))}; tri.col[0]=tri.col[1]=tri.col[2]={0,0,0,uint8_t(util::lerp(0,160,(1/std::pow(decal.z[0]/10.f+1,4))))};
tri.p[0].z=tri.p[1].z=tri.p[2].z=0.1f; tri.p[0].z=tri.p[1].z=tri.p[2].z=0.1f+zIncrementer;
renderer.Render({tri},decal.decal,GFX3D::RENDER_TEXTURED|GFX3D::RENDER_DEPTH); renderer.Render({tri},decal.decal,GFX3D::RENDER_TEXTURED|GFX3D::RENDER_DEPTH);
} }
}else if(decal.points==4){ }else if(decal.points==4){
GFX3D::triangle tri{{{decal.pos[0].x,decal.pos[0].y,decal.z[0],1.f},{decal.pos[1].x,decal.pos[1].y,decal.z[1],1.f},{decal.pos[2].x,decal.pos[2].y,decal.z[2],1.f}},{{decal.uv[0].x,decal.uv[0].y,0.f},{decal.uv[1].x,decal.uv[1].y,0.f},{decal.uv[2].x,decal.uv[2].y,0.f}},{decal.tint[0],decal.tint[1],decal.tint[2]}}; GFX3D::triangle tri{{{decal.pos[0].x,decal.pos[0].y,decal.z[0],1.f},{decal.pos[1].x,decal.pos[1].y,decal.z[1],1.f},{decal.pos[2].x,decal.pos[2].y,decal.z[2],1.f}},{{decal.uv[0].x,decal.uv[0].y,0.f},{decal.uv[1].x,decal.uv[1].y,0.f},{decal.uv[2].x,decal.uv[2].y,0.f}},{decal.tint[0],decal.tint[1],decal.tint[2]}};
GFX3D::triangle tri2{{{decal.pos[0].x,decal.pos[0].y,decal.z[0],1.f},{decal.pos[2].x,decal.pos[2].y,decal.z[2],1.f},{decal.pos[3].x,decal.pos[3].y,decal.z[3],1.f}},{{decal.uv[0].x,decal.uv[0].y,0.f},{decal.uv[2].x,decal.uv[2].y,0.f},{decal.uv[3].x,decal.uv[3].y,0.f}},{decal.tint[0],decal.tint[2],decal.tint[3]}}; GFX3D::triangle tri2{{{decal.pos[0].x,decal.pos[0].y,decal.z[0],1.f},{decal.pos[2].x,decal.pos[2].y,decal.z[2],1.f},{decal.pos[3].x,decal.pos[3].y,decal.z[3],1.f}},{{decal.uv[0].x,decal.uv[0].y,0.f},{decal.uv[2].x,decal.uv[2].y,0.f},{decal.uv[3].x,decal.uv[3].y,0.f}},{decal.tint[0],decal.tint[2],decal.tint[3]}};
tri.p[0].z+=zIncrementer;
tri.p[1].z+=zIncrementer;
tri.p[2].z+=zIncrementer;
tri2.p[0].z+=zIncrementer;
tri2.p[1].z+=zIncrementer;
tri2.p[2].z+=zIncrementer;
renderer.Render({tri,tri2},decal.decal,GFX3D::RENDER_TEXTURED|GFX3D::RENDER_DEPTH); renderer.Render({tri,tri2},decal.decal,GFX3D::RENDER_TEXTURED|GFX3D::RENDER_DEPTH);
if(decal.decal!=GetGFX("dot.png").Decal()&&(decal.z[0]>0.1f||decal.z[1]>0.1f||decal.z[2]>0.1f||decal.z[3]>0.1f)){ if(decal.decal!=GetGFX("dot.png").Decal()&&(decal.z[0]>0.1f||decal.z[1]>0.1f||decal.z[2]>0.1f||decal.z[3]>0.1f)){
tri.col[0]=tri.col[1]=tri.col[2]=tri2.col[0]=tri2.col[1]=tri2.col[2]={0,0,0,uint8_t(util::lerp(0,160,(1/std::pow(decal.z[0]/10.f+1,4))))}; tri.col[0]=tri.col[1]=tri.col[2]=tri2.col[0]=tri2.col[1]=tri2.col[2]={0,0,0,uint8_t(util::lerp(0,160,(1/std::pow(decal.z[0]/10.f+1,4))))};
tri.p[0].z=tri.p[1].z=tri.p[2].z=tri2.p[0].z=tri2.p[1].z=tri2.p[2].z=0.1f; tri.p[0].z=tri.p[1].z=tri.p[2].z=tri2.p[0].z=tri2.p[1].z=tri2.p[2].z=0.1f+zIncrementer;
renderer.Render({tri,tri2},decal.decal,GFX3D::RENDER_TEXTURED|GFX3D::RENDER_DEPTH); renderer.Render({tri,tri2},decal.decal,GFX3D::RENDER_TEXTURED|GFX3D::RENDER_DEPTH);
} }
}else{ }else{
@ -462,10 +474,13 @@ void HamsterGame::Apply3DTransform(std::vector<DecalInstance>&decals){
if(decal.points%3!=0)throw std::runtime_error{std::format("WARNING! Number of decal structure points is not a multiple of 3! Points provided: {}. THIS SHOULD NOT BE HAPPENING!",decal.points)}; if(decal.points%3!=0)throw std::runtime_error{std::format("WARNING! Number of decal structure points is not a multiple of 3! Points provided: {}. THIS SHOULD NOT BE HAPPENING!",decal.points)};
for(int i{0};i<decal.points;i+=3){ for(int i{0};i<decal.points;i+=3){
GFX3D::triangle tri{{{decal.pos[i+0].x,decal.pos[i+0].y,decal.z[i+0],1.f},{decal.pos[i+1].x,decal.pos[i+1].y,decal.z[i+1],1.f},{decal.pos[i+2].x,decal.pos[i+2].y,decal.z[i+2],1.f}},{{decal.uv[i+0].x,decal.uv[i+0].y,0.f},{decal.uv[i+1].x,decal.uv[i+1].y,0.f},{decal.uv[i+2].x,decal.uv[i+2].y,0.f}},{decal.tint[i+0],decal.tint[i+1],decal.tint[i+2]}}; GFX3D::triangle tri{{{decal.pos[i+0].x,decal.pos[i+0].y,decal.z[i+0],1.f},{decal.pos[i+1].x,decal.pos[i+1].y,decal.z[i+1],1.f},{decal.pos[i+2].x,decal.pos[i+2].y,decal.z[i+2],1.f}},{{decal.uv[i+0].x,decal.uv[i+0].y,0.f},{decal.uv[i+1].x,decal.uv[i+1].y,0.f},{decal.uv[i+2].x,decal.uv[i+2].y,0.f}},{decal.tint[i+0],decal.tint[i+1],decal.tint[i+2]}};
tri.p[0].z+=zIncrementer;
tri.p[1].z+=zIncrementer;
tri.p[2].z+=zIncrementer;
tris.emplace_back(tri); tris.emplace_back(tri);
if(decal.z[i+0]>0||decal.z[i+1]>0||decal.z[i+2]>0){ if(decal.z[i+0]>0.1f||decal.z[i+1]>0.1f||decal.z[i+2]>0.1f){
tri.col[0]=tri.col[1]=tri.col[2]={0,0,0,uint8_t(util::lerp(0,160,(1/std::pow(decal.z[0]/10.f+1,4))))}; tri.col[0]=tri.col[1]=tri.col[2]={0,0,0,uint8_t(util::lerp(0,160,(1/std::pow(decal.z[0]/10.f+1,4))))};
tri.p[0].z=tri.p[1].z=tri.p[2].z=0.1f; tri.p[0].z=tri.p[1].z=tri.p[2].z=0.1f+zIncrementer;
shadowTris.emplace_back(tri); shadowTris.emplace_back(tri);
} }
} }
@ -475,6 +490,7 @@ void HamsterGame::Apply3DTransform(std::vector<DecalInstance>&decals){
} }
} }
SetDecalMode(DecalMode::NORMAL); SetDecalMode(DecalMode::NORMAL);
zIncrementer+=0.000001f;
} }
std::sort(decals.begin(),decals.end(),[](const DecalInstance&d1,const DecalInstance&d2){return d1.z[0]>d2.z[0];}); std::sort(decals.begin(),decals.end(),[](const DecalInstance&d1,const DecalInstance&d2){return d1.z[0]>d2.z[0];});
@ -533,22 +549,27 @@ void HamsterGame::DrawRadar(){
{HAMSTER,{{16.f*9,0.f},{16.f,16.f}}}, {HAMSTER,{{16.f*9,0.f},{16.f,16.f}}},
}; };
const auto DeferRenderingBasedOnPosition=[this,&icon](const vf2d&pos,const IconType powerupIcon,const uint8_t iconAlpha){
if(geom2d::intersects(geom2d::circle<float>{{43.f+5.f,44.f+8.f},43},geom2d::rect<float>{pos-vf2d{16.f,16.f},{32.f,32.f}}).size()>0)radar.DrawPartialRotatedDecal(pos,GetGFX("radaricons.png").Decal(),0.f,{8.f,8.f},icon.at(powerupIcon).pos,icon.at(powerupIcon).size,{1.f,1.f},{255,255,255,iconAlpha});
else if(geom2d::contains(geom2d::circle<float>{{43.f+5.f,44.f+8.f},43},geom2d::rect<float>{pos-vf2d{8.f,8.f},{16.f,16.f}}))DrawPartialRotatedDecal(pos+vf2d{5.f,8.f},GetGFX("radaricons.png").Decal(),0.f,{8.f,8.f},icon.at(powerupIcon).pos,icon.at(powerupIcon).size,{1.f,1.f},{255,255,255,iconAlpha});
};
for(const Powerup&powerup:Powerup::GetPowerups()){ for(const Powerup&powerup:Powerup::GetPowerups()){
IconType powerupIcon{IconType(int(powerup.GetType())+1)}; IconType powerupIcon{IconType(int(powerup.GetType())+1)};
uint8_t iconAlpha{255U}; uint8_t iconAlpha{255U};
if(Hamster::GetPlayer().HasPowerup(powerup.GetType()))iconAlpha=64U; if(Hamster::GetPlayer().HasPowerup(powerup.GetType()))iconAlpha=64U;
radar.DrawPartialRotatedDecal(WorldToRadar(powerup.GetPos()),GetGFX("radaricons.png").Decal(),0.f,{8.f,8.f},icon.at(powerupIcon).pos,icon.at(powerupIcon).size,{1.f,1.f},{255,255,255,iconAlpha}); DeferRenderingBasedOnPosition(WorldToRadar(powerup.GetPos()),powerupIcon,iconAlpha);
} }
for(const Checkpoint&cp:Checkpoint::GetCheckpoints()){ for(const Checkpoint&cp:Checkpoint::GetCheckpoints()){
uint8_t iconAlpha{255U}; uint8_t iconAlpha{255U};
if(Hamster::GetPlayer().HasCollectedCheckpoint(cp))iconAlpha=64U; if(Hamster::GetPlayer().HasCollectedCheckpoint(cp))iconAlpha=64U;
radar.DrawPartialRotatedDecal(WorldToRadar(cp.GetPos()),GetGFX("radaricons.png").Decal(),0.f,{8.f,8.f},icon.at(CHECKPOINT).pos,icon.at(CHECKPOINT).size,{1.f,1.f},{255,255,255,iconAlpha}); DeferRenderingBasedOnPosition(WorldToRadar(cp.GetPos()),CHECKPOINT,iconAlpha);
} }
for(const Hamster&h:Hamster::GetHamsters()){ for(const Hamster&h:Hamster::GetHamsters()){
if(&h==&Hamster::GetPlayer())continue; if(&h==&Hamster::GetPlayer())continue;
uint8_t iconAlpha{255U}; uint8_t iconAlpha{255U};
if(h.BurnedOrDrowned())iconAlpha=64U; if(h.BurnedOrDrowned())iconAlpha=64U;
radar.DrawPartialRotatedDecal(WorldToRadar(h.GetPos()),GetGFX("radaricons.png").Decal(),0.f,{8.f,8.f},icon.at(HAMSTER).pos,icon.at(HAMSTER).size,{1.f,1.f},{255,255,255,iconAlpha}); DeferRenderingBasedOnPosition(WorldToRadar(h.GetPos()),HAMSTER,iconAlpha);
} }
} }

@ -52,10 +52,14 @@ void HamsterJet::Update(const float fElapsedTime){
lastTappedSpace+=fElapsedTime; lastTappedSpace+=fElapsedTime;
switch(state){ switch(state){
case SWOOP_DOWN:{ case SWOOP_DOWN:{
HamsterGame::Game().SetZoom(1.5f); if(hamster.IsPlayerControlled)HamsterGame::Game().SetZoom(1.5f);
z=util::lerp(0.f,3.f,std::pow(timer/3.f,2)); z=util::lerp(0.f,3.f,std::pow(timer/3.f,2));
vf2d originalPos{hamster.GetPos().x-128.f,hamster.GetPos().y+32.f}; vf2d originalPos{hamster.GetPos().x-128.f,hamster.GetPos().y+32.f};
if(timer<=0.4f){ if(timer<=0.4f){
if(!setHamsterOriginalPos){
setHamsterOriginalPos=true;
hamsterOriginalPos=hamster.GetPos();
}
hamster.SetPos(hamsterOriginalPos-vf2d{0.f,sin(float(geom2d::pi)*timer/0.4f)*8.f}); hamster.SetPos(hamsterOriginalPos-vf2d{0.f,sin(float(geom2d::pi)*timer/0.4f)*8.f});
hamster.SetZ(sin(float(geom2d::pi)*timer/0.4f)*0.2f); hamster.SetZ(sin(float(geom2d::pi)*timer/0.4f)*0.2f);
jetState[TOP_LEFT]=jetState[BOTTOM_LEFT]=jetState[BOTTOM_RIGHT]=jetState[TOP_RIGHT]=OFF; jetState[TOP_LEFT]=jetState[BOTTOM_LEFT]=jetState[BOTTOM_RIGHT]=jetState[TOP_RIGHT]=OFF;
@ -80,21 +84,28 @@ void HamsterJet::Update(const float fElapsedTime){
hamster.SetZ(z+0.03f); hamster.SetZ(z+0.03f);
if(timer<=0.f){ if(timer<=0.f){
state=HAMSTER_CONTROL; state=HAMSTER_CONTROL;
HamsterGame::Game().SetZoom(0.6f); if(hamster.IsPlayerControlled)HamsterGame::Game().SetZoom(0.6f);
easeInTimer=0.6f; easeInTimer=0.6f;
} }
}break; }break;
case HAMSTER_CONTROL:{ case HAMSTER_CONTROL:{
easeInTimer=std::max(0.f,easeInTimer-fElapsedTime); easeInTimer=std::max(0.f,easeInTimer-fElapsedTime);
jetState[TOP_LEFT]=jetState[BOTTOM_LEFT]=jetState[BOTTOM_RIGHT]=jetState[TOP_RIGHT]=OFF; jetState[TOP_LEFT]=jetState[BOTTOM_LEFT]=jetState[BOTTOM_RIGHT]=jetState[TOP_RIGHT]=OFF;
HandleJetControls(); if(hamster.CanMove()){
if(hamster.IsPlayerControlled)HandleJetControls();
else{
//TODO: AI controls here!
}
}
}break; }break;
case LANDING:{ case LANDING:{
easeInTimer=std::min(0.6f,easeInTimer+fElapsedTime); easeInTimer=std::min(0.6f,easeInTimer+fElapsedTime);
jetState[TOP_LEFT]=jetState[BOTTOM_LEFT]=jetState[BOTTOM_RIGHT]=jetState[TOP_RIGHT]=OFF; jetState[TOP_LEFT]=jetState[BOTTOM_LEFT]=jetState[BOTTOM_RIGHT]=jetState[TOP_RIGHT]=OFF;
if(hamster.IsPlayerControlled)HandleJetControls(); if(hamster.CanMove()){
else{ if(hamster.IsPlayerControlled)HandleJetControls();
//TODO: AI controls here! else{
//TODO: AI controls here!
}
} }
pos=hamster.GetPos(); pos=hamster.GetPos();
hamster.SetZ(hamster.GetZ()-fallSpd*fElapsedTime); hamster.SetZ(hamster.GetZ()-fallSpd*fElapsedTime);
@ -103,7 +114,7 @@ void HamsterJet::Update(const float fElapsedTime){
hamster.SetZ(0.f); hamster.SetZ(0.f);
state=COMPLETE_LANDING; state=COMPLETE_LANDING;
hamster.SetState(Hamster::NORMAL); hamster.SetState(Hamster::NORMAL);
HamsterGame::Game().SetZoom(1.f); if(hamster.IsPlayerControlled)HamsterGame::Game().SetZoom(1.f);
timer=3.f; timer=3.f;
originalPos=hamster.GetPos(); originalPos=hamster.GetPos();
targetPos={hamster.GetPos().x+128.f,hamster.GetPos().y+32.f}; targetPos={hamster.GetPos().x+128.f,hamster.GetPos().y+32.f};
@ -221,3 +232,7 @@ Terrain::CrashSpeed HamsterJet::GetLandingSpeed()const{
if(fallSpd>2.f)return Terrain::MEDIUM; if(fallSpd>2.f)return Terrain::MEDIUM;
else return Terrain::LIGHT; else return Terrain::LIGHT;
} }
const float HamsterJet::GetZ()const{
return z;
}

@ -39,11 +39,9 @@ All rights reserved.
#include "olcUTIL_Geometry2D.h" #include "olcUTIL_Geometry2D.h"
#include "SpecialRenderable.h" #include "SpecialRenderable.h"
#include "Terrain.h"
class Hamster; class Hamster;
namespace Terrain{
enum CrashSpeed;
};
class HamsterJet{ class HamsterJet{
public: public:
@ -80,6 +78,7 @@ private:
float timer{}; float timer{};
std::array<JetState,4>jetState{}; std::array<JetState,4>jetState{};
float lastTappedSpace{}; float lastTappedSpace{};
bool setHamsterOriginalPos{false};
public: public:
HamsterJet(Hamster&hamster); HamsterJet(Hamster&hamster);
void Update(const float fElapsedTime); void Update(const float fElapsedTime);
@ -89,4 +88,5 @@ public:
const State GetState()const; const State GetState()const;
void SetPos(const vf2d pos); void SetPos(const vf2d pos);
Terrain::CrashSpeed GetLandingSpeed()const; Terrain::CrashSpeed GetLandingSpeed()const;
const float GetZ()const;
}; };

@ -976,221 +976,90 @@ namespace olc
line2 = GFX3D::Math::Vec_Sub(triTransformed.p[2], triTransformed.p[0]); line2 = GFX3D::Math::Vec_Sub(triTransformed.p[2], triTransformed.p[0]);
normal = GFX3D::Math::Vec_CrossProduct(line1, line2); normal = GFX3D::Math::Vec_CrossProduct(line1, line2);
normal = GFX3D::Math::Vec_Normalise(normal); normal = GFX3D::Math::Vec_Normalise(normal);
triangle triProjected = triTransformed;
// Cull triangles that face away from viewer
if (flags & RENDER_CULL_CW && GFX3D::Math::Vec_DotProduct(normal, triTransformed.p[0]) > 0.0f) continue; // Project new triangle
if (flags & RENDER_CULL_CCW && GFX3D::Math::Vec_DotProduct(normal, triTransformed.p[0]) < 0.0f) continue; triProjected.p[0] = GFX3D::Math::Mat_MultiplyVector(matProj, triTransformed.p[0]);
triProjected.p[1] = GFX3D::Math::Mat_MultiplyVector(matProj, triTransformed.p[1]);
// If Lighting, calculate shading triProjected.p[2] = GFX3D::Math::Mat_MultiplyVector(matProj, triTransformed.p[2]);
if (flags & RENDER_LIGHTS)
// Apply Projection to Verts
triProjected.p[0].x = triProjected.p[0].x / triProjected.p[0].w;
triProjected.p[1].x = triProjected.p[1].x / triProjected.p[1].w;
triProjected.p[2].x = triProjected.p[2].x / triProjected.p[2].w;
triProjected.p[0].y = triProjected.p[0].y / triProjected.p[0].w;
triProjected.p[1].y = triProjected.p[1].y / triProjected.p[1].w;
triProjected.p[2].y = triProjected.p[2].y / triProjected.p[2].w;
triProjected.p[0].z = triProjected.p[0].z / triProjected.p[0].w;
triProjected.p[1].z = triProjected.p[1].z / triProjected.p[1].w;
triProjected.p[2].z = triProjected.p[2].z / triProjected.p[2].w;
// Apply Projection to Tex coords
triProjected.t[0].x = triProjected.t[0].x / triProjected.p[0].w;
triProjected.t[1].x = triProjected.t[1].x / triProjected.p[1].w;
triProjected.t[2].x = triProjected.t[2].x / triProjected.p[2].w;
triProjected.t[0].y = triProjected.t[0].y / triProjected.p[0].w;
triProjected.t[1].y = triProjected.t[1].y / triProjected.p[1].w;
triProjected.t[2].y = triProjected.t[2].y / triProjected.p[2].w;
triProjected.t[0].z = 1.0f / triProjected.p[0].w;
triProjected.t[1].z = 1.0f / triProjected.p[1].w;
triProjected.t[2].z = 1.0f / triProjected.p[2].w;
// Scale to viewport
/*triRaster.p[0].x *= -1.0f;
triRaster.p[1].x *= -1.0f;
triRaster.p[2].x *= -1.0f;
triRaster.p[0].y *= -1.0f;
triRaster.p[1].y *= -1.0f;
triTransformed.p[2].y *= -1.0f;*/
vec3d vOffsetView = { 1,1,0 };
triProjected.p[0] = Math::Vec_Add(triProjected.p[0], vOffsetView);
triProjected.p[1] = Math::Vec_Add(triProjected.p[1], vOffsetView);
triProjected.p[2] = Math::Vec_Add(triProjected.p[2], vOffsetView);
triProjected.p[0].x *= 0.5f * fViewW;
triProjected.p[0].y *= 0.5f * fViewH;
triProjected.p[1].x *= 0.5f * fViewW;
triProjected.p[1].y *= 0.5f * fViewH;
triProjected.p[2].x *= 0.5f * fViewW;
triProjected.p[2].y *= 0.5f * fViewH;
vOffsetView = { fViewX,fViewY,0 };
triProjected.p[0] = Math::Vec_Add(triProjected.p[0], vOffsetView);
triProjected.p[1] = Math::Vec_Add(triProjected.p[1], vOffsetView);
triProjected.p[2] = Math::Vec_Add(triProjected.p[2], vOffsetView);
// For now, just draw triangle
//if (flags & RENDER_TEXTURED)
//{/*
// TexturedTriangle(
// triProjected.p[0].x, triProjected.p[0].y, triProjected.t[0].x, triProjected.t[0].y, triProjected.t[0].z,
// triProjected.p[1].x, triProjected.p[1].y, triProjected.t[1].x, triProjected.t[1].y, triProjected.t[1].z,
// triProjected.p[2].x, triProjected.p[2].y, triProjected.t[2].x, triProjected.t[2].y, triProjected.t[2].z,
// sprTexture);*/
// RasterTriangle(
// triProjected.p[0].x, triProjected.p[0].y, triProjected.t[0].x, triProjected.t[0].y, triProjected.t[0].z, triProjected.col,
// triProjected.p[1].x, triProjected.p[1].y, triProjected.t[1].x, triProjected.t[1].y, triProjected.t[1].z, triProjected.col,
// triProjected.p[2].x, triProjected.p[2].y, triProjected.t[2].x, triProjected.t[2].y, triProjected.t[2].z, triProjected.col,
// sprTexture, nFlags);
//}
if (flags & RENDER_WIRE)
{ {
olc::Pixel ambient_clamp = { 0,0,0 }; DrawTriangleWire(triProjected, olc::RED);
olc::Pixel light_combined = { 0,0,0 };
uint32_t nLightSources = 0;
float nLightR = 0, nLightG = 0, nLightB = 0;
for (int i = 0; i < 4; i++)
{
switch (lights[i].type)
{
case LIGHT_DISABLED:
break;
case LIGHT_AMBIENT:
ambient_clamp = lights[i].col;
break;
case LIGHT_DIRECTIONAL:
{
nLightSources++;
GFX3D::vec3d light_dir = GFX3D::Math::Vec_Normalise(lights[i].dir);
float light = GFX3D::Math::Vec_DotProduct(light_dir, normal);
if (light > 0)
{
int j = 0;
}
light = std::max(light, 0.0f);
nLightR += light * (lights[i].col.r/255.0f);
nLightG += light * (lights[i].col.g/255.0f);
nLightB += light * (lights[i].col.b/255.0f);
}
break;
case LIGHT_POINT:
break;
}
}
//nLightR /= nLightSources;
//nLightG /= nLightSources;
//nLightB /= nLightSources;
nLightR = std::max(nLightR, ambient_clamp.r / 255.0f);
nLightG = std::max(nLightG, ambient_clamp.g / 255.0f);
nLightB = std::max(nLightB, ambient_clamp.b / 255.0f);
triTransformed.col[0] = olc::Pixel(uint8_t(nLightR * triTransformed.col[0].r), uint8_t(nLightG * triTransformed.col[0].g), uint8_t(nLightB * triTransformed.col[0].b));
triTransformed.col[1] = olc::Pixel(uint8_t(nLightR * triTransformed.col[1].r), uint8_t(nLightG * triTransformed.col[1].g), uint8_t(nLightB * triTransformed.col[1].b));
triTransformed.col[2] = olc::Pixel(uint8_t(nLightR * triTransformed.col[2].r), uint8_t(nLightG * triTransformed.col[2].g), uint8_t(nLightB * triTransformed.col[2].b));
/*GFX3D::vec3d light_dir = { 1,1,1 };
light_dir = GFX3D::Math::Vec_Normalise(light_dir);
float light = GFX3D::Math::Vec_DotProduct(light_dir, normal);
if (light < 0) light = 0;
triTransformed.col[0] = olc::Pixel(light * 255.0f, light * 255.0f, light * 255.0f);
triTransformed.col[1] = olc::Pixel(light * 255.0f, light * 255.0f, light * 255.0f);
triTransformed.col[2] = olc::Pixel(light * 255.0f, light * 255.0f, light * 255.0f);*/
} }
//else else
// triTransformed.col = olc::WHITE;
// Clip triangle against near plane
int nClippedTriangles = 0;
GFX3D::triangle clipped[2];
nClippedTriangles = GFX3D::Math::Triangle_ClipAgainstPlane({ 0.0f, 0.0f, 0.1f }, { 0.0f, 0.0f, 1.0f }, triTransformed, clipped[0], clipped[1]);
// This may yield two new triangles
for (int n = 0; n < nClippedTriangles; n++)
{ {
triangle triProjected = clipped[n]; RasterTriangle(
triProjected.p[0].x,triProjected.p[0].y,triProjected.p[0].z, triProjected.t[0].x, triProjected.t[0].y, triProjected.t[0].z, triProjected.col[0],
// Project new triangle triProjected.p[1].x,triProjected.p[1].y,triProjected.p[1].z, triProjected.t[1].x, triProjected.t[1].y, triProjected.t[1].z, triProjected.col[1],
triProjected.p[0] = GFX3D::Math::Mat_MultiplyVector(matProj, clipped[n].p[0]); triProjected.p[2].x,triProjected.p[2].y,triProjected.p[2].z, triProjected.t[2].x, triProjected.t[2].y, triProjected.t[2].z, triProjected.col[2],
triProjected.p[1] = GFX3D::Math::Mat_MultiplyVector(matProj, clipped[n].p[1]); dec, flags);
triProjected.p[2] = GFX3D::Math::Mat_MultiplyVector(matProj, clipped[n].p[2]);
// Apply Projection to Verts
triProjected.p[0].x = triProjected.p[0].x / triProjected.p[0].w;
triProjected.p[1].x = triProjected.p[1].x / triProjected.p[1].w;
triProjected.p[2].x = triProjected.p[2].x / triProjected.p[2].w;
triProjected.p[0].y = triProjected.p[0].y / triProjected.p[0].w;
triProjected.p[1].y = triProjected.p[1].y / triProjected.p[1].w;
triProjected.p[2].y = triProjected.p[2].y / triProjected.p[2].w;
triProjected.p[0].z = triProjected.p[0].z / triProjected.p[0].w;
triProjected.p[1].z = triProjected.p[1].z / triProjected.p[1].w;
triProjected.p[2].z = triProjected.p[2].z / triProjected.p[2].w;
// Apply Projection to Tex coords
triProjected.t[0].x = triProjected.t[0].x / triProjected.p[0].w;
triProjected.t[1].x = triProjected.t[1].x / triProjected.p[1].w;
triProjected.t[2].x = triProjected.t[2].x / triProjected.p[2].w;
triProjected.t[0].y = triProjected.t[0].y / triProjected.p[0].w;
triProjected.t[1].y = triProjected.t[1].y / triProjected.p[1].w;
triProjected.t[2].y = triProjected.t[2].y / triProjected.p[2].w;
triProjected.t[0].z = 1.0f / triProjected.p[0].w;
triProjected.t[1].z = 1.0f / triProjected.p[1].w;
triProjected.t[2].z = 1.0f / triProjected.p[2].w;
// Clip against viewport in screen space
// Clip triangles against all four screen edges, this could yield
// a bunch of triangles, so create a queue that we traverse to
// ensure we only test new triangles generated against planes
GFX3D::triangle sclipped[2];
std::list<GFX3D::triangle> listTriangles;
// Add initial triangle
listTriangles.push_back(triProjected);
int nNewTriangles = 1;
for (int p = 0; p < 4; p++)
{
int nTrisToAdd = 0;
while (nNewTriangles > 0)
{
// Take triangle from front of queue
triangle test = listTriangles.front();
listTriangles.pop_front();
nNewTriangles--;
// Clip it against a plane. We only need to test each
// subsequent plane, against subsequent new triangles
// as all triangles after a plane clip are guaranteed
// to lie on the inside of the plane. I like how this
// comment is almost completely and utterly justified
switch (p)
{
case 0: nTrisToAdd = GFX3D::Math::Triangle_ClipAgainstPlane({ 0.0f, -1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, test, sclipped[0], sclipped[1]); break;
case 1: nTrisToAdd = GFX3D::Math::Triangle_ClipAgainstPlane({ 0.0f, +1.0f, 0.0f }, { 0.0f, -1.0f, 0.0f }, test, sclipped[0], sclipped[1]); break;
case 2: nTrisToAdd = GFX3D::Math::Triangle_ClipAgainstPlane({ -1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, test, sclipped[0], sclipped[1]); break;
case 3: nTrisToAdd = GFX3D::Math::Triangle_ClipAgainstPlane({ +1.0f, 0.0f, 0.0f }, { -1.0f, 0.0f, 0.0f }, test, sclipped[0], sclipped[1]); break;
}
// Clipping may yield a variable number of triangles, so
// add these new ones to the back of the queue for subsequent
// clipping against next planes
for (int w = 0; w < nTrisToAdd; w++)
listTriangles.push_back(sclipped[w]);
}
nNewTriangles = listTriangles.size();
}
for (auto &triRaster : listTriangles)
{
// Scale to viewport
/*triRaster.p[0].x *= -1.0f;
triRaster.p[1].x *= -1.0f;
triRaster.p[2].x *= -1.0f;
triRaster.p[0].y *= -1.0f;
triRaster.p[1].y *= -1.0f;
triRaster.p[2].y *= -1.0f;*/
vec3d vOffsetView = { 1,1,0 };
triRaster.p[0] = Math::Vec_Add(triRaster.p[0], vOffsetView);
triRaster.p[1] = Math::Vec_Add(triRaster.p[1], vOffsetView);
triRaster.p[2] = Math::Vec_Add(triRaster.p[2], vOffsetView);
triRaster.p[0].x *= 0.5f * fViewW;
triRaster.p[0].y *= 0.5f * fViewH;
triRaster.p[1].x *= 0.5f * fViewW;
triRaster.p[1].y *= 0.5f * fViewH;
triRaster.p[2].x *= 0.5f * fViewW;
triRaster.p[2].y *= 0.5f * fViewH;
vOffsetView = { fViewX,fViewY,0 };
triRaster.p[0] = Math::Vec_Add(triRaster.p[0], vOffsetView);
triRaster.p[1] = Math::Vec_Add(triRaster.p[1], vOffsetView);
triRaster.p[2] = Math::Vec_Add(triRaster.p[2], vOffsetView);
// For now, just draw triangle
//if (flags & RENDER_TEXTURED)
//{/*
// TexturedTriangle(
// triRaster.p[0].x, triRaster.p[0].y, triRaster.t[0].x, triRaster.t[0].y, triRaster.t[0].z,
// triRaster.p[1].x, triRaster.p[1].y, triRaster.t[1].x, triRaster.t[1].y, triRaster.t[1].z,
// triRaster.p[2].x, triRaster.p[2].y, triRaster.t[2].x, triRaster.t[2].y, triRaster.t[2].z,
// sprTexture);*/
// RasterTriangle(
// triRaster.p[0].x, triRaster.p[0].y, triRaster.t[0].x, triRaster.t[0].y, triRaster.t[0].z, triRaster.col,
// triRaster.p[1].x, triRaster.p[1].y, triRaster.t[1].x, triRaster.t[1].y, triRaster.t[1].z, triRaster.col,
// triRaster.p[2].x, triRaster.p[2].y, triRaster.t[2].x, triRaster.t[2].y, triRaster.t[2].z, triRaster.col,
// sprTexture, nFlags);
//}
if (flags & RENDER_WIRE)
{
DrawTriangleWire(triRaster, olc::RED);
}
else
{
RasterTriangle(
triRaster.p[0].x,triRaster.p[0].y,triRaster.p[0].z, triRaster.t[0].x, triRaster.t[0].y, triRaster.t[0].z, triRaster.col[0],
triRaster.p[1].x,triRaster.p[1].y,triRaster.p[1].z, triRaster.t[1].x, triRaster.t[1].y, triRaster.t[1].z, triRaster.col[1],
triRaster.p[2].x,triRaster.p[2].y,triRaster.p[2].z, triRaster.t[2].x, triRaster.t[2].y, triRaster.t[2].z, triRaster.col[2],
dec, flags);
}
nTriangleDrawnCount++;
}
} }
} }

@ -156,7 +156,7 @@ olc::ViewPort::ViewPort(std::vector<vf2d> vertices, olc::vf2d offset)
} }
void olc::ViewPort::addPoint(vf2d point) { void olc::ViewPort::addPoint(vf2d point) {
clipVertices.push_back(point); clipVertices.emplace_back(point);
} }
void olc::ViewPort::clear() { void olc::ViewPort::clear() {
@ -600,17 +600,17 @@ void olc::ViewPort::drawClippedDecal(Decal *decal,
if (bDirection <= 0) { if (bDirection <= 0) {
if (aDirection > 0) { if (aDirection > 0) {
outputList.push_back(intersectionPoint); outputList.emplace_back(intersectionPoint);
outputUvs.push_back(intersectionUv); outputUvs.emplace_back(intersectionUv);
outputCols.push_back(intersectionCol); outputCols.emplace_back(intersectionCol);
} }
outputList.push_back(polygonB); outputList.emplace_back(polygonB);
outputUvs.push_back(uvB); outputUvs.emplace_back(uvB);
outputCols.push_back(colB); outputCols.emplace_back(colB);
} else if (aDirection <= 0) { } else if (aDirection <= 0) {
outputList.push_back(intersectionPoint); outputList.emplace_back(intersectionPoint);
outputUvs.push_back(intersectionUv); outputUvs.emplace_back(intersectionUv);
outputCols.push_back(intersectionCol); outputCols.emplace_back(intersectionCol);
} }
} }
} }
@ -670,17 +670,17 @@ void olc::ViewPort::drawClippedPolygonDecal(Decal *decal,
if (bDirection <= 0) { if (bDirection <= 0) {
if (aDirection > 0) { if (aDirection > 0) {
outputList.push_back(intersectionPoint); outputList.emplace_back(intersectionPoint);
outputUvs.push_back(intersectionUv); outputUvs.emplace_back(intersectionUv);
outputDepths.push_back(intersectionDepth); outputDepths.emplace_back(intersectionDepth);
} }
outputList.push_back(polygonB); outputList.emplace_back(polygonB);
outputUvs.push_back(uvB); outputUvs.emplace_back(uvB);
outputDepths.push_back(Wb); outputDepths.emplace_back(Wb);
} else if (aDirection <= 0) { } else if (aDirection <= 0) {
outputList.push_back(intersectionPoint); outputList.emplace_back(intersectionPoint);
outputUvs.push_back(intersectionUv); outputUvs.emplace_back(intersectionUv);
outputDepths.push_back(intersectionDepth); outputDepths.emplace_back(intersectionDepth);
} }
} }
} }

@ -4596,26 +4596,12 @@ namespace olc
glBegin(GL_TRIANGLES); glBegin(GL_TRIANGLES);
} }
if (decal.depth) // Render as 2D Spatial entity
for (uint32_t n = 0; n < decal.points; n++)
{ {
glColor4ub(decal.tint[n].r, decal.tint[n].g, decal.tint[n].b, decal.tint[n].a);
// Render as 3D Spatial Entity glTexCoord4f(decal.uv[n].x, decal.uv[n].y, 0.0f, decal.w[n]);
for (uint32_t n = 0; n < decal.points; n++) glVertex2f(decal.pos[n].x, decal.pos[n].y);
{
glColor4ub(decal.tint[n].r, decal.tint[n].g, decal.tint[n].b, decal.tint[n].a);
glTexCoord4f(decal.uv[n].x, decal.uv[n].y, 0.0f, decal.w[n]);
glVertex3f(decal.pos[n].x, decal.pos[n].y, decal.z[n]);
}
}
else
{
// Render as 2D Spatial entity
for (uint32_t n = 0; n < decal.points; n++)
{
glColor4ub(decal.tint[n].r, decal.tint[n].g, decal.tint[n].b, decal.tint[n].a);
glTexCoord4f(decal.uv[n].x, decal.uv[n].y, 0.0f, decal.w[n]);
glVertex2f(decal.pos[n].x, decal.pos[n].y);
}
} }
glEnd(); glEnd();

Loading…
Cancel
Save