diff --git a/Chapter06/Actor.cpp b/Chapter06/Actor.cpp new file mode 100644 index 00000000..b3715cca --- /dev/null +++ b/Chapter06/Actor.cpp @@ -0,0 +1,124 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#include "Actor.h" +#include "Game.h" +#include "Component.h" +#include + +Actor::Actor(Game* game) + :mState(EActive) + ,mPosition(Vector3::Zero) + ,mRotation(Quaternion::Identity) + ,mScale(1.0f) + ,mGame(game) + ,mRecomputeWorldTransform(true) +{ + mGame->AddActor(this); +} + +Actor::~Actor() +{ + mGame->RemoveActor(this); + // Need to delete components + // Because ~Component calls RemoveComponent, need a different style loop + while (!mComponents.empty()) + { + delete mComponents.back(); + } +} + +void Actor::Update(float deltaTime) +{ + if (mState == EActive) + { + ComputeWorldTransform(); + + UpdateComponents(deltaTime); + UpdateActor(deltaTime); + + ComputeWorldTransform(); + } +} + +void Actor::UpdateComponents(float deltaTime) +{ + for (auto comp : mComponents) + { + comp->Update(deltaTime); + } +} + +void Actor::UpdateActor(float deltaTime) +{ +} + +void Actor::ProcessInput(const uint8_t* keyState) +{ + if (mState == EActive) + { + // First process input for components + for (auto comp : mComponents) + { + comp->ProcessInput(keyState); + } + + ActorInput(keyState); + } +} + +void Actor::ActorInput(const uint8_t* keyState) +{ +} + +void Actor::ComputeWorldTransform() +{ + if (mRecomputeWorldTransform) + { + mRecomputeWorldTransform = false; + // Scale, then rotate, then translate + mWorldTransform = Matrix4::CreateScale(mScale); + mWorldTransform *= Matrix4::CreateFromQuaternion(mRotation); + mWorldTransform *= Matrix4::CreateTranslation(mPosition); + + // Inform components world transform updated + for (auto comp : mComponents) + { + comp->OnUpdateWorldTransform(); + } + } +} + +void Actor::AddComponent(Component* component) +{ + // Find the insertion point in the sorted vector + // (The first element with a order higher than me) + int myOrder = component->GetUpdateOrder(); + auto iter = mComponents.begin(); + for (; + iter != mComponents.end(); + ++iter) + { + if (myOrder < (*iter)->GetUpdateOrder()) + { + break; + } + } + + // Inserts element before position of iterator + mComponents.insert(iter, component); +} + +void Actor::RemoveComponent(Component* component) +{ + auto iter = std::find(mComponents.begin(), mComponents.end(), component); + if (iter != mComponents.end()) + { + mComponents.erase(iter); + } +} diff --git a/Chapter06/Actor.h b/Chapter06/Actor.h new file mode 100644 index 00000000..05d6b1b6 --- /dev/null +++ b/Chapter06/Actor.h @@ -0,0 +1,74 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#pragma once +#include +#include "Math.h" +#include + +class Actor +{ +public: + enum State + { + EActive, + EPaused, + EDead + }; + + Actor(class Game* game); + virtual ~Actor(); + + // Update function called from Game (not overridable) + void Update(float deltaTime); + // Updates all the components attached to the actor (not overridable) + void UpdateComponents(float deltaTime); + // Any actor-specific update code (overridable) + virtual void UpdateActor(float deltaTime); + + // ProcessInput function called from Game (not overridable) + void ProcessInput(const uint8_t* keyState); + // Any actor-specific input code (overridable) + virtual void ActorInput(const uint8_t* keyState); + + // Getters/setters + const Vector3& GetPosition() const { return mPosition; } + void SetPosition(const Vector3& pos) { mPosition = pos; mRecomputeWorldTransform = true; } + float GetScale() const { return mScale; } + void SetScale(float scale) { mScale = scale; mRecomputeWorldTransform = true; } + const Quaternion& GetRotation() const { return mRotation; } + void SetRotation(const Quaternion& rotation) { mRotation = rotation; mRecomputeWorldTransform = true; } + + void ComputeWorldTransform(); + const Matrix4& GetWorldTransform() const { return mWorldTransform; } + + Vector3 GetForward() const { return Vector3::Transform(Vector3::UnitX, mRotation); } + + State GetState() const { return mState; } + void SetState(State state) { mState = state; } + + class Game* GetGame() { return mGame; } + + + // Add/remove components + void AddComponent(class Component* component); + void RemoveComponent(class Component* component); +private: + // Actor's state + State mState; + + // Transform + Matrix4 mWorldTransform; + Vector3 mPosition; + Quaternion mRotation; + float mScale; + bool mRecomputeWorldTransform; + + std::vector mComponents; + class Game* mGame; +}; diff --git a/Chapter06/Assets/Cube.gpmesh b/Chapter06/Assets/Cube.gpmesh new file mode 100644 index 00000000..de40a15e --- /dev/null +++ b/Chapter06/Assets/Cube.gpmesh @@ -0,0 +1,53 @@ +{ + "version":1, + "vertexformat":"PosNormTex", + "shader":"BasicMesh", + "textures":[ + "Assets/Cube.png" + ], + "specularPower":100.0, + "vertices":[ + [-0.5,-0.5,-0.5,0,0,-1,0,0], + [0.5,-0.5,-0.5,0,0,-1,1,0], + [-0.5,0.5,-0.5,0,0,-1,0,-1], + [0.5,0.5,-0.5,0,0,-1,1,-1], + [-0.5,0.5,0.5,0,1,0,0,-1], + [0.5,0.5,0.5,0,1,0,1,-1], + [-0.5,-0.5,0.5,0,0,1,0,0], + [0.5,-0.5,0.5,0,0,1,1,0], + [-0.5,0.5,-0.5,0,0,-1,0,-1], + [0.5,-0.5,-0.5,0,0,-1,1,0], + [-0.5,0.5,-0.5,0,1,0,0,-1], + [0.5,0.5,-0.5,0,1,0,1,-1], + [-0.5,0.5,0.5,0,1,0,0,-1], + [-0.5,0.5,0.5,0,0,1,0,-1], + [0.5,0.5,0.5,0,0,1,1,-1], + [-0.5,-0.5,0.5,0,0,1,0,0], + [-0.5,-0.5,0.5,0,-1,0,0,0], + [0.5,-0.5,0.5,0,-1,0,1,0], + [-0.5,-0.5,-0.5,0,-1,0,0,0], + [0.5,-0.5,-0.5,0,-1,0,1,0], + [0.5,-0.5,-0.5,1,0,0,1,0], + [0.5,-0.5,0.5,1,0,0,1,0], + [0.5,0.5,-0.5,1,0,0,1,-1], + [0.5,0.5,0.5,1,0,0,1,-1], + [-0.5,-0.5,0.5,-1,0,0,0,0], + [-0.5,-0.5,-0.5,-1,0,0,0,0], + [-0.5,0.5,0.5,-1,0,0,0,-1], + [-0.5,0.5,-0.5,-1,0,0,0,-1] + ], + "indices":[ + [2,1,0], + [3,9,8], + [4,11,10], + [5,11,12], + [6,14,13], + [7,14,15], + [18,17,16], + [19,17,18], + [22,21,20], + [23,21,22], + [26,25,24], + [27,25,26] + ] +} diff --git a/Chapter06/Assets/Cube.png b/Chapter06/Assets/Cube.png new file mode 100644 index 00000000..623b1d39 Binary files /dev/null and b/Chapter06/Assets/Cube.png differ diff --git a/Chapter06/Assets/Default.png b/Chapter06/Assets/Default.png new file mode 100644 index 00000000..165f4df7 Binary files /dev/null and b/Chapter06/Assets/Default.png differ diff --git a/Chapter06/Assets/HealthBar.png b/Chapter06/Assets/HealthBar.png new file mode 100644 index 00000000..ac937016 Binary files /dev/null and b/Chapter06/Assets/HealthBar.png differ diff --git a/Chapter06/Assets/Plane.gpmesh b/Chapter06/Assets/Plane.gpmesh new file mode 100644 index 00000000..9b461fa2 --- /dev/null +++ b/Chapter06/Assets/Plane.gpmesh @@ -0,0 +1,70 @@ +{ + "version":1, + "vertexformat":"PosNormTex", + "shader":"BasicMesh", + "textures":[ + "Assets/Plane.png" + ], + "specularPower":100.0, + "vertices":[ + [50.000000,50.000000,-0.000000,-0.003922,-0.003922,1.000000,1.000000,1.000000], + [50.000000,25.000000,-0.000000,-0.003922,-0.003922,1.000000,1.000000,0.750000], + [25.000000,50.000000,-0.000000,-0.003922,-0.003922,1.000000,0.750000,1.000000], + [25.000000,25.000000,-0.000000,-0.003922,-0.003922,1.000000,0.750000,0.750000], + [0.000000,50.000000,-0.000000,-0.003922,-0.003922,1.000000,0.500000,1.000000], + [50.000000,-0.000000,0.000000,-0.003922,-0.003922,1.000000,1.000000,0.500000], + [0.000000,25.000000,-0.000000,-0.003922,-0.003922,1.000000,0.500000,0.750000], + [-25.000000,50.000000,-0.000000,-0.003922,-0.003922,1.000000,0.250000,1.000000], + [25.000000,-0.000000,0.000000,-0.003922,-0.003922,1.000000,0.750000,0.500000], + [50.000000,-25.000000,0.000000,-0.003922,-0.003922,1.000000,1.000000,0.250000], + [-25.000000,25.000000,-0.000000,-0.003922,-0.003922,1.000000,0.250000,0.750000], + [-50.000000,50.000000,-0.000000,-0.003922,-0.003922,1.000000,0.000000,1.000000], + [-50.000000,25.000000,-0.000000,-0.003922,-0.003922,1.000000,0.000000,0.750000], + [0.000000,-0.000000,0.000000,-0.003922,-0.003922,1.000000,0.500000,0.500000], + [25.000000,-25.000000,0.000000,-0.003922,-0.003922,1.000000,0.750000,0.250000], + [50.000000,-50.000000,0.000000,-0.003922,-0.003922,1.000000,1.000000,0.000000], + [25.000000,-50.000000,0.000000,-0.003922,-0.003922,1.000000,0.750000,0.000000], + [-25.000000,-0.000000,0.000000,-0.003922,-0.003922,1.000000,0.250000,0.500000], + [-50.000000,-0.000000,0.000000,-0.003922,-0.003922,1.000000,0.000000,0.500000], + [0.000000,-25.000000,0.000000,-0.003922,-0.003922,1.000000,0.500000,0.250000], + [0.000000,-50.000000,0.000000,-0.003922,-0.003922,1.000000,0.500000,0.000000], + [-25.000000,-25.000000,0.000000,-0.003922,-0.003922,1.000000,0.250000,0.250000], + [-50.000000,-25.000000,0.000000,-0.003922,-0.003922,1.000000,0.000000,0.250000], + [-25.000000,-50.000000,0.000000,-0.003922,-0.003922,1.000000,0.250000,0.000000], + [-50.000000,-50.000000,0.000000,-0.003922,-0.003922,1.000000,0.000000,0.000000] + ], + "indices":[ + [0,1,2], + [3,2,1], + [2,3,4], + [1,5,3], + [6,4,3], + [4,6,7], + [8,3,5], + [3,8,6], + [5,9,8], + [10,7,6], + [7,10,11], + [12,11,10], + [13,6,8], + [6,13,10], + [14,8,9], + [8,14,13], + [9,15,14], + [16,14,15], + [10,17,12], + [17,10,13], + [18,12,17], + [19,13,14], + [14,16,19], + [13,19,17], + [20,19,16], + [17,21,18], + [21,17,19], + [19,20,21], + [22,18,21], + [23,21,20], + [21,23,22], + [24,22,23] + ] +} diff --git a/Chapter06/Assets/Plane.png b/Chapter06/Assets/Plane.png new file mode 100644 index 00000000..d6cc44ba Binary files /dev/null and b/Chapter06/Assets/Plane.png differ diff --git a/Chapter06/Assets/Radar.png b/Chapter06/Assets/Radar.png new file mode 100644 index 00000000..d20ef734 Binary files /dev/null and b/Chapter06/Assets/Radar.png differ diff --git a/Chapter06/Assets/Sphere.gpmesh b/Chapter06/Assets/Sphere.gpmesh new file mode 100644 index 00000000..02700de4 --- /dev/null +++ b/Chapter06/Assets/Sphere.gpmesh @@ -0,0 +1,1532 @@ +{ + "version":1, + "vertexformat":"PosNormTex", + "shader":"BasicMesh", + "textures":[ + "Assets/Sphere.png" + ], + "specularPower":10.0, + "vertices":[ + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.968750,0.000000], + [0.475748,-2.391772,12.259815,0.027451,-0.215686,0.968628,0.968750,0.062500], + [-0.000000,-2.438629,12.259815,-0.011765,-0.215686,0.968628,1.000000,0.062500], + [-0.000000,-4.783543,11.548492,-0.003922,-0.388235,0.913726,1.000000,0.125000], + [0.933213,-4.691630,11.548492,0.066667,-0.388235,0.921569,0.968750,0.125000], + [-0.000000,-6.944628,10.393370,-0.011765,-0.568627,0.827451,1.000000,0.187500], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.937500,0.000000], + [0.933218,-2.253001,12.259815,0.066667,-0.207843,0.968628,0.937500,0.062500], + [1.354815,-6.811192,10.393370,0.090196,-0.552941,0.819608,0.968750,0.187500], + [-0.000000,-8.838834,8.838835,-0.011765,-0.717647,0.701961,1.000000,0.250000], + [1.830574,-4.419421,11.548492,0.137255,-0.364706,0.921569,0.937500,0.125000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.906250,0.000000], + [1.354826,-2.027648,12.259815,0.105882,-0.184314,0.968628,0.906250,0.062500], + [1.724352,-8.669002,8.838835,0.129412,-0.701961,0.701961,0.968750,0.250000], + [-0.000000,-10.393370,6.944628,-0.003922,-0.835294,0.545098,1.000000,0.312500], + [2.657581,-6.416005,10.393370,0.207843,-0.529412,0.827451,0.937500,0.187500], + [2.657586,-3.977376,11.548492,0.207843,-0.333333,0.921569,0.906250,0.125000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.875000,0.000000], + [1.724368,-1.724374,12.259815,0.137255,-0.160784,0.968628,0.875000,0.062500], + [2.027624,-10.193668,6.944628,0.145098,-0.819608,0.545098,0.968750,0.312500], + [-0.000001,-11.548492,4.783543,-0.003922,-0.929412,0.372549,1.000000,0.375000], + [3.382459,-8.166025,8.838835,0.262745,-0.662745,0.701961,0.937500,0.250000], + [3.858217,-5.774255,10.393370,0.301961,-0.474510,0.827451,0.906250,0.187500], + [2.252975,-11.326596,4.783543,0.168628,-0.913725,0.372549,0.968750,0.375000], + [-0.000001,-12.259814,2.438629,-0.003922,-0.984314,0.184314,1.000000,0.437500], + [3.977351,-9.602230,6.944628,0.309804,-0.780392,0.552941,0.937500,0.312500], + [2.391745,-12.024251,2.438629,0.176471,-0.968627,0.184314,0.968750,0.437500], + [-0.000001,-12.499999,0.000001,-0.003922,-1.000000,-0.003922,1.000000,0.500000], + [4.419395,-10.669425,4.783543,0.341177,-0.858824,0.372549,0.937500,0.375000], + [4.910579,-7.349232,8.838835,0.388235,-0.600000,0.701961,0.906250,0.250000], + [5.774230,-8.641783,6.944628,0.458824,-0.701961,0.552941,0.906250,0.312500], + [2.438602,-12.259821,0.000001,0.184314,-0.984314,-0.003922,0.968750,0.500000], + [-0.000001,-12.259815,-2.438627,-0.003922,-0.984314,-0.200000,1.000000,0.562012], + [4.691605,-11.326601,2.438629,0.364706,-0.913725,0.184314,0.937500,0.437500], + [2.391745,-12.024252,-2.438627,0.176471,-0.968627,-0.200000,0.968750,0.562012], + [-0.000001,-11.548493,-4.783541,-0.003922,-0.929412,-0.388235,1.000000,0.624512], + [4.783519,-11.548503,0.000001,0.372549,-0.929412,-0.003922,0.937500,0.500000], + [6.415980,-9.602233,4.783543,0.505883,-0.780392,0.380392,0.906250,0.375000], + [6.811168,-10.193677,2.438629,0.537255,-0.827451,0.192157,0.906250,0.437500], + [2.252975,-11.326597,-4.783541,0.168628,-0.905882,-0.388235,0.968750,0.624512], + [-0.000000,-10.393370,-6.944627,-0.003922,-0.835294,-0.560784,1.000000,0.687012], + [4.691605,-11.326602,-2.438627,0.364706,-0.913725,-0.200000,0.937500,0.562012], + [2.027624,-10.193668,-6.944627,0.152941,-0.819608,-0.560784,0.968750,0.687012], + [-0.000000,-8.838834,-8.838835,-0.003922,-0.709804,-0.709804,1.000000,0.750000], + [4.419395,-10.669426,-4.783541,0.341177,-0.858824,-0.388235,0.937500,0.624512], + [6.944607,-10.393383,0.000001,0.545098,-0.835294,-0.003922,0.906250,0.500000], + [6.811169,-10.193677,-2.438627,0.537255,-0.819608,-0.200000,0.906250,0.562012], + [1.724352,-8.669002,-8.838835,0.129412,-0.694118,-0.709804,0.968750,0.750000], + [-0.000000,-6.944627,-10.393371,-0.003922,-0.560784,-0.835294,1.000000,0.812500], + [3.977351,-9.602230,-6.944627,0.309804,-0.772549,-0.560784,0.937500,0.687012], + [1.354815,-6.811191,-10.393371,0.098039,-0.545098,-0.835294,0.968750,0.812500], + [-0.000000,-4.783540,-11.548495,-0.003922,-0.388235,-0.929412,1.000000,0.875000], + [3.382459,-8.166025,-8.838835,0.262745,-0.654902,-0.709804,0.937500,0.750000], + [6.415980,-9.602234,-4.783541,0.505883,-0.772549,-0.388235,0.906250,0.624512], + [5.774230,-8.641783,-6.944627,0.450980,-0.694118,-0.560784,0.906250,0.687012], + [0.933212,-4.691628,-11.548495,0.066667,-0.380392,-0.929412,0.968750,0.875000], + [-0.000000,-2.438626,-12.259816,-0.003922,-0.215686,-0.984314,1.000000,0.937500], + [2.657581,-6.416004,-10.393371,0.200000,-0.513725,-0.835294,0.937500,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.968750,1.000000], + [0.475747,-2.391769,-12.259816,0.035294,-0.215686,-0.976471,0.968750,0.937500], + [4.910579,-7.349232,-8.838835,0.380392,-0.592157,-0.709804,0.906250,0.750000], + [1.830573,-4.419419,-11.548495,0.137255,-0.356863,-0.929412,0.937500,0.875000], + [3.858217,-5.774254,-10.393371,0.301961,-0.466667,-0.835294,0.906250,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.937500,1.000000], + [0.933217,-2.252998,-12.259816,0.074510,-0.200000,-0.984314,0.937500,0.937500], + [2.657585,-3.977374,-11.548495,0.200000,-0.317647,-0.929412,0.906250,0.875000], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.906250,1.000000], + [1.354824,-2.027646,-12.259816,0.113726,-0.176471,-0.984314,0.906250,0.937500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.875000,1.000000], + [1.724366,-1.724372,-12.259816,0.145098,-0.152941,-0.984314,0.875000,0.937500], + [3.382468,-3.382480,-11.548495,0.262745,-0.270588,-0.929412,0.875000,0.875000], + [4.910583,-4.910602,-10.393371,0.380392,-0.396078,-0.835294,0.875000,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.843750,1.000000], + [2.027641,-1.354831,-12.259816,0.168628,-0.121569,-0.984314,0.843750,0.937500], + [3.977364,-2.657600,-11.548495,0.309804,-0.215686,-0.929412,0.843750,0.875000], + [5.774240,-3.858238,-10.393371,0.450980,-0.309804,-0.835294,0.843750,0.812500], + [6.249988,-6.250011,-8.838835,0.490196,-0.505882,-0.709804,0.875000,0.750000], + [7.349214,-4.910607,-8.838835,0.576471,-0.396078,-0.709804,0.843750,0.750000], + [7.349208,-7.349236,-6.944627,0.576471,-0.592157,-0.560784,0.875000,0.687012], + [8.641761,-5.774263,-6.944627,0.678432,-0.466667,-0.560784,0.843750,0.687012], + [8.166002,-8.166034,-4.783541,0.647059,-0.662745,-0.396078,0.875000,0.624512], + [9.602210,-6.416017,-4.783541,0.764706,-0.521569,-0.396078,0.843750,0.624512], + [8.668983,-8.669015,-2.438627,0.686275,-0.701961,-0.207843,0.875000,0.562012], + [10.193652,-6.811208,-2.438627,0.811765,-0.552941,-0.207843,0.843750,0.562012], + [8.838818,-8.838851,0.000001,0.701961,-0.717647,-0.011765,0.875000,0.500000], + [10.393357,-6.944647,0.000001,0.827451,-0.568627,-0.011765,0.843750,0.500000], + [8.668982,-8.669014,2.438629,0.686275,-0.701961,0.192157,0.875000,0.437500], + [10.193651,-6.811207,2.438629,0.803922,-0.552941,0.184314,0.843750,0.437500], + [8.166002,-8.166033,4.783543,0.647059,-0.662745,0.380392,0.875000,0.375000], + [9.602209,-6.416017,4.783543,0.756863,-0.521569,0.372549,0.843750,0.375000], + [7.349208,-7.349236,6.944628,0.584314,-0.600000,0.552941,0.875000,0.312500], + [8.641761,-5.774263,6.944628,0.686275,-0.474510,0.552941,0.843750,0.312500], + [6.249988,-6.250011,8.838835,0.498039,-0.513725,0.701961,0.875000,0.250000], + [7.349214,-4.910607,8.838835,0.584314,-0.403922,0.701961,0.843750,0.250000], + [4.910584,-4.910603,10.393370,0.388235,-0.403922,0.827451,0.875000,0.187500], + [5.774240,-3.858239,10.393370,0.458824,-0.325490,0.827451,0.843750,0.187500], + [3.382469,-3.382482,11.548492,0.262745,-0.286274,0.921569,0.875000,0.125000], + [3.977366,-2.657601,11.548492,0.309804,-0.223529,0.921569,0.843750,0.125000], + [2.027643,-1.354833,12.259815,0.168628,-0.137255,0.976471,0.843750,0.062500], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.843750,0.000000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.812500,0.000000], + [2.252998,-0.933226,12.259815,0.192157,-0.098039,0.976471,0.812500,0.062500], + [4.419415,-1.830590,11.548492,0.349020,-0.160784,0.921569,0.812500,0.125000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.781250,0.000000], + [2.391771,-0.475756,12.259815,0.207843,-0.058823,0.976471,0.781250,0.062500], + [6.415995,-2.657605,10.393370,0.505883,-0.223529,0.827451,0.812500,0.187500], + [4.691627,-0.933230,11.548492,0.372549,-0.090196,0.921569,0.781250,0.125000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.750000,0.000000], + [2.438629,-0.000003,12.259815,0.207843,-0.019608,0.976471,0.750000,0.062500], + [8.166013,-3.382490,8.838835,0.647059,-0.286274,0.701961,0.812500,0.250000], + [6.811187,-1.354841,10.393370,0.537255,-0.121569,0.827451,0.781250,0.187500], + [4.783543,-0.000007,11.548492,0.380392,-0.011765,0.921569,0.750000,0.125000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.718750,0.000000], + [2.391772,0.475750,12.259815,0.207843,0.035294,0.976471,0.718750,0.062500], + [9.602215,-3.977387,6.944628,0.764706,-0.333333,0.552941,0.812500,0.312500], + [8.668996,-1.724385,8.838835,0.686275,-0.152941,0.701961,0.781250,0.250000], + [6.944628,-0.000011,10.393370,0.552941,-0.011765,0.827451,0.750000,0.187500], + [10.669409,-4.419436,4.783543,0.850981,-0.364706,0.380392,0.812500,0.375000], + [10.193662,-2.027663,6.944628,0.811765,-0.176471,0.552941,0.781250,0.312500], + [11.326584,-4.691648,2.438629,0.898039,-0.380392,0.184314,0.812500,0.437500], + [11.326589,-2.253018,4.783543,0.898039,-0.192157,0.380392,0.781250,0.375000], + [8.838835,-0.000014,8.838835,0.701961,-0.011765,0.701961,0.750000,0.250000], + [10.393371,-0.000016,6.944628,0.827451,-0.011765,0.552941,0.750000,0.312500], + [11.548486,-4.783563,0.000001,0.913726,-0.388235,-0.003922,0.812500,0.500000], + [12.024242,-2.391791,2.438629,0.960784,-0.200000,0.192157,0.781250,0.437500], + [11.326585,-4.691648,-2.438627,0.898039,-0.380392,-0.200000,0.812500,0.562012], + [12.259812,-2.438649,0.000001,0.976471,-0.207843,-0.011765,0.781250,0.500000], + [11.548493,-0.000018,4.783543,0.921569,-0.011765,0.380392,0.750000,0.375000], + [12.259815,-0.000019,2.438629,0.976471,-0.011765,0.192157,0.750000,0.437500], + [10.669410,-4.419436,-4.783541,0.843137,-0.356863,-0.388235,0.812500,0.624512], + [12.024243,-2.391791,-2.438627,0.952941,-0.192157,-0.200000,0.781250,0.562012], + [9.602215,-3.977387,-6.944627,0.756863,-0.317647,-0.560784,0.812500,0.687012], + [11.326590,-2.253018,-4.783541,0.898039,-0.184314,-0.388235,0.781250,0.624512], + [12.500000,-0.000020,0.000001,0.992157,-0.003922,-0.003922,0.750000,0.500000], + [12.259816,-0.000019,-2.438627,0.976471,-0.011765,-0.207843,0.750000,0.562012], + [8.166013,-3.382490,-8.838835,0.647059,-0.278431,-0.717647,0.812500,0.750000], + [10.193662,-2.027663,-6.944627,0.811765,-0.168627,-0.568627,0.781250,0.687012], + [6.415994,-2.657605,-10.393371,0.505883,-0.215686,-0.835294,0.812500,0.812500], + [8.668996,-1.724385,-8.838835,0.686275,-0.145098,-0.717647,0.781250,0.750000], + [11.548494,-0.000018,-4.783541,0.913726,-0.003922,-0.388235,0.750000,0.624512], + [10.393371,-0.000016,-6.944627,0.827451,-0.011765,-0.568627,0.750000,0.687012], + [4.419412,-1.830589,-11.548495,0.341177,-0.145098,-0.929412,0.812500,0.875000], + [6.811186,-1.354841,-10.393371,0.537255,-0.105882,-0.835294,0.781250,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.812500,1.000000], + [2.252995,-0.933225,-12.259816,0.192157,-0.082353,-0.984314,0.812500,0.937500], + [8.838835,-0.000014,-8.838835,0.701961,-0.011765,-0.717647,0.750000,0.750000], + [4.691625,-0.933230,-11.548495,0.364706,-0.074510,-0.929412,0.781250,0.875000], + [6.944627,-0.000011,-10.393371,0.545098,-0.003922,-0.835294,0.750000,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.781250,1.000000], + [2.391768,-0.475756,-12.259816,0.200000,-0.043137,-0.984314,0.781250,0.937500], + [4.783541,-0.000007,-11.548495,0.372549,-0.003922,-0.929412,0.750000,0.875000], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.750000,1.000000], + [2.438626,-0.000003,-12.259816,0.200000,-0.003922,-0.984314,0.750000,0.937500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.718750,1.000000], + [2.391769,0.475749,-12.259816,0.200000,0.035294,-0.984314,0.718750,0.937500], + [4.691628,0.933216,-11.548495,0.364706,0.066667,-0.929412,0.718750,0.875000], + [6.811190,1.354820,-10.393371,0.537255,0.105882,-0.843137,0.718750,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.687500,1.000000], + [2.252998,0.933219,-12.259816,0.184314,0.074510,-0.984314,0.687500,0.937500], + [4.419418,1.830576,-11.548495,0.341177,0.137255,-0.929412,0.687500,0.875000], + [6.416003,2.657585,-10.393371,0.505883,0.207843,-0.843137,0.687500,0.812500], + [8.669002,1.724358,-8.838835,0.686275,0.137255,-0.717647,0.718750,0.750000], + [8.166023,3.382464,-8.838835,0.647059,0.270588,-0.717647,0.687500,0.750000], + [10.193667,2.027631,-6.944627,0.811765,0.160784,-0.568627,0.718750,0.687012], + [9.602228,3.977357,-6.944627,0.756863,0.309804,-0.560784,0.687500,0.687012], + [11.326596,2.252983,-4.783541,0.898039,0.176471,-0.396078,0.718750,0.624512], + [10.669424,4.419403,-4.783541,0.850981,0.349020,-0.396078,0.687500,0.624512], + [12.024251,2.391753,-2.438627,0.960784,0.184314,-0.207843,0.718750,0.562012], + [11.326600,4.691613,-2.438627,0.905882,0.372549,-0.207843,0.687500,0.562012], + [12.259819,2.438611,0.000001,0.976471,0.192157,-0.011765,0.718750,0.500000], + [11.548501,4.783526,0.000001,0.921569,0.380392,-0.011765,0.687500,0.500000], + [12.024250,2.391753,2.438629,0.960784,0.184314,0.192157,0.718750,0.437500], + [11.326599,4.691612,2.438629,0.905882,0.372549,0.192157,0.687500,0.437500], + [11.326595,2.252982,4.783543,0.905882,0.176471,0.380392,0.718750,0.375000], + [10.669423,4.419402,4.783543,0.850981,0.349020,0.380392,0.687500,0.375000], + [10.193667,2.027631,6.944628,0.811765,0.152941,0.552941,0.718750,0.312500], + [9.602228,3.977357,6.944628,0.764706,0.309804,0.552941,0.687500,0.312500], + [8.669002,1.724358,8.838835,0.686275,0.129412,0.701961,0.718750,0.250000], + [8.166023,3.382464,8.838835,0.647059,0.262745,0.701961,0.687500,0.250000], + [6.811191,1.354820,10.393370,0.545098,0.098039,0.827451,0.718750,0.187500], + [6.416004,2.657585,10.393370,0.513726,0.207843,0.827451,0.687500,0.187500], + [4.691630,0.933216,11.548492,0.372549,0.066667,0.921569,0.718750,0.125000], + [4.419420,1.830577,11.548492,0.349020,0.137255,0.921569,0.687500,0.125000], + [2.253001,0.933220,12.259815,0.200000,0.074510,0.976471,0.687500,0.062500], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.687500,0.000000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.656250,0.000000], + [2.027648,1.354828,12.259815,0.176471,0.113726,0.976471,0.656250,0.062500], + [3.977374,2.657589,11.548492,0.317647,0.207843,0.921569,0.656250,0.125000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.625000,0.000000], + [1.724373,1.724370,12.259815,0.152941,0.145098,0.976471,0.625000,0.062500], + [5.774252,3.858222,10.393370,0.458824,0.301961,0.827451,0.656250,0.187500], + [3.382480,3.382472,11.548492,0.270588,0.262745,0.921569,0.625000,0.125000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.593750,0.000000], + [1.354832,2.027645,12.259815,0.121569,0.168628,0.976471,0.593750,0.062500], + [7.349229,4.910584,8.838835,0.584314,0.388235,0.701961,0.656250,0.250000], + [4.910600,4.910588,10.393370,0.388235,0.388235,0.827451,0.625000,0.187500], + [2.657599,3.977368,11.548492,0.207843,0.309804,0.921569,0.593750,0.125000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.562500,0.000000], + [0.933226,2.252999,12.259815,0.082353,0.192157,0.976471,0.562500,0.062500], + [8.641780,5.774236,6.944628,0.686275,0.458824,0.552941,0.656250,0.312500], + [6.250008,6.249992,8.838835,0.498039,0.498039,0.701961,0.625000,0.250000], + [3.858236,5.774243,10.393370,0.309804,0.458824,0.827451,0.593750,0.187500], + [9.602230,6.415987,4.783543,0.764706,0.505883,0.380392,0.656250,0.375000], + [7.349232,7.349214,6.944628,0.584314,0.584314,0.552941,0.625000,0.312500], + [10.193673,6.811175,2.438629,0.811765,0.537255,0.192157,0.656250,0.437500], + [8.166028,8.166009,4.783543,0.647059,0.647059,0.380392,0.625000,0.375000], + [4.910603,7.349217,8.838835,0.388235,0.584314,0.701961,0.593750,0.250000], + [5.774258,8.641766,6.944628,0.458824,0.686275,0.552941,0.593750,0.312500], + [10.393379,6.944614,0.000001,0.827451,0.552941,-0.011765,0.656250,0.500000], + [8.669009,8.668988,2.438629,0.686275,0.686275,0.192157,0.625000,0.437500], + [10.193674,6.811176,-2.438627,0.811765,0.545098,-0.207843,0.656250,0.562012], + [8.838846,8.838824,0.000001,0.701961,0.701961,-0.011765,0.625000,0.500000], + [6.416011,9.602215,4.783543,0.513726,0.764706,0.380392,0.593750,0.375000], + [6.811201,10.193657,2.438629,0.545098,0.811765,0.192157,0.593750,0.437500], + [9.602231,6.415987,-4.783541,0.764706,0.513726,-0.396078,0.656250,0.624512], + [8.669010,8.668989,-2.438627,0.686275,0.686275,-0.207843,0.625000,0.562012], + [8.641780,5.774236,-6.944627,0.686275,0.458824,-0.568627,0.656250,0.687012], + [8.166029,8.166009,-4.783541,0.647059,0.647059,-0.396078,0.625000,0.624512], + [6.944641,10.393363,0.000001,0.552941,0.827451,-0.011765,0.593750,0.500000], + [6.811202,10.193657,-2.438627,0.537255,0.811765,-0.207843,0.593750,0.562012], + [7.349229,4.910584,-8.838835,0.584314,0.388235,-0.717647,0.656250,0.750000], + [7.349232,7.349214,-6.944627,0.584314,0.584314,-0.568627,0.625000,0.687012], + [5.774252,3.858221,-10.393371,0.450980,0.301961,-0.835294,0.656250,0.812500], + [6.250008,6.249992,-8.838835,0.498039,0.498039,-0.717647,0.625000,0.750000], + [6.416011,9.602216,-4.783541,0.505883,0.764706,-0.396078,0.593750,0.624512], + [5.774258,8.641766,-6.944627,0.458824,0.686275,-0.568627,0.593750,0.687012], + [3.977372,2.657588,-11.548495,0.301961,0.200000,-0.929412,0.656250,0.875000], + [4.910599,4.910587,-10.393371,0.388235,0.388235,-0.843137,0.625000,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.656250,1.000000], + [2.027645,1.354826,-12.259816,0.160784,0.113726,-0.984314,0.656250,0.937500], + [4.910603,7.349217,-8.838835,0.388235,0.584314,-0.717647,0.593750,0.750000], + [3.382478,3.382470,-11.548495,0.254902,0.262745,-0.929412,0.625000,0.875000], + [3.858235,5.774242,-10.393371,0.301961,0.458824,-0.843137,0.593750,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.625000,1.000000], + [1.724371,1.724367,-12.259816,0.137255,0.145098,-0.984314,0.625000,0.937500], + [2.657598,3.977366,-11.548495,0.200000,0.309804,-0.929412,0.593750,0.875000], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.593750,1.000000], + [1.354831,2.027642,-12.259816,0.105882,0.168628,-0.984314,0.593750,0.937500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.562500,1.000000], + [0.933224,2.252996,-12.259816,0.066667,0.192157,-0.984314,0.562500,0.937500], + [1.830587,4.419414,-11.548495,0.129412,0.341177,-0.929412,0.562500,0.875000], + [2.657601,6.415997,-10.393371,0.200000,0.505883,-0.835294,0.562500,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.531250,1.000000], + [0.475755,2.391768,-12.259816,0.027451,0.200000,-0.984314,0.531250,0.937500], + [0.933227,4.691626,-11.548495,0.058824,0.364706,-0.929412,0.531250,0.875000], + [1.354837,6.811187,-10.393371,0.090196,0.537255,-0.835294,0.531250,0.812500], + [3.382485,8.166016,-8.838835,0.262745,0.647059,-0.717647,0.562500,0.750000], + [1.724380,8.668998,-8.838835,0.129412,0.686275,-0.717647,0.531250,0.750000], + [3.977381,9.602219,-6.944627,0.309804,0.764706,-0.568627,0.562500,0.687012], + [2.027657,10.193664,-6.944627,0.152941,0.811765,-0.568627,0.531250,0.687012], + [4.419429,10.669414,-4.783541,0.349020,0.850981,-0.396078,0.562500,0.624512], + [2.253011,11.326591,-4.783541,0.168628,0.898039,-0.388235,0.531250,0.624512], + [4.691641,11.326589,-2.438627,0.372549,0.905882,-0.207843,0.562500,0.562012], + [2.391784,12.024245,-2.438627,0.184314,0.960784,-0.207843,0.531250,0.562012], + [4.783556,11.548490,0.000001,0.380392,0.921569,-0.011765,0.562500,0.500000], + [2.438642,12.259814,0.000001,0.192157,0.976471,-0.011765,0.531250,0.500000], + [4.691641,11.326588,2.438629,0.372549,0.905882,0.192157,0.562500,0.437500], + [2.391784,12.024244,2.438629,0.184314,0.960784,0.192157,0.531250,0.437500], + [4.419429,10.669413,4.783543,0.349020,0.850981,0.380392,0.562500,0.375000], + [2.253011,11.326591,4.783543,0.176471,0.905882,0.380392,0.531250,0.375000], + [3.977381,9.602219,6.944628,0.317647,0.764706,0.552941,0.562500,0.312500], + [2.027657,10.193664,6.944628,0.160784,0.811765,0.552941,0.531250,0.312500], + [3.382485,8.166016,8.838835,0.270588,0.647059,0.701961,0.562500,0.250000], + [1.724380,8.668998,8.838835,0.137255,0.686275,0.701961,0.531250,0.250000], + [2.657601,6.415998,10.393370,0.207843,0.505883,0.827451,0.562500,0.187500], + [1.354837,6.811188,10.393370,0.105882,0.537255,0.827451,0.531250,0.187500], + [1.830588,4.419416,11.548492,0.145098,0.349020,0.921569,0.562500,0.125000], + [0.933228,4.691628,11.548492,0.074510,0.372549,0.921569,0.531250,0.125000], + [0.475755,2.391772,12.259815,0.043137,0.207843,0.976471,0.531250,0.062500], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.531250,0.000000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.500000,0.000000], + [0.000002,2.438630,12.259815,0.003922,0.207843,0.976471,0.500000,0.062500], + [0.000005,4.783544,11.548492,-0.011765,0.380392,0.921569,0.500000,0.125000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.468750,0.000000], + [-0.475751,2.391773,12.259815,-0.050980,0.207843,0.976471,0.468750,0.062500], + [0.000007,6.944629,10.393370,-0.011765,0.552941,0.827451,0.500000,0.187500], + [-0.933219,4.691630,11.548492,-0.082353,0.372549,0.921569,0.468750,0.125000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.437500,0.000000], + [-0.933221,2.253001,12.259815,-0.082353,0.192157,0.968628,0.437500,0.062500], + [0.000009,8.838836,8.838835,-0.011765,0.701961,0.701961,0.500000,0.250000], + [-1.354824,6.811191,10.393370,-0.113725,0.545098,0.827451,0.468750,0.187500], + [-1.830579,4.419420,11.548492,-0.152941,0.349020,0.921569,0.437500,0.125000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.406250,0.000000], + [-1.354828,2.027647,12.259815,-0.129412,0.176471,0.976471,0.406250,0.062500], + [0.000010,10.393372,6.944628,-0.011765,0.827451,0.552941,0.500000,0.312500], + [-1.724363,8.669002,8.838835,-0.145098,0.686275,0.701961,0.468750,0.250000], + [-2.657589,6.416003,10.393370,-0.223529,0.513726,0.827451,0.437500,0.187500], + [0.000011,11.548494,4.783543,-0.011765,0.921569,0.380392,0.500000,0.375000], + [-2.027637,10.193667,6.944628,-0.168627,0.811765,0.552941,0.468750,0.312500], + [0.000012,12.259816,2.438629,-0.011765,0.976471,0.192157,0.500000,0.437500], + [-2.252989,11.326595,4.783543,-0.192157,0.905882,0.380392,0.468750,0.375000], + [-3.382469,8.166022,8.838835,-0.278431,0.647059,0.701961,0.437500,0.250000], + [-3.977363,9.602227,6.944628,-0.325490,0.764706,0.552941,0.437500,0.312500], + [0.000012,12.500001,0.000001,-0.003922,0.992157,-0.003922,0.500000,0.500000], + [-2.391761,12.024249,2.438629,-0.200000,0.960784,0.192157,0.468750,0.437500], + [0.000012,12.259817,-2.438627,-0.011765,0.976471,-0.207843,0.500000,0.562012], + [-2.438618,12.259819,0.000001,-0.207843,0.976471,-0.011765,0.468750,0.500000], + [-4.419408,10.669421,4.783543,-0.364706,0.850981,0.380392,0.437500,0.375000], + [-4.691619,11.326597,2.438629,-0.380392,0.898039,0.184314,0.437500,0.437500], + [0.000011,11.548495,-4.783541,-0.003922,0.913726,-0.388235,0.500000,0.624512], + [-2.391761,12.024250,-2.438627,-0.192157,0.952941,-0.200000,0.468750,0.562012], + [0.000010,10.393372,-6.944627,-0.011765,0.827451,-0.568627,0.500000,0.687012], + [-2.252990,11.326596,-4.783541,-0.192157,0.898039,-0.396078,0.468750,0.624512], + [-4.783534,11.548499,0.000001,-0.388235,0.913726,-0.003922,0.437500,0.500000], + [-4.691619,11.326598,-2.438627,-0.380392,0.898039,-0.200000,0.437500,0.562012], + [0.000009,8.838836,-8.838835,-0.011765,0.701961,-0.717647,0.500000,0.750000], + [-2.027637,10.193667,-6.944627,-0.168627,0.803922,-0.560784,0.468750,0.687012], + [0.000007,6.944628,-10.393371,-0.003922,0.545098,-0.835294,0.500000,0.812500], + [-1.724363,8.669002,-8.838835,-0.152941,0.686275,-0.717647,0.468750,0.750000], + [-4.419409,10.669422,-4.783541,-0.356863,0.843137,-0.388235,0.437500,0.624512], + [-3.977363,9.602227,-6.944627,-0.325490,0.756863,-0.560784,0.437500,0.687012], + [0.000005,4.783541,-11.548495,-0.003922,0.372549,-0.929412,0.500000,0.875000], + [-1.354824,6.811190,-10.393371,-0.121569,0.537255,-0.843137,0.468750,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.500000,1.000000], + [0.000002,2.438627,-12.259816,-0.011765,0.200000,-0.984314,0.500000,0.937500], + [-3.382469,8.166022,-8.838835,-0.278431,0.639216,-0.709804,0.437500,0.750000], + [-0.933218,4.691628,-11.548495,-0.082353,0.364706,-0.929412,0.468750,0.875000], + [-2.657588,6.416002,-10.393371,-0.215686,0.498039,-0.835294,0.437500,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.468750,1.000000], + [-0.475750,2.391769,-12.259816,-0.050980,0.200000,-0.984314,0.468750,0.937500], + [-1.830578,4.419417,-11.548495,-0.152941,0.341177,-0.929412,0.437500,0.875000], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.437500,1.000000], + [-0.933220,2.252998,-12.259816,-0.090196,0.184314,-0.984314,0.437500,0.937500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.406250,1.000000], + [-1.354827,2.027645,-12.259816,-0.129412,0.160784,-0.984314,0.406250,0.937500], + [-2.657590,3.977371,-11.548495,-0.215686,0.301961,-0.929412,0.406250,0.875000], + [-3.858224,5.774250,-10.393371,-0.317647,0.450980,-0.835294,0.406250,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.375000,1.000000], + [-1.724368,1.724371,-12.259816,-0.160784,0.137255,-0.984314,0.375000,0.937500], + [-3.382472,3.382477,-11.548495,-0.278431,0.254902,-0.929412,0.375000,0.875000], + [-4.910590,4.910597,-10.393371,-0.396078,0.380392,-0.835294,0.375000,0.812500], + [-4.910588,7.349226,-8.838835,-0.396078,0.576471,-0.709804,0.406250,0.750000], + [-6.249996,6.250005,-8.838835,-0.505882,0.490196,-0.709804,0.375000,0.750000], + [-5.774241,8.641777,-6.944627,-0.466667,0.678432,-0.560784,0.406250,0.687012], + [-7.349218,7.349228,-6.944627,-0.592157,0.576471,-0.560784,0.375000,0.687012], + [-6.415993,9.602228,-4.783541,-0.521569,0.756863,-0.388235,0.406250,0.624512], + [-8.166014,8.166025,-4.783541,-0.662745,0.647059,-0.396078,0.375000,0.624512], + [-6.811182,10.193670,-2.438627,-0.552941,0.803922,-0.200000,0.406250,0.562012], + [-8.668994,8.669005,-2.438627,-0.701961,0.686275,-0.207843,0.375000,0.562012], + [-6.944621,10.393376,0.000001,-0.568627,0.827451,-0.011765,0.406250,0.500000], + [-8.838829,8.838841,0.000001,-0.717647,0.701961,-0.011765,0.375000,0.500000], + [-6.811181,10.193669,2.438629,-0.552941,0.811765,0.192157,0.406250,0.437500], + [-8.668993,8.669005,2.438629,-0.701961,0.686275,0.192157,0.375000,0.437500], + [-6.415992,9.602227,4.783543,-0.521569,0.764706,0.380392,0.406250,0.375000], + [-8.166013,8.166024,4.783543,-0.662745,0.647059,0.380392,0.375000,0.375000], + [-5.774241,8.641777,6.944628,-0.474510,0.686275,0.552941,0.406250,0.312500], + [-7.349218,7.349228,6.944628,-0.600000,0.584314,0.552941,0.375000,0.312500], + [-4.910588,7.349226,8.838835,-0.403922,0.584314,0.701961,0.406250,0.250000], + [-6.249996,6.250005,8.838835,-0.513725,0.498039,0.701961,0.375000,0.250000], + [-3.858225,5.774251,10.393370,-0.317647,0.458824,0.827451,0.406250,0.187500], + [-4.910591,4.910597,10.393370,-0.403922,0.388235,0.827451,0.375000,0.187500], + [-2.657591,3.977373,11.548492,-0.223529,0.317647,0.921569,0.406250,0.125000], + [-3.382474,3.382478,11.548492,-0.278431,0.270588,0.921569,0.375000,0.125000], + [-1.724370,1.724373,12.259815,-0.152941,0.145098,0.968628,0.375000,0.062500], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.375000,0.000000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.343506,0.000000], + [-2.027645,1.354832,12.259815,-0.184314,0.121569,0.976471,0.343506,0.062500], + [-3.977369,2.657597,11.548492,-0.325490,0.207843,0.921569,0.343506,0.125000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.312256,0.000000], + [-2.252999,0.933225,12.259815,-0.200000,0.074510,0.968628,0.312256,0.062500], + [-5.774245,3.858232,10.393370,-0.474510,0.309804,0.827451,0.343506,0.187500], + [-4.419416,1.830585,11.548492,-0.364706,0.145098,0.921569,0.312256,0.125000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.281006,0.000000], + [-2.391771,0.475754,12.259815,-0.215686,0.035294,0.968628,0.281006,0.062500], + [-7.349220,4.910598,8.838835,-0.600000,0.388235,0.701961,0.343506,0.250000], + [-6.415998,2.657598,10.393370,-0.521569,0.207843,0.827451,0.312256,0.187500], + [-4.691628,0.933225,11.548492,-0.388235,0.074510,0.921569,0.281006,0.125000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.249878,0.000000], + [-2.438629,0.000001,12.259815,-0.215686,-0.003922,0.968628,0.249878,0.062500], + [-8.641768,5.774253,6.944628,-0.701961,0.458824,0.552941,0.343506,0.312500], + [-8.166017,3.382480,8.838835,-0.662745,0.270588,0.701961,0.312256,0.250000], + [-6.811189,1.354833,10.393370,-0.552941,0.105882,0.827451,0.281006,0.187500], + [-9.602218,6.416005,4.783543,-0.772549,0.505883,0.372549,0.343506,0.375000], + [-9.602221,3.977376,6.944628,-0.772549,0.309804,0.545098,0.312256,0.312500], + [-10.193660,6.811195,2.438629,-0.819608,0.537255,0.184314,0.343506,0.437500], + [-10.669415,4.419423,4.783543,-0.858824,0.341177,0.372549,0.312256,0.375000], + [-8.668998,1.724375,8.838835,-0.701961,0.137255,0.701961,0.281006,0.250000], + [-10.193664,2.027651,6.944628,-0.819608,0.152941,0.545098,0.281006,0.312500], + [-10.393366,6.944634,0.000001,-0.835294,0.545098,-0.003922,0.343506,0.500000], + [-11.326590,4.691634,2.438629,-0.913725,0.364706,0.184314,0.312256,0.437500], + [-10.193661,6.811195,-2.438627,-0.819608,0.529412,-0.200000,0.343506,0.562012], + [-11.548491,4.783549,0.000001,-0.929412,0.372549,-0.003922,0.312256,0.500000], + [-11.326591,2.253005,4.783543,-0.913725,0.176471,0.380392,0.281006,0.375000], + [-12.024245,2.391777,2.438629,-0.968627,0.176471,0.184314,0.281006,0.437500], + [-9.602219,6.416006,-4.783541,-0.772549,0.498039,-0.388235,0.343506,0.624512], + [-11.326591,4.691634,-2.438627,-0.913725,0.364706,-0.200000,0.312256,0.562012], + [-8.641768,5.774253,-6.944627,-0.694118,0.450980,-0.560784,0.343506,0.687012], + [-10.669415,4.419423,-4.783541,-0.858824,0.341177,-0.388235,0.312256,0.624512], + [-12.259815,2.438635,0.000001,-0.984314,0.184314,-0.003922,0.281006,0.500000], + [-12.024246,2.391777,-2.438627,-0.968627,0.176471,-0.200000,0.281006,0.562012], + [-7.349220,4.910598,-8.838835,-0.592157,0.380392,-0.709804,0.343506,0.750000], + [-9.602221,3.977376,-6.944627,-0.772549,0.301961,-0.560784,0.312256,0.687012], + [-5.774244,3.858232,-10.393371,-0.466667,0.294118,-0.835294,0.343506,0.812500], + [-8.166017,3.382480,-8.838835,-0.654902,0.254902,-0.709804,0.312256,0.750000], + [-11.326592,2.253005,-4.783541,-0.913725,0.168628,-0.388235,0.281006,0.624512], + [-10.193664,2.027651,-6.944627,-0.819608,0.145098,-0.560784,0.281006,0.687012], + [-3.977367,2.657596,-11.548495,-0.325490,0.200000,-0.929412,0.343506,0.875000], + [-6.415998,2.657597,-10.393371,-0.521569,0.200000,-0.835294,0.312256,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.343506,1.000000], + [-2.027643,1.354830,-12.259816,-0.184314,0.105882,-0.984314,0.343506,0.937500], + [-8.668998,1.724375,-8.838835,-0.694118,0.121569,-0.709804,0.281006,0.750000], + [-4.419415,1.830585,-11.548495,-0.356863,0.129412,-0.929412,0.312256,0.875000], + [-6.811188,1.354833,-10.393371,-0.552941,0.090196,-0.835294,0.281006,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.312256,1.000000], + [-2.252996,0.933223,-12.259816,-0.207843,0.066667,-0.976471,0.312256,0.937500], + [-4.691626,0.933225,-11.548495,-0.380392,0.058824,-0.929412,0.281006,0.875000], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.281006,1.000000], + [-2.391768,0.475754,-12.259816,-0.215686,0.027451,-0.976471,0.281006,0.937500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.249878,1.000000], + [-2.438626,0.000001,-12.259816,-0.215686,-0.011765,-0.984314,0.249878,0.937500], + [-4.783541,0.000002,-11.548495,-0.388235,-0.003922,-0.929412,0.249878,0.875000], + [-6.944627,0.000003,-10.393371,-0.560784,-0.003922,-0.835294,0.249878,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.218628,1.000000], + [-2.391769,-0.475751,-12.259816,-0.215686,-0.050980,-0.976471,0.218628,0.937500], + [-4.691627,-0.933221,-11.548495,-0.380392,-0.082353,-0.929412,0.218628,0.875000], + [-6.811188,-1.354827,-10.393371,-0.545098,-0.113725,-0.835294,0.218628,0.812500], + [-8.838835,0.000003,-8.838835,-0.709804,-0.003922,-0.709804,0.249878,0.750000], + [-8.669000,-1.724368,-8.838835,-0.694118,-0.145098,-0.709804,0.218628,0.750000], + [-10.393371,0.000004,-6.944627,-0.835294,-0.003922,-0.560784,0.249878,0.687012], + [-10.193666,-2.027643,-6.944627,-0.819608,-0.168627,-0.560784,0.218628,0.687012], + [-11.548494,0.000004,-4.783541,-0.929412,-0.003922,-0.388235,0.249878,0.624512], + [-11.326593,-2.252996,-4.783541,-0.905882,-0.184314,-0.388235,0.218628,0.624512], + [-12.259816,0.000005,-2.438627,-0.984314,-0.003922,-0.200000,0.249878,0.562012], + [-12.024247,-2.391768,-2.438627,-0.968627,-0.192157,-0.200000,0.218628,0.562012], + [-12.500000,0.000005,0.000001,-1.000000,-0.003922,-0.003922,0.249878,0.500000], + [-12.259816,-2.438626,0.000001,-0.984314,-0.200000,-0.003922,0.218628,0.500000], + [-12.259815,0.000005,2.438629,-0.984314,-0.003922,0.184314,0.249878,0.437500], + [-12.024246,-2.391768,2.438629,-0.968627,-0.192157,0.184314,0.218628,0.437500], + [-11.548493,0.000004,4.783543,-0.929412,-0.003922,0.372549,0.249878,0.375000], + [-11.326592,-2.252996,4.783543,-0.913725,-0.184314,0.372549,0.218628,0.375000], + [-10.393371,0.000004,6.944628,-0.835294,-0.003922,0.545098,0.249878,0.312500], + [-10.193666,-2.027643,6.944628,-0.819608,-0.160784,0.545098,0.218628,0.312500], + [-8.838835,0.000003,8.838835,-0.717647,-0.011765,0.701961,0.249878,0.250000], + [-8.669000,-1.724368,8.838835,-0.701961,-0.145098,0.701961,0.218628,0.250000], + [-6.944628,0.000003,10.393370,-0.568627,-0.011765,0.827451,0.249878,0.187500], + [-6.811189,-1.354828,10.393370,-0.552941,-0.105882,0.819608,0.218628,0.187500], + [-4.783543,0.000002,11.548492,-0.388235,-0.003922,0.913726,0.249878,0.125000], + [-4.691629,-0.933221,11.548492,-0.388235,-0.082353,0.921569,0.218628,0.125000], + [-2.391772,-0.475752,12.259815,-0.215686,-0.043137,0.968628,0.218628,0.062500], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.218628,0.000000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.187500,0.000000], + [-2.253000,-0.933222,12.259815,-0.207843,-0.082353,0.968628,0.187500,0.062500], + [-4.419418,-1.830581,11.548492,-0.364706,-0.152941,0.921569,0.187500,0.125000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.156250,0.000000], + [-2.027646,-1.354829,12.259815,-0.184314,-0.121569,0.968628,0.156250,0.062500], + [-6.416000,-2.657593,10.393370,-0.521569,-0.215686,0.819608,0.187500,0.187500], + [-3.977371,-2.657593,11.548492,-0.325490,-0.215686,0.913726,0.156250,0.125000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.125000,0.000000], + [-1.724371,-1.724371,12.259815,-0.160784,-0.152941,0.968628,0.125000,0.062500], + [-8.166019,-3.382474,8.838835,-0.662745,-0.278431,0.701961,0.187500,0.250000], + [-5.774248,-3.858228,10.393370,-0.474510,-0.317647,0.827451,0.156250,0.187500], + [-3.382476,-3.382475,11.548492,-0.278431,-0.270588,0.913726,0.125000,0.125000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.093750,0.000000], + [-1.354830,-2.027646,12.259815,-0.129412,-0.176471,0.968628,0.093750,0.062500], + [-9.602223,-3.977369,6.944628,-0.772549,-0.317647,0.545098,0.187500,0.312500], + [-7.349223,-4.910593,8.838835,-0.592157,-0.396078,0.694118,0.156250,0.250000], + [-4.910594,-4.910593,10.393370,-0.403922,-0.403922,0.827451,0.125000,0.187500], + [-10.669417,-4.419415,4.783543,-0.858824,-0.356863,0.372549,0.187500,0.375000], + [-8.641772,-5.774246,6.944628,-0.694118,-0.466667,0.545098,0.156250,0.312500], + [-11.326593,-4.691626,2.438629,-0.913725,-0.380392,0.184314,0.187500,0.437500], + [-9.602221,-6.415998,4.783543,-0.772549,-0.513725,0.372549,0.156250,0.375000], + [-6.250000,-6.250000,8.838835,-0.505882,-0.505882,0.694118,0.125000,0.250000], + [-7.349223,-7.349222,6.944628,-0.592157,-0.592157,0.545098,0.125000,0.312500], + [-11.548495,-4.783540,0.000001,-0.929412,-0.388235,-0.003922,0.187500,0.500000], + [-10.193665,-6.811187,2.438629,-0.819608,-0.545098,0.184314,0.156250,0.437500], + [-11.326594,-4.691626,-2.438627,-0.905882,-0.380392,-0.200000,0.187500,0.562012], + [-10.393371,-6.944627,0.000001,-0.835294,-0.560784,-0.003922,0.156250,0.500000], + [-8.166018,-8.166017,4.783543,-0.654902,-0.654902,0.372549,0.125000,0.375000], + [-8.668999,-8.668998,2.438629,-0.694118,-0.694118,0.184314,0.125000,0.437500], + [-10.669418,-4.419415,-4.783541,-0.858824,-0.356863,-0.388235,0.187500,0.624512], + [-10.193666,-6.811188,-2.438627,-0.819608,-0.552941,-0.200000,0.156250,0.562012], + [-9.602223,-3.977369,-6.944627,-0.772549,-0.325490,-0.560784,0.187500,0.687012], + [-9.602222,-6.415998,-4.783541,-0.772549,-0.521569,-0.388235,0.156250,0.624512], + [-8.838835,-8.838834,0.000001,-0.709804,-0.709804,-0.003922,0.125000,0.500000], + [-8.668999,-8.668998,-2.438627,-0.694118,-0.694118,-0.200000,0.125000,0.562012], + [-8.166019,-3.382474,-8.838835,-0.654902,-0.278431,-0.709804,0.187500,0.750000], + [-8.641772,-5.774246,-6.944627,-0.694118,-0.466667,-0.560784,0.156250,0.687012], + [-6.415999,-2.657592,-10.393371,-0.513725,-0.215686,-0.835294,0.187500,0.812500], + [-7.349223,-4.910593,-8.838835,-0.592157,-0.396078,-0.709804,0.156250,0.750000], + [-8.166018,-8.166018,-4.783541,-0.654902,-0.654902,-0.388235,0.125000,0.624512], + [-7.349223,-7.349222,-6.944627,-0.592157,-0.592157,-0.560784,0.125000,0.687012], + [-4.419416,-1.830580,-11.548495,-0.356863,-0.152941,-0.929412,0.187500,0.875000], + [-5.774247,-3.858227,-10.393371,-0.466667,-0.317647,-0.835294,0.156250,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.187500,1.000000], + [-2.252997,-0.933221,-12.259816,-0.200000,-0.090196,-0.976471,0.187500,0.937500], + [-6.250000,-6.250000,-8.838835,-0.505882,-0.505882,-0.709804,0.125000,0.750000], + [-3.977369,-2.657592,-11.548495,-0.317647,-0.215686,-0.929412,0.156250,0.875000], + [-4.910593,-4.910593,-10.393371,-0.396078,-0.396078,-0.835294,0.125000,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.156250,1.000000], + [-2.027643,-1.354827,-12.259816,-0.176471,-0.129412,-0.976471,0.156250,0.937500], + [-3.382474,-3.382473,-11.548495,-0.270588,-0.278431,-0.929412,0.125000,0.875000], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.125000,1.000000], + [-1.724369,-1.724368,-12.259816,-0.152941,-0.160784,-0.976471,0.125000,0.937500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.093750,1.000000], + [-1.354828,-2.027643,-12.259816,-0.121569,-0.184314,-0.976471,0.093750,0.937500], + [-2.657593,-3.977369,-11.548495,-0.215686,-0.325490,-0.929412,0.093750,0.875000], + [-3.858228,-5.774246,-10.393371,-0.309804,-0.466667,-0.835294,0.093750,0.812500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.062500,1.000000], + [-0.933222,-2.252996,-12.259816,-0.082353,-0.207843,-0.976471,0.062500,0.937500], + [-1.830582,-4.419415,-11.548495,-0.145098,-0.356863,-0.929412,0.062500,0.875000], + [-2.657593,-6.415999,-10.393371,-0.215686,-0.521569,-0.835294,0.062500,0.812500], + [-4.910593,-7.349222,-8.838835,-0.396078,-0.592157,-0.709804,0.093750,0.750000], + [-3.382475,-8.166018,-8.838835,-0.270588,-0.654902,-0.709804,0.062500,0.750000], + [-5.774247,-8.641771,-6.944627,-0.466667,-0.694118,-0.560784,0.093750,0.687012], + [-3.977370,-9.602221,-6.944627,-0.317647,-0.772549,-0.560784,0.062500,0.687012], + [-6.415999,-9.602221,-4.783541,-0.513725,-0.772549,-0.388235,0.093750,0.624512], + [-4.419417,-10.669417,-4.783541,-0.356863,-0.858824,-0.388235,0.062500,0.624512], + [-6.811188,-10.193665,-2.438627,-0.545098,-0.819608,-0.200000,0.093750,0.562012], + [-4.691628,-11.326592,-2.438627,-0.380392,-0.905882,-0.200000,0.062500,0.562012], + [-6.944627,-10.393370,0.000001,-0.560784,-0.835294,-0.003922,0.093750,0.500000], + [-4.783543,-11.548493,0.000001,-0.388235,-0.929412,-0.003922,0.062500,0.500000], + [-6.811188,-10.193664,2.438629,-0.552941,-0.819608,0.184314,0.093750,0.437500], + [-4.691628,-11.326591,2.438629,-0.380392,-0.913725,0.184314,0.062500,0.437500], + [-6.415998,-9.602221,4.783543,-0.521569,-0.772549,0.372549,0.093750,0.375000], + [-4.419417,-10.669416,4.783543,-0.356863,-0.858824,0.372549,0.062500,0.375000], + [-5.774247,-8.641771,6.944628,-0.466667,-0.694118,0.545098,0.093750,0.312500], + [-3.977370,-9.602221,6.944628,-0.325490,-0.772549,0.545098,0.062500,0.312500], + [-4.910593,-7.349222,8.838835,-0.396078,-0.592157,0.694118,0.093750,0.250000], + [-3.382475,-8.166018,8.838835,-0.286274,-0.662745,0.701961,0.062500,0.250000], + [-3.858228,-5.774247,10.393370,-0.317647,-0.466667,0.819608,0.093750,0.187500], + [-2.657594,-6.415999,10.393370,-0.223529,-0.521569,0.827451,0.062500,0.187500], + [-2.657594,-3.977371,11.548492,-0.223529,-0.325490,0.921569,0.093750,0.125000], + [-1.830582,-4.419417,11.548492,-0.152941,-0.356863,0.913726,0.062500,0.125000], + [-0.933223,-2.252999,12.259815,-0.090196,-0.200000,0.968628,0.062500,0.062500], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.062500,0.000000], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.031250,0.000000], + [-0.475753,-2.391771,12.259815,-0.050980,-0.215686,0.968628,0.031250,0.062500], + [0.000000,0.000001,12.500000,-0.003922,-0.003922,0.992157,0.000000,0.000000], + [-0.000000,-2.438629,12.259815,-0.011765,-0.215686,0.968628,0.000000,0.062500], + [-0.933223,-4.691628,11.548492,-0.082353,-0.380392,0.913726,0.031250,0.125000], + [-0.000000,-4.783543,11.548492,-0.003922,-0.388235,0.913726,0.000000,0.125000], + [-1.354830,-6.811189,10.393370,-0.121569,-0.552941,0.827451,0.031250,0.187500], + [-0.000000,-6.944628,10.393370,-0.011765,-0.568627,0.827451,0.000000,0.187500], + [-1.724371,-8.668998,8.838835,-0.152941,-0.701961,0.701961,0.031250,0.250000], + [-0.000000,-8.838834,8.838835,-0.011765,-0.717647,0.701961,0.000000,0.250000], + [-2.027646,-10.193664,6.944628,-0.168627,-0.819608,0.545098,0.031250,0.312500], + [-0.000000,-10.393370,6.944628,-0.003922,-0.835294,0.545098,0.000000,0.312500], + [-2.252999,-11.326591,4.783543,-0.192157,-0.913725,0.380392,0.031250,0.375000], + [-0.000001,-11.548492,4.783543,-0.003922,-0.929412,0.372549,0.000000,0.375000], + [-2.391771,-12.024245,2.438629,-0.192157,-0.968627,0.184314,0.031250,0.437500], + [-0.000001,-12.259814,2.438629,-0.003922,-0.984314,0.184314,0.000000,0.437500], + [-2.438629,-12.259814,0.000001,-0.200000,-0.984314,-0.003922,0.031250,0.500000], + [-0.000001,-12.499999,0.000001,-0.003922,-1.000000,-0.003922,0.000000,0.500000], + [-2.391772,-12.024246,-2.438627,-0.192157,-0.968627,-0.200000,0.031250,0.562012], + [-0.000001,-12.259815,-2.438627,-0.003922,-0.984314,-0.200000,0.000000,0.562012], + [-2.253000,-11.326591,-4.783541,-0.184314,-0.905882,-0.388235,0.031250,0.624512], + [-0.000001,-11.548493,-4.783541,-0.003922,-0.929412,-0.388235,0.000000,0.624512], + [-2.027646,-10.193664,-6.944627,-0.160784,-0.819608,-0.560784,0.031250,0.687012], + [-0.000000,-10.393370,-6.944627,-0.003922,-0.835294,-0.560784,0.000000,0.687012], + [-1.724371,-8.668998,-8.838835,-0.137255,-0.694118,-0.709804,0.031250,0.750000], + [-0.000000,-8.838834,-8.838835,-0.003922,-0.709804,-0.709804,0.000000,0.750000], + [-1.354830,-6.811188,-10.393371,-0.105882,-0.552941,-0.835294,0.031250,0.812500], + [-0.000000,-6.944627,-10.393371,-0.003922,-0.560784,-0.835294,0.000000,0.812500], + [-0.933223,-4.691626,-11.548495,-0.074510,-0.380392,-0.929412,0.031250,0.875000], + [-0.000000,-4.783540,-11.548495,-0.003922,-0.388235,-0.929412,0.000000,0.875000], + [-0.475752,-2.391768,-12.259816,-0.043137,-0.215686,-0.976471,0.031250,0.937500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.031250,1.000000], + [-0.000000,-2.438626,-12.259816,-0.003922,-0.215686,-0.984314,0.000000,0.937500], + [0.000000,0.000001,-12.500000,-0.003922,-0.003922,-1.000000,0.000000,1.000000] + ], + "indices":[ + [0,1,2], + [1,3,2], + [1,4,3], + [4,5,3], + [6,7,1], + [7,4,1], + [4,8,5], + [8,9,5], + [7,10,4], + [10,8,4], + [11,12,7], + [12,10,7], + [8,13,9], + [13,14,9], + [10,15,8], + [15,13,8], + [12,16,10], + [16,15,10], + [17,18,12], + [18,16,12], + [13,19,14], + [19,20,14], + [15,21,13], + [21,19,13], + [16,22,15], + [22,21,15], + [19,23,20], + [23,24,20], + [21,25,19], + [25,23,19], + [23,26,24], + [26,27,24], + [25,28,23], + [28,26,23], + [29,25,21], + [22,29,21], + [30,28,25], + [29,30,25], + [26,31,27], + [31,32,27], + [28,33,26], + [33,31,26], + [31,34,32], + [34,35,32], + [33,36,31], + [36,34,31], + [37,33,28], + [30,37,28], + [38,36,33], + [37,38,33], + [34,39,35], + [39,40,35], + [36,41,34], + [41,39,34], + [39,42,40], + [42,43,40], + [41,44,39], + [44,42,39], + [45,41,36], + [38,45,36], + [46,44,41], + [45,46,41], + [42,47,43], + [47,48,43], + [44,49,42], + [49,47,42], + [47,50,48], + [50,51,48], + [49,52,47], + [52,50,47], + [53,49,44], + [46,53,44], + [54,52,49], + [53,54,49], + [50,55,51], + [55,56,51], + [52,57,50], + [57,55,50], + [58,56,59], + [55,59,56], + [60,57,52], + [54,60,52], + [57,61,55], + [61,59,55], + [60,62,57], + [62,61,57], + [63,59,64], + [61,64,59], + [62,65,61], + [65,64,61], + [66,64,67], + [65,67,64], + [68,67,69], + [70,67,65], + [70,69,67], + [71,65,62], + [71,70,65], + [72,69,73], + [74,69,70], + [74,73,69], + [75,70,71], + [75,74,70], + [76,71,62], + [76,62,60], + [77,75,71], + [77,71,76], + [78,76,60], + [78,60,54], + [79,77,76], + [79,76,78], + [80,78,54], + [80,54,53], + [81,79,78], + [81,78,80], + [82,80,53], + [82,53,46], + [83,81,80], + [83,80,82], + [84,82,46], + [84,46,45], + [85,83,82], + [85,82,84], + [86,84,45], + [86,45,38], + [87,85,84], + [87,84,86], + [88,86,38], + [88,38,37], + [89,87,86], + [89,86,88], + [90,88,37], + [90,37,30], + [91,89,88], + [91,88,90], + [92,90,30], + [92,30,29], + [93,91,90], + [93,90,92], + [94,92,29], + [94,29,22], + [95,93,92], + [95,92,94], + [96,94,22], + [96,22,16], + [18,96,16], + [97,94,96], + [97,95,94], + [98,96,18], + [99,98,18], + [98,97,96], + [100,101,98], + [101,97,98], + [102,95,97], + [101,102,97], + [103,104,101], + [104,102,101], + [102,105,95], + [105,93,95], + [104,106,102], + [106,105,102], + [107,108,104], + [108,106,104], + [105,109,93], + [109,91,93], + [106,110,105], + [110,109,105], + [108,111,106], + [111,110,106], + [112,113,108], + [113,111,108], + [109,114,91], + [114,89,91], + [110,115,109], + [115,114,109], + [111,116,110], + [116,115,110], + [114,117,89], + [117,87,89], + [115,118,114], + [118,117,114], + [117,119,87], + [119,85,87], + [118,120,117], + [120,119,117], + [121,118,115], + [116,121,115], + [122,120,118], + [121,122,118], + [119,123,85], + [123,83,85], + [120,124,119], + [124,123,119], + [123,125,83], + [125,81,83], + [124,126,123], + [126,125,123], + [127,124,120], + [122,127,120], + [128,126,124], + [127,128,124], + [125,129,81], + [129,79,81], + [126,130,125], + [130,129,125], + [129,131,79], + [131,77,79], + [130,132,129], + [132,131,129], + [133,130,126], + [128,133,126], + [134,132,130], + [133,134,130], + [131,135,77], + [135,75,77], + [132,136,131], + [136,135,131], + [135,137,75], + [137,74,75], + [136,138,135], + [138,137,135], + [139,136,132], + [134,139,132], + [140,138,136], + [139,140,136], + [137,141,74], + [141,73,74], + [138,142,137], + [142,141,137], + [143,73,144], + [141,144,73], + [145,142,138], + [140,145,138], + [142,146,141], + [146,144,141], + [145,147,142], + [147,146,142], + [148,144,149], + [146,149,144], + [147,150,146], + [150,149,146], + [151,149,152], + [150,152,149], + [153,152,154], + [155,152,150], + [155,154,152], + [156,150,147], + [156,155,150], + [157,154,158], + [159,154,155], + [159,158,154], + [160,155,156], + [160,159,155], + [161,156,147], + [161,147,145], + [162,160,156], + [162,156,161], + [163,161,145], + [163,145,140], + [164,162,161], + [164,161,163], + [165,163,140], + [165,140,139], + [166,164,163], + [166,163,165], + [167,165,139], + [167,139,134], + [168,166,165], + [168,165,167], + [169,167,134], + [169,134,133], + [170,168,167], + [170,167,169], + [171,169,133], + [171,133,128], + [172,170,169], + [172,169,171], + [173,171,128], + [173,128,127], + [174,172,171], + [174,171,173], + [175,173,127], + [175,127,122], + [176,174,173], + [176,173,175], + [177,175,122], + [177,122,121], + [178,176,175], + [178,175,177], + [179,177,121], + [179,121,116], + [180,178,177], + [180,177,179], + [181,179,116], + [181,116,111], + [113,181,111], + [182,179,181], + [182,180,179], + [183,181,113], + [184,183,113], + [183,182,181], + [185,186,183], + [186,182,183], + [187,180,182], + [186,187,182], + [188,189,186], + [189,187,186], + [187,190,180], + [190,178,180], + [189,191,187], + [191,190,187], + [192,193,189], + [193,191,189], + [190,194,178], + [194,176,178], + [191,195,190], + [195,194,190], + [193,196,191], + [196,195,191], + [197,198,193], + [198,196,193], + [194,199,176], + [199,174,176], + [195,200,194], + [200,199,194], + [196,201,195], + [201,200,195], + [199,202,174], + [202,172,174], + [200,203,199], + [203,202,199], + [202,204,172], + [204,170,172], + [203,205,202], + [205,204,202], + [206,203,200], + [201,206,200], + [207,205,203], + [206,207,203], + [204,208,170], + [208,168,170], + [205,209,204], + [209,208,204], + [208,210,168], + [210,166,168], + [209,211,208], + [211,210,208], + [212,209,205], + [207,212,205], + [213,211,209], + [212,213,209], + [210,214,166], + [214,164,166], + [211,215,210], + [215,214,210], + [214,216,164], + [216,162,164], + [215,217,214], + [217,216,214], + [218,215,211], + [213,218,211], + [219,217,215], + [218,219,215], + [216,220,162], + [220,160,162], + [217,221,216], + [221,220,216], + [220,222,160], + [222,159,160], + [221,223,220], + [223,222,220], + [224,221,217], + [219,224,217], + [225,223,221], + [224,225,221], + [222,226,159], + [226,158,159], + [223,227,222], + [227,226,222], + [228,158,229], + [226,229,158], + [230,227,223], + [225,230,223], + [227,231,226], + [231,229,226], + [230,232,227], + [232,231,227], + [233,229,234], + [231,234,229], + [232,235,231], + [235,234,231], + [236,234,237], + [235,237,234], + [238,237,239], + [240,237,235], + [240,239,237], + [241,235,232], + [241,240,235], + [242,239,243], + [244,239,240], + [244,243,239], + [245,240,241], + [245,244,240], + [246,241,232], + [246,232,230], + [247,245,241], + [247,241,246], + [248,246,230], + [248,230,225], + [249,247,246], + [249,246,248], + [250,248,225], + [250,225,224], + [251,249,248], + [251,248,250], + [252,250,224], + [252,224,219], + [253,251,250], + [253,250,252], + [254,252,219], + [254,219,218], + [255,253,252], + [255,252,254], + [256,254,218], + [256,218,213], + [257,255,254], + [257,254,256], + [258,256,213], + [258,213,212], + [259,257,256], + [259,256,258], + [260,258,212], + [260,212,207], + [261,259,258], + [261,258,260], + [262,260,207], + [262,207,206], + [263,261,260], + [263,260,262], + [264,262,206], + [264,206,201], + [265,263,262], + [265,262,264], + [266,264,201], + [266,201,196], + [198,266,196], + [267,264,266], + [267,265,264], + [268,266,198], + [269,268,198], + [268,267,266], + [270,271,268], + [271,267,268], + [272,265,267], + [271,272,267], + [273,274,271], + [274,272,271], + [272,275,265], + [275,263,265], + [274,276,272], + [276,275,272], + [277,278,274], + [278,276,274], + [275,279,263], + [279,261,263], + [276,280,275], + [280,279,275], + [278,281,276], + [281,280,276], + [282,283,278], + [283,281,278], + [279,284,261], + [284,259,261], + [280,285,279], + [285,284,279], + [281,286,280], + [286,285,280], + [284,287,259], + [287,257,259], + [285,288,284], + [288,287,284], + [287,289,257], + [289,255,257], + [288,290,287], + [290,289,287], + [291,288,285], + [286,291,285], + [292,290,288], + [291,292,288], + [289,293,255], + [293,253,255], + [290,294,289], + [294,293,289], + [293,295,253], + [295,251,253], + [294,296,293], + [296,295,293], + [297,294,290], + [292,297,290], + [298,296,294], + [297,298,294], + [295,299,251], + [299,249,251], + [296,300,295], + [300,299,295], + [299,301,249], + [301,247,249], + [300,302,299], + [302,301,299], + [303,300,296], + [298,303,296], + [304,302,300], + [303,304,300], + [301,305,247], + [305,245,247], + [302,306,301], + [306,305,301], + [305,307,245], + [307,244,245], + [306,308,305], + [308,307,305], + [309,306,302], + [304,309,302], + [310,308,306], + [309,310,306], + [307,311,244], + [311,243,244], + [308,312,307], + [312,311,307], + [313,243,314], + [311,314,243], + [315,312,308], + [310,315,308], + [312,316,311], + [316,314,311], + [315,317,312], + [317,316,312], + [318,314,319], + [316,319,314], + [317,320,316], + [320,319,316], + [321,319,322], + [320,322,319], + [323,322,324], + [325,322,320], + [325,324,322], + [326,320,317], + [326,325,320], + [327,324,328], + [329,324,325], + [329,328,324], + [330,325,326], + [330,329,325], + [331,326,317], + [331,317,315], + [332,330,326], + [332,326,331], + [333,331,315], + [333,315,310], + [334,332,331], + [334,331,333], + [335,333,310], + [335,310,309], + [336,334,333], + [336,333,335], + [337,335,309], + [337,309,304], + [338,336,335], + [338,335,337], + [339,337,304], + [339,304,303], + [340,338,337], + [340,337,339], + [341,339,303], + [341,303,298], + [342,340,339], + [342,339,341], + [343,341,298], + [343,298,297], + [344,342,341], + [344,341,343], + [345,343,297], + [345,297,292], + [346,344,343], + [346,343,345], + [347,345,292], + [347,292,291], + [348,346,345], + [348,345,347], + [349,347,291], + [349,291,286], + [350,348,347], + [350,347,349], + [351,349,286], + [351,286,281], + [283,351,281], + [352,349,351], + [352,350,349], + [353,351,283], + [354,353,283], + [353,352,351], + [355,356,353], + [356,352,353], + [357,350,352], + [356,357,352], + [358,359,356], + [359,357,356], + [357,360,350], + [360,348,350], + [359,361,357], + [361,360,357], + [362,363,359], + [363,361,359], + [360,364,348], + [364,346,348], + [361,365,360], + [365,364,360], + [363,366,361], + [366,365,361], + [367,368,363], + [368,366,363], + [364,369,346], + [369,344,346], + [365,370,364], + [370,369,364], + [366,371,365], + [371,370,365], + [369,372,344], + [372,342,344], + [370,373,369], + [373,372,369], + [372,374,342], + [374,340,342], + [373,375,372], + [375,374,372], + [376,373,370], + [371,376,370], + [377,375,373], + [376,377,373], + [374,378,340], + [378,338,340], + [375,379,374], + [379,378,374], + [378,380,338], + [380,336,338], + [379,381,378], + [381,380,378], + [382,379,375], + [377,382,375], + [383,381,379], + [382,383,379], + [380,384,336], + [384,334,336], + [381,385,380], + [385,384,380], + [384,386,334], + [386,332,334], + [385,387,384], + [387,386,384], + [388,385,381], + [383,388,381], + [389,387,385], + [388,389,385], + [386,390,332], + [390,330,332], + [387,391,386], + [391,390,386], + [390,392,330], + [392,329,330], + [391,393,390], + [393,392,390], + [394,391,387], + [389,394,387], + [395,393,391], + [394,395,391], + [392,396,329], + [396,328,329], + [393,397,392], + [397,396,392], + [398,328,399], + [396,399,328], + [400,397,393], + [395,400,393], + [397,401,396], + [401,399,396], + [400,402,397], + [402,401,397], + [403,399,404], + [401,404,399], + [402,405,401], + [405,404,401], + [406,404,407], + [405,407,404], + [408,407,409], + [410,407,405], + [410,409,407], + [411,405,402], + [411,410,405], + [412,409,413], + [414,409,410], + [414,413,409], + [415,410,411], + [415,414,410], + [416,411,402], + [416,402,400], + [417,415,411], + [417,411,416], + [418,416,400], + [418,400,395], + [419,417,416], + [419,416,418], + [420,418,395], + [420,395,394], + [421,419,418], + [421,418,420], + [422,420,394], + [422,394,389], + [423,421,420], + [423,420,422], + [424,422,389], + [424,389,388], + [425,423,422], + [425,422,424], + [426,424,388], + [426,388,383], + [427,425,424], + [427,424,426], + [428,426,383], + [428,383,382], + [429,427,426], + [429,426,428], + [430,428,382], + [430,382,377], + [431,429,428], + [431,428,430], + [432,430,377], + [432,377,376], + [433,431,430], + [433,430,432], + [434,432,376], + [434,376,371], + [435,433,432], + [435,432,434], + [436,434,371], + [436,371,366], + [368,436,366], + [437,434,436], + [437,435,434], + [438,436,368], + [439,438,368], + [438,437,436], + [440,441,438], + [441,437,438], + [442,435,437], + [441,442,437], + [443,444,441], + [444,442,441], + [442,445,435], + [445,433,435], + [444,446,442], + [446,445,442], + [447,448,444], + [448,446,444], + [445,449,433], + [449,431,433], + [446,450,445], + [450,449,445], + [448,451,446], + [451,450,446], + [452,453,448], + [453,451,448], + [449,454,431], + [454,429,431], + [450,455,449], + [455,454,449], + [451,456,450], + [456,455,450], + [454,457,429], + [457,427,429], + [455,458,454], + [458,457,454], + [457,459,427], + [459,425,427], + [458,460,457], + [460,459,457], + [461,458,455], + [456,461,455], + [462,460,458], + [461,462,458], + [459,463,425], + [463,423,425], + [460,464,459], + [464,463,459], + [463,465,423], + [465,421,423], + [464,466,463], + [466,465,463], + [467,464,460], + [462,467,460], + [468,466,464], + [467,468,464], + [465,469,421], + [469,419,421], + [466,470,465], + [470,469,465], + [469,471,419], + [471,417,419], + [470,472,469], + [472,471,469], + [473,470,466], + [468,473,466], + [474,472,470], + [473,474,470], + [471,475,417], + [475,415,417], + [472,476,471], + [476,475,471], + [475,477,415], + [477,414,415], + [476,478,475], + [478,477,475], + [479,476,472], + [474,479,472], + [480,478,476], + [479,480,476], + [477,481,414], + [481,413,414], + [478,482,477], + [482,481,477], + [483,413,484], + [481,484,413], + [485,482,478], + [480,485,478], + [482,486,481], + [486,484,481], + [485,487,482], + [487,486,482], + [488,484,489], + [486,489,484], + [487,490,486], + [490,489,486], + [491,489,492], + [490,492,489], + [493,492,494], + [495,492,490], + [495,494,492], + [496,490,487], + [496,495,490], + [497,494,498], + [499,494,495], + [499,498,494], + [500,495,496], + [500,499,495], + [501,496,487], + [501,487,485], + [502,500,496], + [502,496,501], + [503,501,485], + [503,485,480], + [504,502,501], + [504,501,503], + [505,503,480], + [505,480,479], + [506,504,503], + [506,503,505], + [507,505,479], + [507,479,474], + [508,506,505], + [508,505,507], + [509,507,474], + [509,474,473], + [510,508,507], + [510,507,509], + [511,509,473], + [511,473,468], + [512,510,509], + [512,509,511], + [513,511,468], + [513,468,467], + [514,512,511], + [514,511,513], + [515,513,467], + [515,467,462], + [516,514,513], + [516,513,515], + [517,515,462], + [517,462,461], + [518,516,515], + [518,515,517], + [519,517,461], + [519,461,456], + [520,518,517], + [520,517,519], + [521,519,456], + [521,456,451], + [453,521,451], + [522,519,521], + [522,520,519], + [523,521,453], + [524,523,453], + [523,522,521], + [525,526,523], + [526,522,523], + [527,528,526], + [526,529,522], + [528,529,526], + [529,520,522], + [528,530,529], + [529,531,520], + [530,531,529], + [531,518,520], + [530,532,531], + [531,533,518], + [532,533,531], + [533,516,518], + [532,534,533], + [533,535,516], + [534,535,533], + [535,514,516], + [534,536,535], + [535,537,514], + [536,537,535], + [537,512,514], + [536,538,537], + [537,539,512], + [538,539,537], + [539,510,512], + [538,540,539], + [539,541,510], + [540,541,539], + [541,508,510], + [540,542,541], + [541,543,508], + [542,543,541], + [543,506,508], + [542,544,543], + [543,545,506], + [544,545,543], + [545,504,506], + [544,546,545], + [545,547,504], + [546,547,545], + [547,502,504], + [546,548,547], + [547,549,502], + [548,549,547], + [549,500,502], + [548,550,549], + [549,551,500], + [550,551,549], + [551,499,500], + [550,552,551], + [551,553,499], + [552,553,551], + [553,498,499], + [552,554,553], + [553,555,498], + [554,555,553], + [556,498,555], + [554,557,555], + [558,555,557] + ] +} diff --git a/Chapter06/Assets/Sphere.png b/Chapter06/Assets/Sphere.png new file mode 100644 index 00000000..1378cbe5 Binary files /dev/null and b/Chapter06/Assets/Sphere.png differ diff --git a/Chapter06/CameraActor.cpp b/Chapter06/CameraActor.cpp new file mode 100644 index 00000000..5338b1bf --- /dev/null +++ b/Chapter06/CameraActor.cpp @@ -0,0 +1,58 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#include "CameraActor.h" +#include "MoveComponent.h" +#include "SDL/SDL_scancode.h" +#include "Renderer.h" +#include "Game.h" + +CameraActor::CameraActor(Game* game) + :Actor(game) +{ + mMoveComp = new MoveComponent(this); +} + +void CameraActor::UpdateActor(float deltaTime) +{ + Actor::UpdateActor(deltaTime); + + // Compute new camera from this actor + Vector3 cameraPos = GetPosition(); + Vector3 target = GetPosition() + GetForward() * 100.0f; + Vector3 up = Vector3::UnitZ; + + Matrix4 view = Matrix4::CreateLookAt(cameraPos, target, up); + GetGame()->GetRenderer()->SetViewMatrix(view); +} + +void CameraActor::ActorInput(const uint8_t* keys) +{ + float forwardSpeed = 0.0f; + float angularSpeed = 0.0f; + // wasd movement + if (keys[SDL_SCANCODE_W]) + { + forwardSpeed += 300.0f; + } + if (keys[SDL_SCANCODE_S]) + { + forwardSpeed -= 300.0f; + } + if (keys[SDL_SCANCODE_A]) + { + angularSpeed -= Math::TwoPi; + } + if (keys[SDL_SCANCODE_D]) + { + angularSpeed += Math::TwoPi; + } + + mMoveComp->SetForwardSpeed(forwardSpeed); + mMoveComp->SetAngularSpeed(angularSpeed); +} diff --git a/Chapter06/CameraActor.h b/Chapter06/CameraActor.h new file mode 100644 index 00000000..a7e3923c --- /dev/null +++ b/Chapter06/CameraActor.h @@ -0,0 +1,21 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#pragma once +#include "Actor.h" + +class CameraActor : public Actor +{ +public: + CameraActor(class Game* game); + + void UpdateActor(float deltaTime) override; + void ActorInput(const uint8_t* keys) override; +private: + class MoveComponent* mMoveComp; +}; diff --git a/Chapter06/Chapter06-mac.xcodeproj/project.pbxproj b/Chapter06/Chapter06-mac.xcodeproj/project.pbxproj new file mode 100644 index 00000000..a5b2a6ce --- /dev/null +++ b/Chapter06/Chapter06-mac.xcodeproj/project.pbxproj @@ -0,0 +1,404 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 9206FDC61F140707005078A2 /* Texture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9206FDC41F140707005078A2 /* Texture.cpp */; }; + 9206FDC91F140D40005078A2 /* Shader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9206FDC71F140D40005078A2 /* Shader.cpp */; }; + 9223C4781F009428009A94D7 /* Game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9223C4671F009428009A94D7 /* Game.cpp */; }; + 9223C4791F009428009A94D7 /* Actor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9223C4681F009428009A94D7 /* Actor.cpp */; }; + 9223C47C1F009428009A94D7 /* Component.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9223C46E1F009428009A94D7 /* Component.cpp */; }; + 9223C47D1F009428009A94D7 /* Main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9223C4711F009428009A94D7 /* Main.cpp */; }; + 9223C47E1F009428009A94D7 /* Math.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9223C4721F009428009A94D7 /* Math.cpp */; }; + 9223C4801F009428009A94D7 /* SpriteComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9223C4761F009428009A94D7 /* SpriteComponent.cpp */; }; + 9223C48B1F0CA3CE009A94D7 /* MoveComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9223C48A1F0CA3CE009A94D7 /* MoveComponent.cpp */; }; + 9223C4951F0CA766009A94D7 /* CircleComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9223C4911F0CA766009A94D7 /* CircleComponent.cpp */; }; + 92279F471F17101E00D5F4B9 /* VertexArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 92279F451F17101E00D5F4B9 /* VertexArray.cpp */; }; + 92CF0D721F3BBBE50086A0F3 /* CameraActor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 92CF0D681F3BBBE50086A0F3 /* CameraActor.cpp */; }; + 92CF0D731F3BBBE50086A0F3 /* Mesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 92CF0D6A1F3BBBE50086A0F3 /* Mesh.cpp */; }; + 92CF0D741F3BBBE50086A0F3 /* MeshComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 92CF0D6C1F3BBBE50086A0F3 /* MeshComponent.cpp */; }; + 92CF0D751F3BBBE50086A0F3 /* PlaneActor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 92CF0D6E1F3BBBE50086A0F3 /* PlaneActor.cpp */; }; + 92CF0D761F3BBBE50086A0F3 /* Renderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 92CF0D701F3BBBE50086A0F3 /* Renderer.cpp */; }; + 92D324FB1B697389005A86C7 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 92D324FA1B697389005A86C7 /* CoreFoundation.framework */; }; + 92E46E941B6353E50035CD21 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 92E46E931B6353E50035CD21 /* OpenGL.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 9206FDC31F13F7E8005078A2 /* Shaders */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Shaders; sourceTree = ""; }; + 9206FDC41F140707005078A2 /* Texture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Texture.cpp; sourceTree = ""; }; + 9206FDC51F140707005078A2 /* Texture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Texture.h; sourceTree = ""; }; + 9206FDC71F140D40005078A2 /* Shader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Shader.cpp; sourceTree = ""; }; + 9206FDC81F140D40005078A2 /* Shader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Shader.h; sourceTree = ""; }; + 9223C4671F009428009A94D7 /* Game.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Game.cpp; sourceTree = ""; }; + 9223C4681F009428009A94D7 /* Actor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Actor.cpp; sourceTree = ""; }; + 9223C4691F009428009A94D7 /* Actor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Actor.h; sourceTree = ""; }; + 9223C46E1F009428009A94D7 /* Component.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Component.cpp; sourceTree = ""; }; + 9223C46F1F009428009A94D7 /* Component.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Component.h; sourceTree = ""; }; + 9223C4701F009428009A94D7 /* Game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Game.h; sourceTree = ""; }; + 9223C4711F009428009A94D7 /* Main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Main.cpp; sourceTree = ""; }; + 9223C4721F009428009A94D7 /* Math.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Math.cpp; sourceTree = ""; }; + 9223C4731F009428009A94D7 /* Math.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Math.h; sourceTree = ""; }; + 9223C4761F009428009A94D7 /* SpriteComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpriteComponent.cpp; sourceTree = ""; }; + 9223C4771F009428009A94D7 /* SpriteComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteComponent.h; sourceTree = ""; }; + 9223C48A1F0CA3CE009A94D7 /* MoveComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MoveComponent.cpp; sourceTree = ""; }; + 9223C48C1F0CA3D4009A94D7 /* MoveComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MoveComponent.h; sourceTree = ""; }; + 9223C4911F0CA766009A94D7 /* CircleComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CircleComponent.cpp; sourceTree = ""; }; + 9223C4931F0CA766009A94D7 /* CircleComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CircleComponent.h; sourceTree = ""; }; + 92279F451F17101E00D5F4B9 /* VertexArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VertexArray.cpp; sourceTree = ""; }; + 92279F461F17101E00D5F4B9 /* VertexArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VertexArray.h; sourceTree = ""; }; + 92CF0D681F3BBBE50086A0F3 /* CameraActor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CameraActor.cpp; sourceTree = ""; }; + 92CF0D691F3BBBE50086A0F3 /* CameraActor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CameraActor.h; sourceTree = ""; }; + 92CF0D6A1F3BBBE50086A0F3 /* Mesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mesh.cpp; sourceTree = ""; }; + 92CF0D6B1F3BBBE50086A0F3 /* Mesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Mesh.h; sourceTree = ""; }; + 92CF0D6C1F3BBBE50086A0F3 /* MeshComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MeshComponent.cpp; sourceTree = ""; }; + 92CF0D6D1F3BBBE50086A0F3 /* MeshComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MeshComponent.h; sourceTree = ""; }; + 92CF0D6E1F3BBBE50086A0F3 /* PlaneActor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlaneActor.cpp; sourceTree = ""; }; + 92CF0D6F1F3BBBE50086A0F3 /* PlaneActor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlaneActor.h; sourceTree = ""; }; + 92CF0D701F3BBBE50086A0F3 /* Renderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Renderer.cpp; sourceTree = ""; }; + 92CF0D711F3BBBE50086A0F3 /* Renderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Renderer.h; sourceTree = ""; }; + 92D324FA1B697389005A86C7 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + 92E46DF71B634EA30035CD21 /* Game-mac */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Game-mac"; sourceTree = BUILT_PRODUCTS_DIR; }; + 92E46E931B6353E50035CD21 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 92E46DF41B634EA30035CD21 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 92D324FB1B697389005A86C7 /* CoreFoundation.framework in Frameworks */, + 92E46E941B6353E50035CD21 /* OpenGL.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 92E46DEE1B634EA30035CD21 = { + isa = PBXGroup; + children = ( + 9223C4681F009428009A94D7 /* Actor.cpp */, + 9223C4691F009428009A94D7 /* Actor.h */, + 92CF0D681F3BBBE50086A0F3 /* CameraActor.cpp */, + 92CF0D691F3BBBE50086A0F3 /* CameraActor.h */, + 9223C46E1F009428009A94D7 /* Component.cpp */, + 9223C46F1F009428009A94D7 /* Component.h */, + 9223C4911F0CA766009A94D7 /* CircleComponent.cpp */, + 9223C4931F0CA766009A94D7 /* CircleComponent.h */, + 9223C4671F009428009A94D7 /* Game.cpp */, + 9223C4701F009428009A94D7 /* Game.h */, + 9223C4711F009428009A94D7 /* Main.cpp */, + 9223C4721F009428009A94D7 /* Math.cpp */, + 9223C4731F009428009A94D7 /* Math.h */, + 92CF0D6A1F3BBBE50086A0F3 /* Mesh.cpp */, + 92CF0D6B1F3BBBE50086A0F3 /* Mesh.h */, + 92CF0D6C1F3BBBE50086A0F3 /* MeshComponent.cpp */, + 92CF0D6D1F3BBBE50086A0F3 /* MeshComponent.h */, + 9223C48A1F0CA3CE009A94D7 /* MoveComponent.cpp */, + 9223C48C1F0CA3D4009A94D7 /* MoveComponent.h */, + 92CF0D6E1F3BBBE50086A0F3 /* PlaneActor.cpp */, + 92CF0D6F1F3BBBE50086A0F3 /* PlaneActor.h */, + 92CF0D701F3BBBE50086A0F3 /* Renderer.cpp */, + 92CF0D711F3BBBE50086A0F3 /* Renderer.h */, + 9206FDC71F140D40005078A2 /* Shader.cpp */, + 9206FDC81F140D40005078A2 /* Shader.h */, + 9223C4761F009428009A94D7 /* SpriteComponent.cpp */, + 9223C4771F009428009A94D7 /* SpriteComponent.h */, + 9206FDC41F140707005078A2 /* Texture.cpp */, + 9206FDC51F140707005078A2 /* Texture.h */, + 92279F451F17101E00D5F4B9 /* VertexArray.cpp */, + 92279F461F17101E00D5F4B9 /* VertexArray.h */, + 9206FDC31F13F7E8005078A2 /* Shaders */, + 92E46DF81B634EA30035CD21 /* Products */, + 92D324FA1B697389005A86C7 /* CoreFoundation.framework */, + 92E46E931B6353E50035CD21 /* OpenGL.framework */, + ); + sourceTree = ""; + }; + 92E46DF81B634EA30035CD21 /* Products */ = { + isa = PBXGroup; + children = ( + 92E46DF71B634EA30035CD21 /* Game-mac */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 92E46DF61B634EA30035CD21 /* Game-mac */ = { + isa = PBXNativeTarget; + buildConfigurationList = 92E46DFE1B634EA40035CD21 /* Build configuration list for PBXNativeTarget "Game-mac" */; + buildPhases = ( + 92E46DF31B634EA30035CD21 /* Sources */, + 92E46DF41B634EA30035CD21 /* Frameworks */, + 92E46EA11B63615B0035CD21 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Game-mac"; + productName = "Game-mac"; + productReference = 92E46DF71B634EA30035CD21 /* Game-mac */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 92E46DEF1B634EA30035CD21 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0920; + ORGANIZATIONNAME = "Sanjay Madhav"; + TargetAttributes = { + 92E46DF61B634EA30035CD21 = { + CreatedOnToolsVersion = 6.4; + }; + }; + }; + buildConfigurationList = 92E46DF21B634EA30035CD21 /* Build configuration list for PBXProject "Chapter06-mac" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 92E46DEE1B634EA30035CD21; + productRefGroup = 92E46DF81B634EA30035CD21 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 92E46DF61B634EA30035CD21 /* Game-mac */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 92E46EA11B63615B0035CD21 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if [ -d \"$BUILD_DIR/Debug\" ]; then\n cp \"$SRCROOT\"/../external/GLEW/lib/mac/*.dylib $BUILD_DIR/Debug\n cp \"$SRCROOT\"/../external/SDL/lib/mac/*.dylib $BUILD_DIR/Debug\nfi\n\nif [ -d \"$BUILD_DIR/Release\" ]; then\n cp \"$SRCROOT\"/../external/GLEW/lib/mac/*.dylib $BUILD_DIR/Release\n cp \"$SRCROOT\"/../external/SDL/lib/mac/*.dylib $BUILD_DIR/Release\nfi"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 92E46DF31B634EA30035CD21 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 92279F471F17101E00D5F4B9 /* VertexArray.cpp in Sources */, + 9223C47D1F009428009A94D7 /* Main.cpp in Sources */, + 9223C47E1F009428009A94D7 /* Math.cpp in Sources */, + 92CF0D721F3BBBE50086A0F3 /* CameraActor.cpp in Sources */, + 9223C4781F009428009A94D7 /* Game.cpp in Sources */, + 9223C4801F009428009A94D7 /* SpriteComponent.cpp in Sources */, + 92CF0D761F3BBBE50086A0F3 /* Renderer.cpp in Sources */, + 9223C48B1F0CA3CE009A94D7 /* MoveComponent.cpp in Sources */, + 92CF0D751F3BBBE50086A0F3 /* PlaneActor.cpp in Sources */, + 9206FDC91F140D40005078A2 /* Shader.cpp in Sources */, + 9223C4791F009428009A94D7 /* Actor.cpp in Sources */, + 92CF0D741F3BBBE50086A0F3 /* MeshComponent.cpp in Sources */, + 92CF0D731F3BBBE50086A0F3 /* Mesh.cpp in Sources */, + 9223C4951F0CA766009A94D7 /* CircleComponent.cpp in Sources */, + 9223C47C1F009428009A94D7 /* Component.cpp in Sources */, + 9206FDC61F140707005078A2 /* Texture.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 92E46DFC1B634EA40035CD21 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 92E46DFD1B634EA40035CD21 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 92E46DFF1B634EA40035CD21 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "c++14"; + FRAMEWORK_SEARCH_PATHS = ""; + GCC_ENABLE_CPP_RTTI = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../external/SDL/include", + "$(SRCROOT)/../external/GLEW/include", + "$(SRCROOT)/../external/SOIL/include", + "$(SRCROOT)/../external/rapidjson/include", + ); + LIBRARY_SEARCH_PATHS = ( + "$(SRCROOT)/../external/GLEW/lib/mac", + "$(SRCROOT)/../external/SDL/lib/mac", + "$(SRCROOT)/../external/SOIL/lib/mac", + ); + OTHER_LDFLAGS = ( + "-lGLEW.2.1.0", + "-lSDL2-2.0.0", + "-lSDL2_mixer-2.0.0", + "-lSDL2_ttf-2.0.0", + "-lSOIL", + "-lSDL2_image-2.0.0", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 92E46E001B634EA40035CD21 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "c++14"; + FRAMEWORK_SEARCH_PATHS = ""; + GCC_ENABLE_CPP_RTTI = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../external/SDL/include", + "$(SRCROOT)/../external/GLEW/include", + "$(SRCROOT)/../external/SOIL/include", + "$(SRCROOT)/../external/rapidjson/include", + ); + LIBRARY_SEARCH_PATHS = ( + "$(SRCROOT)/../external/GLEW/lib/mac", + "$(SRCROOT)/../external/SDL/lib/mac", + "$(SRCROOT)/../external/SOIL/lib/mac", + ); + OTHER_LDFLAGS = ( + "-lGLEW.2.1.0", + "-lSDL2-2.0.0", + "-lSDL2_mixer-2.0.0", + "-lSDL2_ttf-2.0.0", + "-lSOIL", + "-lSDL2_image-2.0.0", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 92E46DF21B634EA30035CD21 /* Build configuration list for PBXProject "Chapter06-mac" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 92E46DFC1B634EA40035CD21 /* Debug */, + 92E46DFD1B634EA40035CD21 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 92E46DFE1B634EA40035CD21 /* Build configuration list for PBXNativeTarget "Game-mac" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 92E46DFF1B634EA40035CD21 /* Debug */, + 92E46E001B634EA40035CD21 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 92E46DEF1B634EA30035CD21 /* Project object */; +} diff --git a/Chapter06/Chapter06-mac.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Chapter06/Chapter06-mac.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..f7e51f57 --- /dev/null +++ b/Chapter06/Chapter06-mac.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Chapter06/Chapter06-mac.xcodeproj/xcshareddata/xcschemes/Game-mac.xcscheme b/Chapter06/Chapter06-mac.xcodeproj/xcshareddata/xcschemes/Game-mac.xcscheme new file mode 100644 index 00000000..bc5246bc --- /dev/null +++ b/Chapter06/Chapter06-mac.xcodeproj/xcshareddata/xcschemes/Game-mac.xcscheme @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Chapter06/Chapter06-windows.sln b/Chapter06/Chapter06-windows.sln new file mode 100644 index 00000000..f560df0f --- /dev/null +++ b/Chapter06/Chapter06-windows.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Game", "Game.vcxproj", "{BC508D87-495F-4554-932D-DD68388B63CC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BC508D87-495F-4554-932D-DD68388B63CC}.Debug|Win32.ActiveCfg = Debug|Win32 + {BC508D87-495F-4554-932D-DD68388B63CC}.Debug|Win32.Build.0 = Debug|Win32 + {BC508D87-495F-4554-932D-DD68388B63CC}.Release|Win32.ActiveCfg = Release|Win32 + {BC508D87-495F-4554-932D-DD68388B63CC}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Chapter06/CircleComponent.cpp b/Chapter06/CircleComponent.cpp new file mode 100644 index 00000000..4e40d109 --- /dev/null +++ b/Chapter06/CircleComponent.cpp @@ -0,0 +1,40 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#include "CircleComponent.h" +#include "Actor.h" + +CircleComponent::CircleComponent(class Actor* owner) +:Component(owner) +,mRadius(0.0f) +{ + +} + +const Vector3& CircleComponent::GetCenter() const +{ + return mOwner->GetPosition(); +} + +float CircleComponent::GetRadius() const +{ + return mOwner->GetScale() * mRadius; +} + +bool Intersect(const CircleComponent& a, const CircleComponent& b) +{ + // Calculate distance squared + Vector3 diff = a.GetCenter() - b.GetCenter(); + float distSq = diff.LengthSq(); + + // Calculate sum of radii squared + float radiiSq = a.GetRadius() + b.GetRadius(); + radiiSq *= radiiSq; + + return distSq <= radiiSq; +} diff --git a/Chapter06/CircleComponent.h b/Chapter06/CircleComponent.h new file mode 100644 index 00000000..61c63ba9 --- /dev/null +++ b/Chapter06/CircleComponent.h @@ -0,0 +1,26 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#pragma once +#include "Component.h" +#include "Math.h" + +class CircleComponent : public Component +{ +public: + CircleComponent(class Actor* owner); + + void SetRadius(float radius) { mRadius = radius; } + float GetRadius() const; + + const Vector3& GetCenter() const; +private: + float mRadius; +}; + +bool Intersect(const CircleComponent& a, const CircleComponent& b); diff --git a/Chapter06/Component.cpp b/Chapter06/Component.cpp new file mode 100644 index 00000000..c4ed432d --- /dev/null +++ b/Chapter06/Component.cpp @@ -0,0 +1,27 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#include "Component.h" +#include "Actor.h" + +Component::Component(Actor* owner, int updateOrder) + :mOwner(owner) + ,mUpdateOrder(updateOrder) +{ + // Add to actor's vector of components + mOwner->AddComponent(this); +} + +Component::~Component() +{ + mOwner->RemoveComponent(this); +} + +void Component::Update(float deltaTime) +{ +} diff --git a/Chapter06/Component.h b/Chapter06/Component.h new file mode 100644 index 00000000..e2be424b --- /dev/null +++ b/Chapter06/Component.h @@ -0,0 +1,33 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#pragma once +#include + +class Component +{ +public: + // Constructor + // (the lower the update order, the earlier the component updates) + Component(class Actor* owner, int updateOrder = 100); + // Destructor + virtual ~Component(); + // Update this component by delta time + virtual void Update(float deltaTime); + // Process input for this component + virtual void ProcessInput(const uint8_t* keyState) {} + // Called when world transform changes + virtual void OnUpdateWorldTransform() { } + + int GetUpdateOrder() const { return mUpdateOrder; } +protected: + // Owning actor + class Actor* mOwner; + // Update order of component + int mUpdateOrder; +}; diff --git a/Chapter06/Game.cpp b/Chapter06/Game.cpp new file mode 100644 index 00000000..cf7e03a7 --- /dev/null +++ b/Chapter06/Game.cpp @@ -0,0 +1,274 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#include "Game.h" +#include +#include "Renderer.h" +#include "Actor.h" +#include "SpriteComponent.h" +#include "MeshComponent.h" +#include "CameraActor.h" +#include "PlaneActor.h" + +Game::Game() +:mRenderer(nullptr) +,mIsRunning(true) +,mUpdatingActors(false) +{ + +} + +bool Game::Initialize() +{ + if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) != 0) + { + SDL_Log("Unable to initialize SDL: %s", SDL_GetError()); + return false; + } + + // Create the renderer + mRenderer = new Renderer(this); + if (!mRenderer->Initialize(1024.0f, 768.0f)) + { + SDL_Log("Failed to initialize renderer"); + delete mRenderer; + mRenderer = nullptr; + return false; + } + + LoadData(); + + mTicksCount = SDL_GetTicks(); + + return true; +} + +void Game::RunLoop() +{ + while (mIsRunning) + { + ProcessInput(); + UpdateGame(); + GenerateOutput(); + } +} + +void Game::ProcessInput() +{ + SDL_Event event; + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_QUIT: + mIsRunning = false; + break; + } + } + + const Uint8* state = SDL_GetKeyboardState(NULL); + if (state[SDL_SCANCODE_ESCAPE]) + { + mIsRunning = false; + } + + for (auto actor : mActors) + { + actor->ProcessInput(state); + } +} + +void Game::UpdateGame() +{ + // Compute delta time + // Wait until 16ms has elapsed since last frame + while (!SDL_TICKS_PASSED(SDL_GetTicks(), mTicksCount + 16)) + ; + + float deltaTime = (SDL_GetTicks() - mTicksCount) / 1000.0f; + if (deltaTime > 0.05f) + { + deltaTime = 0.05f; + } + mTicksCount = SDL_GetTicks(); + + // Update all actors + mUpdatingActors = true; + for (auto actor : mActors) + { + actor->Update(deltaTime); + } + mUpdatingActors = false; + + // Move any pending actors to mActors + for (auto pending : mPendingActors) + { + pending->ComputeWorldTransform(); + mActors.emplace_back(pending); + } + mPendingActors.clear(); + + // Add any dead actors to a temp vector + std::vector deadActors; + for (auto actor : mActors) + { + if (actor->GetState() == Actor::EDead) + { + deadActors.emplace_back(actor); + } + } + + // Delete dead actors (which removes them from mActors) + for (auto actor : deadActors) + { + delete actor; + } +} + +void Game::GenerateOutput() +{ + mRenderer->Draw(); +} + +void Game::LoadData() +{ + // Create actors + Actor* a = new Actor(this); + a->SetPosition(Vector3(200.0f, 75.0f, 0.0f)); + a->SetScale(100.0f); + Quaternion q(Vector3::UnitY, -Math::PiOver2); + q = Quaternion::Concatenate(q, Quaternion(Vector3::UnitZ, Math::Pi + Math::Pi / 4.0f)); + a->SetRotation(q); + MeshComponent* mc = new MeshComponent(a); + mc->SetMesh(mRenderer->GetMesh("Assets/Cube.gpmesh")); + + a = new Actor(this); + a->SetPosition(Vector3(200.0f, -75.0f, 0.0f)); + a->SetScale(3.0f); + mc = new MeshComponent(a); + mc->SetMesh(mRenderer->GetMesh("Assets/Sphere.gpmesh")); + + // Setup floor + const float start = -1250.0f; + const float size = 250.0f; + for (int i = 0; i < 10; i++) + { + for (int j = 0; j < 10; j++) + { + a = new PlaneActor(this); + a->SetPosition(Vector3(start + i * size, start + j * size, -100.0f)); + } + } + + // Left/right walls + q = Quaternion(Vector3::UnitX, Math::PiOver2); + for (int i = 0; i < 10; i++) + { + a = new PlaneActor(this); + a->SetPosition(Vector3(start + i * size, start - size, 0.0f)); + a->SetRotation(q); + + a = new PlaneActor(this); + a->SetPosition(Vector3(start + i * size, -start + size, 0.0f)); + a->SetRotation(q); + } + + q = Quaternion::Concatenate(q, Quaternion(Vector3::UnitZ, Math::PiOver2)); + // Forward/back walls + for (int i = 0; i < 10; i++) + { + a = new PlaneActor(this); + a->SetPosition(Vector3(start - size, start + i * size, 0.0f)); + a->SetRotation(q); + + a = new PlaneActor(this); + a->SetPosition(Vector3(-start + size, start + i * size, 0.0f)); + a->SetRotation(q); + } + + // Setup lights + mRenderer->SetAmbientLight(Vector3(0.2f, 0.2f, 0.2f)); + DirectionalLight& dir = mRenderer->GetDirectionalLight(); + dir.mDirection = Vector3(0.0f, -0.707f, -0.707f); + dir.mDiffuseColor = Vector3(0.78f, 0.88f, 1.0f); + dir.mSpecColor = Vector3(0.8f, 0.8f, 0.8f); + + // Camera actor + mCameraActor = new CameraActor(this); + + // UI elements + a = new Actor(this); + a->SetPosition(Vector3(-350.0f, -350.0f, 0.0f)); + SpriteComponent* sc = new SpriteComponent(a); + sc->SetTexture(mRenderer->GetTexture("Assets/HealthBar.png")); + + a = new Actor(this); + a->SetPosition(Vector3(375.0f, -275.0f, 0.0f)); + a->SetScale(0.75f); + sc = new SpriteComponent(a); + sc->SetTexture(mRenderer->GetTexture("Assets/Radar.png")); +} + +void Game::UnloadData() +{ + // Delete actors + // Because ~Actor calls RemoveActor, have to use a different style loop + while (!mActors.empty()) + { + delete mActors.back(); + } + + if (mRenderer) + { + mRenderer->UnloadData(); + } +} + +void Game::Shutdown() +{ + UnloadData(); + if (mRenderer) + { + mRenderer->Shutdown(); + } + SDL_Quit(); +} + +void Game::AddActor(Actor* actor) +{ + // If we're updating actors, need to add to pending + if (mUpdatingActors) + { + mPendingActors.emplace_back(actor); + } + else + { + mActors.emplace_back(actor); + } +} + +void Game::RemoveActor(Actor* actor) +{ + // Is it in pending actors? + auto iter = std::find(mPendingActors.begin(), mPendingActors.end(), actor); + if (iter != mPendingActors.end()) + { + // Swap to end of vector and pop off (avoid erase copies) + std::iter_swap(iter, mPendingActors.end() - 1); + mPendingActors.pop_back(); + } + + // Is it in actors? + iter = std::find(mActors.begin(), mActors.end(), actor); + if (iter != mActors.end()) + { + // Swap to end of vector and pop off (avoid erase copies) + std::iter_swap(iter, mActors.end() - 1); + mActors.pop_back(); + } +} diff --git a/Chapter06/Game.h b/Chapter06/Game.h new file mode 100644 index 00000000..6f567720 --- /dev/null +++ b/Chapter06/Game.h @@ -0,0 +1,49 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#pragma once +#include +#include +#include +#include +#include "Math.h" + +class Game +{ +public: + Game(); + bool Initialize(); + void RunLoop(); + void Shutdown(); + + void AddActor(class Actor* actor); + void RemoveActor(class Actor* actor); + + class Renderer* GetRenderer() { return mRenderer; } +private: + void ProcessInput(); + void UpdateGame(); + void GenerateOutput(); + void LoadData(); + void UnloadData(); + + // All the actors in the game + std::vector mActors; + // Any pending actors + std::vector mPendingActors; + + class Renderer* mRenderer; + + Uint32 mTicksCount; + bool mIsRunning; + // Track if we're updating actors right now + bool mUpdatingActors; + + // Game-specific code + class CameraActor* mCameraActor; +}; diff --git a/Chapter06/Game.vcxproj b/Chapter06/Game.vcxproj new file mode 100644 index 00000000..182b0c8f --- /dev/null +++ b/Chapter06/Game.vcxproj @@ -0,0 +1,146 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {BC508D87-495F-4554-932D-DD68388B63CC} + Win32Proj + Game + 10.0.16299.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + ..\external\SDL\include;..\external\GLEW\include;..\external\SOIL\include;..\external\rapidjson\include;%(AdditionalIncludeDirectories) + false + Sync + + + Console + true + ..\external\SDL\lib\win\x86;..\external\GLEW\lib\win\x86;..\external\SOIL\lib\win\x86;%(AdditionalLibraryDirectories) + opengl32.lib;SDL2.lib;SDL2main.lib;SDL2_ttf.lib;SDL2_mixer.lib;SDL2_image.lib;glew32.lib;SOIL.lib;%(AdditionalDependencies) + /NODEFAULTLIB:msvcrt.lib %(AdditionalOptions) + + + xcopy "$(ProjectDir)\..\external\SDL\lib\win\x86\*.dll" "$(OutDir)" /i /s /y +xcopy "$(ProjectDir)\..\external\GLEW\lib\win\x86\*.dll" "$(OutDir)" /i /s /y + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + ..\external\SDL\include;..\external\GLEW\include;..\external\SOIL\include;..\external\rapidjson\include;%(AdditionalIncludeDirectories) + false + Sync + + + Console + true + true + true + ..\external\SDL\lib\win\x86;..\external\GLEW\lib\win\x86;..\external\SOIL\lib\win\x86;%(AdditionalLibraryDirectories) + opengl32.lib;SDL2.lib;SDL2main.lib;SDL2_ttf.lib;SDL2_mixer.lib;SDL2_image.lib;glew32.lib;SOIL.lib;%(AdditionalDependencies) + + + xcopy "$(ProjectDir)\..\external\SDL\lib\win\x86\*.dll" "$(OutDir)" /i /s /y +xcopy "$(ProjectDir)\..\external\GLEW\lib\win\x86\*.dll" "$(OutDir)" /i /s /y + + + + + + \ No newline at end of file diff --git a/Chapter06/Game.vcxproj.filters b/Chapter06/Game.vcxproj.filters new file mode 100644 index 00000000..5a07708a --- /dev/null +++ b/Chapter06/Game.vcxproj.filters @@ -0,0 +1,129 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {12a47348-9a6e-404a-8d7e-2ffa91eb59f6} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + \ No newline at end of file diff --git a/Chapter06/Main.cpp b/Chapter06/Main.cpp new file mode 100644 index 00000000..36c41e1c --- /dev/null +++ b/Chapter06/Main.cpp @@ -0,0 +1,24 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE.txt for full details. +// ---------------------------------------------------------------- + +#include "Game.h" +#include +#include +#include + +int main(int argc, char** argv) +{ + Game game; + bool success = game.Initialize(); + if (success) + { + game.RunLoop(); + } + game.Shutdown(); + return 0; +} diff --git a/Chapter06/Math.cpp b/Chapter06/Math.cpp new file mode 100644 index 00000000..a16e7261 --- /dev/null +++ b/Chapter06/Math.cpp @@ -0,0 +1,239 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#include "Math.h" + +const Vector2 Vector2::Zero(0.0f, 0.0f); +const Vector2 Vector2::UnitX(1.0f, 0.0f); +const Vector2 Vector2::UnitY(0.0f, 1.0f); +const Vector2 Vector2::NegUnitX(-1.0f, 0.0f); +const Vector2 Vector2::NegUnitY(0.0f, -1.0f); + +const Vector3 Vector3::Zero(0.0f, 0.0f, 0.f); +const Vector3 Vector3::UnitX(1.0f, 0.0f, 0.0f); +const Vector3 Vector3::UnitY(0.0f, 1.0f, 0.0f); +const Vector3 Vector3::UnitZ(0.0f, 0.0f, 1.0f); +const Vector3 Vector3::NegUnitX(-1.0f, 0.0f, 0.0f); +const Vector3 Vector3::NegUnitY(0.0f, -1.0f, 0.0f); +const Vector3 Vector3::NegUnitZ(0.0f, 0.0f, -1.0f); +const Vector3 Vector3::Infinity(Math::Infinity, Math::Infinity, Math::Infinity); +const Vector3 Vector3::NegInfinity(Math::NegInfinity, Math::NegInfinity, Math::NegInfinity); + +static float m3Ident[3][3] = +{ + { 1.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f } +}; +const Matrix3 Matrix3::Identity(m3Ident); + +static float m4Ident[4][4] = +{ + { 1.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 1.0f } +}; + +const Matrix4 Matrix4::Identity(m4Ident); + +const Quaternion Quaternion::Identity(0.0f, 0.0f, 0.0f, 1.0f); + +Vector2 Vector2::Transform(const Vector2& vec, const Matrix3& mat, float w /*= 1.0f*/) +{ + Vector2 retVal; + retVal.x = vec.x * mat.mat[0][0] + vec.y * mat.mat[1][0] + w * mat.mat[2][0]; + retVal.y = vec.x * mat.mat[0][1] + vec.y * mat.mat[1][1] + w * mat.mat[2][1]; + //ignore w since we aren't returning a new value for it... + return retVal; +} + +Vector3 Vector3::Transform(const Vector3& vec, const Matrix4& mat, float w /*= 1.0f*/) +{ + Vector3 retVal; + retVal.x = vec.x * mat.mat[0][0] + vec.y * mat.mat[1][0] + + vec.z * mat.mat[2][0] + w * mat.mat[3][0]; + retVal.y = vec.x * mat.mat[0][1] + vec.y * mat.mat[1][1] + + vec.z * mat.mat[2][1] + w * mat.mat[3][1]; + retVal.z = vec.x * mat.mat[0][2] + vec.y * mat.mat[1][2] + + vec.z * mat.mat[2][2] + w * mat.mat[3][2]; + //ignore w since we aren't returning a new value for it... + return retVal; +} + +// This will transform the vector and renormalize the w component +Vector3 Vector3::TransformWithPerspDiv(const Vector3& vec, const Matrix4& mat, float w /*= 1.0f*/) +{ + Vector3 retVal; + retVal.x = vec.x * mat.mat[0][0] + vec.y * mat.mat[1][0] + + vec.z * mat.mat[2][0] + w * mat.mat[3][0]; + retVal.y = vec.x * mat.mat[0][1] + vec.y * mat.mat[1][1] + + vec.z * mat.mat[2][1] + w * mat.mat[3][1]; + retVal.z = vec.x * mat.mat[0][2] + vec.y * mat.mat[1][2] + + vec.z * mat.mat[2][2] + w * mat.mat[3][2]; + float transformedW = vec.x * mat.mat[0][3] + vec.y * mat.mat[1][3] + + vec.z * mat.mat[2][3] + w * mat.mat[3][3]; + if (!Math::NearZero(Math::Abs(transformedW))) + { + transformedW = 1.0f / transformedW; + retVal *= transformedW; + } + return retVal; +} + +// Transform a Vector3 by a quaternion +Vector3 Vector3::Transform(const Vector3& v, const Quaternion& q) +{ + // v + 2.0*cross(q.xyz, cross(q.xyz,v) + q.w*v); + Vector3 qv(q.x, q.y, q.z); + Vector3 retVal = v; + retVal += 2.0f * Vector3::Cross(qv, Vector3::Cross(qv, v) + q.w * v); + return retVal; +} + +void Matrix4::Invert() +{ + // Thanks slow math + // This is a really janky way to unroll everything... + float tmp[12]; + float src[16]; + float dst[16]; + float det; + + // Transpose matrix + // row 1 to col 1 + src[0] = mat[0][0]; + src[4] = mat[0][1]; + src[8] = mat[0][2]; + src[12] = mat[0][3]; + + // row 2 to col 2 + src[1] = mat[1][0]; + src[5] = mat[1][1]; + src[9] = mat[1][2]; + src[13] = mat[1][3]; + + // row 3 to col 3 + src[2] = mat[2][0]; + src[6] = mat[2][1]; + src[10] = mat[2][2]; + src[14] = mat[2][3]; + + // row 4 to col 4 + src[3] = mat[3][0]; + src[7] = mat[3][1]; + src[11] = mat[3][2]; + src[15] = mat[3][3]; + + // Calculate cofactors + tmp[0] = src[10] * src[15]; + tmp[1] = src[11] * src[14]; + tmp[2] = src[9] * src[15]; + tmp[3] = src[11] * src[13]; + tmp[4] = src[9] * src[14]; + tmp[5] = src[10] * src[13]; + tmp[6] = src[8] * src[15]; + tmp[7] = src[11] * src[12]; + tmp[8] = src[8] * src[14]; + tmp[9] = src[10] * src[12]; + tmp[10] = src[8] * src[13]; + tmp[11] = src[9] * src[12]; + + dst[0] = tmp[0] * src[5] + tmp[3] * src[6] + tmp[4] * src[7]; + dst[0] -= tmp[1] * src[5] + tmp[2] * src[6] + tmp[5] * src[7]; + dst[1] = tmp[1] * src[4] + tmp[6] * src[6] + tmp[9] * src[7]; + dst[1] -= tmp[0] * src[4] + tmp[7] * src[6] + tmp[8] * src[7]; + dst[2] = tmp[2] * src[4] + tmp[7] * src[5] + tmp[10] * src[7]; + dst[2] -= tmp[3] * src[4] + tmp[6] * src[5] + tmp[11] * src[7]; + dst[3] = tmp[5] * src[4] + tmp[8] * src[5] + tmp[11] * src[6]; + dst[3] -= tmp[4] * src[4] + tmp[9] * src[5] + tmp[10] * src[6]; + dst[4] = tmp[1] * src[1] + tmp[2] * src[2] + tmp[5] * src[3]; + dst[4] -= tmp[0] * src[1] + tmp[3] * src[2] + tmp[4] * src[3]; + dst[5] = tmp[0] * src[0] + tmp[7] * src[2] + tmp[8] * src[3]; + dst[5] -= tmp[1] * src[0] + tmp[6] * src[2] + tmp[9] * src[3]; + dst[6] = tmp[3] * src[0] + tmp[6] * src[1] + tmp[11] * src[3]; + dst[6] -= tmp[2] * src[0] + tmp[7] * src[1] + tmp[10] * src[3]; + dst[7] = tmp[4] * src[0] + tmp[9] * src[1] + tmp[10] * src[2]; + dst[7] -= tmp[5] * src[0] + tmp[8] * src[1] + tmp[11] * src[2]; + + tmp[0] = src[2] * src[7]; + tmp[1] = src[3] * src[6]; + tmp[2] = src[1] * src[7]; + tmp[3] = src[3] * src[5]; + tmp[4] = src[1] * src[6]; + tmp[5] = src[2] * src[5]; + tmp[6] = src[0] * src[7]; + tmp[7] = src[3] * src[4]; + tmp[8] = src[0] * src[6]; + tmp[9] = src[2] * src[4]; + tmp[10] = src[0] * src[5]; + tmp[11] = src[1] * src[4]; + + dst[8] = tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15]; + dst[8] -= tmp[1] * src[13] + tmp[2] * src[14] + tmp[5] * src[15]; + dst[9] = tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15]; + dst[9] -= tmp[0] * src[12] + tmp[7] * src[14] + tmp[8] * src[15]; + dst[10] = tmp[2] * src[12] + tmp[7] * src[13] + tmp[10] * src[15]; + dst[10] -= tmp[3] * src[12] + tmp[6] * src[13] + tmp[11] * src[15]; + dst[11] = tmp[5] * src[12] + tmp[8] * src[13] + tmp[11] * src[14]; + dst[11] -= tmp[4] * src[12] + tmp[9] * src[13] + tmp[10] * src[14]; + dst[12] = tmp[2] * src[10] + tmp[5] * src[11] + tmp[1] * src[9]; + dst[12] -= tmp[4] * src[11] + tmp[0] * src[9] + tmp[3] * src[10]; + dst[13] = tmp[8] * src[11] + tmp[0] * src[8] + tmp[7] * src[10]; + dst[13] -= tmp[6] * src[10] + tmp[9] * src[11] + tmp[1] * src[8]; + dst[14] = tmp[6] * src[9] + tmp[11] * src[11] + tmp[3] * src[8]; + dst[14] -= tmp[10] * src[11] + tmp[2] * src[8] + tmp[7] * src[9]; + dst[15] = tmp[10] * src[10] + tmp[4] * src[8] + tmp[9] * src[9]; + dst[15] -= tmp[8] * src[9] + tmp[11] * src[10] + tmp[5] * src[8]; + + // Calculate determinant + det = src[0] * dst[0] + src[1] * dst[1] + src[2] * dst[2] + src[3] * dst[3]; + + // Inverse of matrix is divided by determinant + det = 1 / det; + for (int j = 0; j < 16; j++) + { + dst[j] *= det; + } + + // Set it back + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 4; j++) + { + mat[i][j] = dst[i * 4 + j]; + } + } +} + +Matrix4 Matrix4::CreateFromQuaternion(const class Quaternion& q) +{ + float mat[4][4]; + + mat[0][0] = 1.0f - 2.0f * q.y * q.y - 2.0f * q.z * q.z; + mat[0][1] = 2.0f * q.x * q.y + 2.0f * q.w * q.z; + mat[0][2] = 2.0f * q.x * q.z - 2.0f * q.w * q.y; + mat[0][3] = 0.0f; + + mat[1][0] = 2.0f * q.x * q.y - 2.0f * q.w * q.z; + mat[1][1] = 1.0f - 2.0f * q.x * q.x - 2.0f * q.z * q.z; + mat[1][2] = 2.0f * q.y * q.z + 2.0f * q.w * q.x; + mat[1][3] = 0.0f; + + mat[2][0] = 2.0f * q.x * q.z + 2.0f * q.w * q.y; + mat[2][1] = 2.0f * q.y * q.z - 2.0f * q.w * q.x; + mat[2][2] = 1.0f - 2.0f * q.x * q.x - 2.0f * q.y * q.y; + mat[2][3] = 0.0f; + + mat[3][0] = 0.0f; + mat[3][1] = 0.0f; + mat[3][2] = 0.0f; + mat[3][3] = 1.0f; + + return Matrix4(mat); +} diff --git a/Chapter06/Math.h b/Chapter06/Math.h new file mode 100644 index 00000000..752963f1 --- /dev/null +++ b/Chapter06/Math.h @@ -0,0 +1,1033 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#pragma once + +#include +#include +#include + +namespace Math +{ + const float Pi = 3.1415926535f; + const float TwoPi = Pi * 2.0f; + const float PiOver2 = Pi / 2.0f; + const float Infinity = std::numeric_limits::infinity(); + const float NegInfinity = -std::numeric_limits::infinity(); + + inline float ToRadians(float degrees) + { + return degrees * Pi / 180.0f; + } + + inline float ToDegrees(float radians) + { + return radians * 180.0f / Pi; + } + + inline bool NearZero(float val, float epsilon = 0.001f) + { + if (fabs(val) <= epsilon) + { + return true; + } + else + { + return false; + } + } + + template + T Max(const T& a, const T& b) + { + return (a < b ? b : a); + } + + template + T Min(const T& a, const T& b) + { + return (a < b ? a : b); + } + + template + T Clamp(const T& value, const T& lower, const T& upper) + { + return Min(upper, Max(lower, value)); + } + + inline float Abs(float value) + { + return fabs(value); + } + + inline float Cos(float angle) + { + return cosf(angle); + } + + inline float Sin(float angle) + { + return sinf(angle); + } + + inline float Tan(float angle) + { + return tanf(angle); + } + + inline float Acos(float value) + { + return acosf(value); + } + + inline float Atan2(float y, float x) + { + return atan2f(y, x); + } + + inline float Cot(float angle) + { + return 1.0f / Tan(angle); + } + + inline float Lerp(float a, float b, float f) + { + return a + f * (b - a); + } + + inline float Sqrt(float value) + { + return sqrtf(value); + } + + inline float Fmod(float numer, float denom) + { + return fmod(numer, denom); + } +} + +// 2D Vector +class Vector2 +{ +public: + float x; + float y; + + Vector2() + :x(0.0f) + ,y(0.0f) + {} + + explicit Vector2(float inX, float inY) + :x(inX) + ,y(inY) + {} + + // Set both components in one line + void Set(float inX, float inY) + { + x = inX; + y = inY; + } + + // Vector addition (a + b) + friend Vector2 operator+(const Vector2& a, const Vector2& b) + { + return Vector2(a.x + b.x, a.y + b.y); + } + + // Vector subtraction (a - b) + friend Vector2 operator-(const Vector2& a, const Vector2& b) + { + return Vector2(a.x - b.x, a.y - b.y); + } + + // Component-wise multiplication + // (a.x * b.x, ...) + friend Vector2 operator*(const Vector2& a, const Vector2& b) + { + return Vector2(a.x * b.x, a.y * b.y); + } + + // Scalar multiplication + friend Vector2 operator*(const Vector2& vec, float scalar) + { + return Vector2(vec.x * scalar, vec.y * scalar); + } + + // Scalar multiplication + friend Vector2 operator*(float scalar, const Vector2& vec) + { + return Vector2(vec.x * scalar, vec.y * scalar); + } + + // Scalar *= + Vector2& operator*=(float scalar) + { + x *= scalar; + y *= scalar; + return *this; + } + + // Vector += + Vector2& operator+=(const Vector2& right) + { + x += right.x; + y += right.y; + return *this; + } + + // Vector -= + Vector2& operator-=(const Vector2& right) + { + x -= right.x; + y -= right.y; + return *this; + } + + // Length squared of vector + float LengthSq() const + { + return (x*x + y*y); + } + + // Length of vector + float Length() const + { + return (Math::Sqrt(LengthSq())); + } + + // Normalize this vector + void Normalize() + { + float length = Length(); + x /= length; + y /= length; + } + + // Normalize the provided vector + static Vector2 Normalize(const Vector2& vec) + { + Vector2 temp = vec; + temp.Normalize(); + return temp; + } + + // Dot product between two vectors (a dot b) + static float Dot(const Vector2& a, const Vector2& b) + { + return (a.x * b.x + a.y * b.y); + } + + // Lerp from A to B by f + static Vector2 Lerp(const Vector2& a, const Vector2& b, float f) + { + return Vector2(a + f * (b - a)); + } + + // Reflect V about (normalized) N + static Vector2 Reflect(const Vector2& v, const Vector2& n) + { + return v - 2.0f * Vector2::Dot(v, n) * n; + } + + // Transform vector by matrix + static Vector2 Transform(const Vector2& vec, const class Matrix3& mat, float w = 1.0f); + + static const Vector2 Zero; + static const Vector2 UnitX; + static const Vector2 UnitY; + static const Vector2 NegUnitX; + static const Vector2 NegUnitY; +}; + +// 3D Vector +class Vector3 +{ +public: + float x; + float y; + float z; + + Vector3() + :x(0.0f) + ,y(0.0f) + ,z(0.0f) + {} + + explicit Vector3(float inX, float inY, float inZ) + :x(inX) + ,y(inY) + ,z(inZ) + {} + + // Cast to a const float pointer + const float* GetAsFloatPtr() const + { + return reinterpret_cast(&x); + } + + // Set all three components in one line + void Set(float inX, float inY, float inZ) + { + x = inX; + y = inY; + z = inZ; + } + + // Vector addition (a + b) + friend Vector3 operator+(const Vector3& a, const Vector3& b) + { + return Vector3(a.x + b.x, a.y + b.y, a.z + b.z); + } + + // Vector subtraction (a - b) + friend Vector3 operator-(const Vector3& a, const Vector3& b) + { + return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); + } + + // Component-wise multiplication + friend Vector3 operator*(const Vector3& left, const Vector3& right) + { + return Vector3(left.x * right.x, left.y * right.y, left.z * right.z); + } + + // Scalar multiplication + friend Vector3 operator*(const Vector3& vec, float scalar) + { + return Vector3(vec.x * scalar, vec.y * scalar, vec.z * scalar); + } + + // Scalar multiplication + friend Vector3 operator*(float scalar, const Vector3& vec) + { + return Vector3(vec.x * scalar, vec.y * scalar, vec.z * scalar); + } + + // Scalar *= + Vector3& operator*=(float scalar) + { + x *= scalar; + y *= scalar; + z *= scalar; + return *this; + } + + // Vector += + Vector3& operator+=(const Vector3& right) + { + x += right.x; + y += right.y; + z += right.z; + return *this; + } + + // Vector -= + Vector3& operator-=(const Vector3& right) + { + x -= right.x; + y -= right.y; + z -= right.z; + return *this; + } + + // Length squared of vector + float LengthSq() const + { + return (x*x + y*y + z*z); + } + + // Length of vector + float Length() const + { + return (Math::Sqrt(LengthSq())); + } + + // Normalize this vector + void Normalize() + { + float length = Length(); + x /= length; + y /= length; + z /= length; + } + + // Normalize the provided vector + static Vector3 Normalize(const Vector3& vec) + { + Vector3 temp = vec; + temp.Normalize(); + return temp; + } + + // Dot product between two vectors (a dot b) + static float Dot(const Vector3& a, const Vector3& b) + { + return (a.x * b.x + a.y * b.y + a.z * b.z); + } + + // Cross product between two vectors (a cross b) + static Vector3 Cross(const Vector3& a, const Vector3& b) + { + Vector3 temp; + temp.x = a.y * b.z - a.z * b.y; + temp.y = a.z * b.x - a.x * b.z; + temp.z = a.x * b.y - a.y * b.x; + return temp; + } + + // Lerp from A to B by f + static Vector3 Lerp(const Vector3& a, const Vector3& b, float f) + { + return Vector3(a + f * (b - a)); + } + + // Reflect V about (normalized) N + static Vector3 Reflect(const Vector3& v, const Vector3& n) + { + return v - 2.0f * Vector3::Dot(v, n) * n; + } + + static Vector3 Transform(const Vector3& vec, const class Matrix4& mat, float w = 1.0f); + // This will transform the vector and renormalize the w component + static Vector3 TransformWithPerspDiv(const Vector3& vec, const class Matrix4& mat, float w = 1.0f); + + // Transform a Vector3 by a quaternion + static Vector3 Transform(const Vector3& v, const class Quaternion& q); + + static const Vector3 Zero; + static const Vector3 UnitX; + static const Vector3 UnitY; + static const Vector3 UnitZ; + static const Vector3 NegUnitX; + static const Vector3 NegUnitY; + static const Vector3 NegUnitZ; + static const Vector3 Infinity; + static const Vector3 NegInfinity; +}; + +// 3x3 Matrix +class Matrix3 +{ +public: + float mat[3][3]; + + Matrix3() + { + *this = Matrix3::Identity; + } + + explicit Matrix3(float inMat[3][3]) + { + memcpy(mat, inMat, 9 * sizeof(float)); + } + + // Cast to a const float pointer + const float* GetAsFloatPtr() const + { + return reinterpret_cast(&mat[0][0]); + } + + // Matrix multiplication + friend Matrix3 operator*(const Matrix3& left, const Matrix3& right) + { + Matrix3 retVal; + // row 0 + retVal.mat[0][0] = + left.mat[0][0] * right.mat[0][0] + + left.mat[0][1] * right.mat[1][0] + + left.mat[0][2] * right.mat[2][0]; + + retVal.mat[0][1] = + left.mat[0][0] * right.mat[0][1] + + left.mat[0][1] * right.mat[1][1] + + left.mat[0][2] * right.mat[2][1]; + + retVal.mat[0][2] = + left.mat[0][0] * right.mat[0][2] + + left.mat[0][1] * right.mat[1][2] + + left.mat[0][2] * right.mat[2][2]; + + // row 1 + retVal.mat[1][0] = + left.mat[1][0] * right.mat[0][0] + + left.mat[1][1] * right.mat[1][0] + + left.mat[1][2] * right.mat[2][0]; + + retVal.mat[1][1] = + left.mat[1][0] * right.mat[0][1] + + left.mat[1][1] * right.mat[1][1] + + left.mat[1][2] * right.mat[2][1]; + + retVal.mat[1][2] = + left.mat[1][0] * right.mat[0][2] + + left.mat[1][1] * right.mat[1][2] + + left.mat[1][2] * right.mat[2][2]; + + // row 2 + retVal.mat[2][0] = + left.mat[2][0] * right.mat[0][0] + + left.mat[2][1] * right.mat[1][0] + + left.mat[2][2] * right.mat[2][0]; + + retVal.mat[2][1] = + left.mat[2][0] * right.mat[0][1] + + left.mat[2][1] * right.mat[1][1] + + left.mat[2][2] * right.mat[2][1]; + + retVal.mat[2][2] = + left.mat[2][0] * right.mat[0][2] + + left.mat[2][1] * right.mat[1][2] + + left.mat[2][2] * right.mat[2][2]; + + return retVal; + } + + Matrix3& operator*=(const Matrix3& right) + { + *this = *this * right; + return *this; + } + + // Create a scale matrix with x and y scales + static Matrix3 CreateScale(float xScale, float yScale) + { + float temp[3][3] = + { + { xScale, 0.0f, 0.0f }, + { 0.0f, yScale, 0.0f }, + { 0.0f, 0.0f, 1.0f }, + }; + return Matrix3(temp); + } + + static Matrix3 CreateScale(const Vector2& scaleVector) + { + return CreateScale(scaleVector.x, scaleVector.y); + } + + // Create a scale matrix with a uniform factor + static Matrix3 CreateScale(float scale) + { + return CreateScale(scale, scale); + } + + // Create a rotation matrix about the Z axis + // theta is in radians + static Matrix3 CreateRotation(float theta) + { + float temp[3][3] = + { + { Math::Cos(theta), Math::Sin(theta), 0.0f }, + { -Math::Sin(theta), Math::Cos(theta), 0.0f }, + { 0.0f, 0.0f, 1.0f }, + }; + return Matrix3(temp); + } + + // Create a translation matrix (on the xy-plane) + static Matrix3 CreateTranslation(const Vector2& trans) + { + float temp[3][3] = + { + { 1.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f }, + { trans.x, trans.y, 1.0f }, + }; + return Matrix3(temp); + } + + static const Matrix3 Identity; +}; + +// 4x4 Matrix +class Matrix4 +{ +public: + float mat[4][4]; + + Matrix4() + { + *this = Matrix4::Identity; + } + + explicit Matrix4(float inMat[4][4]) + { + memcpy(mat, inMat, 16 * sizeof(float)); + } + + // Cast to a const float pointer + const float* GetAsFloatPtr() const + { + return reinterpret_cast(&mat[0][0]); + } + + // Matrix multiplication (a * b) + friend Matrix4 operator*(const Matrix4& a, const Matrix4& b) + { + Matrix4 retVal; + // row 0 + retVal.mat[0][0] = + a.mat[0][0] * b.mat[0][0] + + a.mat[0][1] * b.mat[1][0] + + a.mat[0][2] * b.mat[2][0] + + a.mat[0][3] * b.mat[3][0]; + + retVal.mat[0][1] = + a.mat[0][0] * b.mat[0][1] + + a.mat[0][1] * b.mat[1][1] + + a.mat[0][2] * b.mat[2][1] + + a.mat[0][3] * b.mat[3][1]; + + retVal.mat[0][2] = + a.mat[0][0] * b.mat[0][2] + + a.mat[0][1] * b.mat[1][2] + + a.mat[0][2] * b.mat[2][2] + + a.mat[0][3] * b.mat[3][2]; + + retVal.mat[0][3] = + a.mat[0][0] * b.mat[0][3] + + a.mat[0][1] * b.mat[1][3] + + a.mat[0][2] * b.mat[2][3] + + a.mat[0][3] * b.mat[3][3]; + + // row 1 + retVal.mat[1][0] = + a.mat[1][0] * b.mat[0][0] + + a.mat[1][1] * b.mat[1][0] + + a.mat[1][2] * b.mat[2][0] + + a.mat[1][3] * b.mat[3][0]; + + retVal.mat[1][1] = + a.mat[1][0] * b.mat[0][1] + + a.mat[1][1] * b.mat[1][1] + + a.mat[1][2] * b.mat[2][1] + + a.mat[1][3] * b.mat[3][1]; + + retVal.mat[1][2] = + a.mat[1][0] * b.mat[0][2] + + a.mat[1][1] * b.mat[1][2] + + a.mat[1][2] * b.mat[2][2] + + a.mat[1][3] * b.mat[3][2]; + + retVal.mat[1][3] = + a.mat[1][0] * b.mat[0][3] + + a.mat[1][1] * b.mat[1][3] + + a.mat[1][2] * b.mat[2][3] + + a.mat[1][3] * b.mat[3][3]; + + // row 2 + retVal.mat[2][0] = + a.mat[2][0] * b.mat[0][0] + + a.mat[2][1] * b.mat[1][0] + + a.mat[2][2] * b.mat[2][0] + + a.mat[2][3] * b.mat[3][0]; + + retVal.mat[2][1] = + a.mat[2][0] * b.mat[0][1] + + a.mat[2][1] * b.mat[1][1] + + a.mat[2][2] * b.mat[2][1] + + a.mat[2][3] * b.mat[3][1]; + + retVal.mat[2][2] = + a.mat[2][0] * b.mat[0][2] + + a.mat[2][1] * b.mat[1][2] + + a.mat[2][2] * b.mat[2][2] + + a.mat[2][3] * b.mat[3][2]; + + retVal.mat[2][3] = + a.mat[2][0] * b.mat[0][3] + + a.mat[2][1] * b.mat[1][3] + + a.mat[2][2] * b.mat[2][3] + + a.mat[2][3] * b.mat[3][3]; + + // row 3 + retVal.mat[3][0] = + a.mat[3][0] * b.mat[0][0] + + a.mat[3][1] * b.mat[1][0] + + a.mat[3][2] * b.mat[2][0] + + a.mat[3][3] * b.mat[3][0]; + + retVal.mat[3][1] = + a.mat[3][0] * b.mat[0][1] + + a.mat[3][1] * b.mat[1][1] + + a.mat[3][2] * b.mat[2][1] + + a.mat[3][3] * b.mat[3][1]; + + retVal.mat[3][2] = + a.mat[3][0] * b.mat[0][2] + + a.mat[3][1] * b.mat[1][2] + + a.mat[3][2] * b.mat[2][2] + + a.mat[3][3] * b.mat[3][2]; + + retVal.mat[3][3] = + a.mat[3][0] * b.mat[0][3] + + a.mat[3][1] * b.mat[1][3] + + a.mat[3][2] * b.mat[2][3] + + a.mat[3][3] * b.mat[3][3]; + + return retVal; + } + + Matrix4& operator*=(const Matrix4& right) + { + *this = *this * right; + return *this; + } + + // Invert the matrix - super slow + void Invert(); + + // Get the translation component of the matrix + Vector3 GetTranslation() const + { + return Vector3(mat[3][0], mat[3][1], mat[3][2]); + } + + // Get the X axis of the matrix (forward) + Vector3 GetXAxis() const + { + return Vector3::Normalize(Vector3(mat[0][0], mat[0][1], mat[0][2])); + } + + // Get the Y axis of the matrix (left) + Vector3 GetYAxis() const + { + return Vector3::Normalize(Vector3(mat[1][0], mat[1][1], mat[1][2])); + } + + // Get the Z axis of the matrix (up) + Vector3 GetZAxis() const + { + return Vector3::Normalize(Vector3(mat[2][0], mat[2][1], mat[2][2])); + } + + // Extract the scale component from the matrix + Vector3 GetScale() const + { + Vector3 retVal; + retVal.x = Vector3(mat[0][0], mat[0][1], mat[0][2]).Length(); + retVal.y = Vector3(mat[1][0], mat[1][1], mat[1][2]).Length(); + retVal.z = Vector3(mat[2][0], mat[2][1], mat[2][2]).Length(); + return retVal; + } + + // Create a scale matrix with x, y, and z scales + static Matrix4 CreateScale(float xScale, float yScale, float zScale) + { + float temp[4][4] = + { + { xScale, 0.0f, 0.0f, 0.0f }, + { 0.0f, yScale, 0.0f, 0.0f }, + { 0.0f, 0.0f, zScale, 0.0f }, + { 0.0f, 0.0f, 0.0f, 1.0f } + }; + return Matrix4(temp); + } + + static Matrix4 CreateScale(const Vector3& scaleVector) + { + return CreateScale(scaleVector.x, scaleVector.y, scaleVector.z); + } + + // Create a scale matrix with a uniform factor + static Matrix4 CreateScale(float scale) + { + return CreateScale(scale, scale, scale); + } + + // Rotation about x-axis + static Matrix4 CreateRotationX(float theta) + { + float temp[4][4] = + { + { 1.0f, 0.0f, 0.0f , 0.0f }, + { 0.0f, Math::Cos(theta), Math::Sin(theta), 0.0f }, + { 0.0f, -Math::Sin(theta), Math::Cos(theta), 0.0f }, + { 0.0f, 0.0f, 0.0f, 1.0f }, + }; + return Matrix4(temp); + } + + // Rotation about y-axis + static Matrix4 CreateRotationY(float theta) + { + float temp[4][4] = + { + { Math::Cos(theta), 0.0f, -Math::Sin(theta), 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f }, + { Math::Sin(theta), 0.0f, Math::Cos(theta), 0.0f }, + { 0.0f, 0.0f, 0.0f, 1.0f }, + }; + return Matrix4(temp); + } + + // Rotation about z-axis + static Matrix4 CreateRotationZ(float theta) + { + float temp[4][4] = + { + { Math::Cos(theta), Math::Sin(theta), 0.0f, 0.0f }, + { -Math::Sin(theta), Math::Cos(theta), 0.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 1.0f }, + }; + return Matrix4(temp); + } + + // Create a rotation matrix from a quaternion + static Matrix4 CreateFromQuaternion(const class Quaternion& q); + + static Matrix4 CreateTranslation(const Vector3& trans) + { + float temp[4][4] = + { + { 1.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f, 0.0f }, + { trans.x, trans.y, trans.z, 1.0f } + }; + return Matrix4(temp); + } + + static Matrix4 CreateLookAt(const Vector3& eye, const Vector3& target, const Vector3& up) + { + Vector3 zaxis = Vector3::Normalize(target - eye); + Vector3 xaxis = Vector3::Normalize(Vector3::Cross(up, zaxis)); + Vector3 yaxis = Vector3::Normalize(Vector3::Cross(zaxis, xaxis)); + Vector3 trans; + trans.x = -Vector3::Dot(xaxis, eye); + trans.y = -Vector3::Dot(yaxis, eye); + trans.z = -Vector3::Dot(zaxis, eye); + + float temp[4][4] = + { + { xaxis.x, yaxis.x, zaxis.x, 0.0f }, + { xaxis.y, yaxis.y, zaxis.y, 0.0f }, + { xaxis.z, yaxis.z, zaxis.z, 0.0f }, + { trans.x, trans.y, trans.z, 1.0f } + }; + return Matrix4(temp); + } + + static Matrix4 CreateOrtho(float width, float height, float near, float far) + { + float temp[4][4] = + { + { 2.0f / width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f / height, 0.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f / (far - near), 0.0f }, + { 0.0f, 0.0f, near / (near - far), 1.0f } + }; + return Matrix4(temp); + } + + static Matrix4 CreatePerspectiveFOV(float fovY, float width, float height, float near, float far) + { + float yScale = Math::Cot(fovY / 2.0f); + float xScale = yScale * height / width; + float temp[4][4] = + { + { xScale, 0.0f, 0.0f, 0.0f }, + { 0.0f, yScale, 0.0f, 0.0f }, + { 0.0f, 0.0f, far / (far - near), 1.0f }, + { 0.0f, 0.0f, -near * far / (far - near), 0.0f } + }; + return Matrix4(temp); + } + + // Create "Simple" View-Projection Matrix from Chapter 6 + static Matrix4 CreateSimpleViewProj(float width, float height) + { + float temp[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/height, 0.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f, 1.0f } + }; + return Matrix4(temp); + } + + static const Matrix4 Identity; +}; + +// (Unit) Quaternion +class Quaternion +{ +public: + float x; + float y; + float z; + float w; + + Quaternion() + { + *this = Quaternion::Identity; + } + + // This directly sets the quaternion components -- + // don't use for axis/angle + explicit Quaternion(float inX, float inY, float inZ, float inW) + { + Set(inX, inY, inZ, inW); + } + + // Construct the quaternion from an axis and angle + // It is assumed that axis is already normalized, + // and the angle is in radians + explicit Quaternion(const Vector3& axis, float angle) + { + float scalar = Math::Sin(angle / 2.0f); + x = axis.x * scalar; + y = axis.y * scalar; + z = axis.z * scalar; + w = Math::Cos(angle / 2.0f); + } + + // Directly set the internal components + void Set(float inX, float inY, float inZ, float inW) + { + x = inX; + y = inY; + z = inZ; + w = inW; + } + + void Conjugate() + { + x *= -1.0f; + y *= -1.0f; + z *= -1.0f; + } + + float LengthSq() const + { + return (x*x + y*y + z*z + w*w); + } + + float Length() const + { + return Math::Sqrt(LengthSq()); + } + + void Normalize() + { + float length = Length(); + x /= length; + y /= length; + z /= length; + w /= length; + } + + // Normalize the provided quaternion + static Quaternion Normalize(const Quaternion& q) + { + Quaternion retVal = q; + retVal.Normalize(); + return retVal; + } + + // Linear interpolation + static Quaternion Lerp(const Quaternion& a, const Quaternion& b, float f) + { + Quaternion retVal; + retVal.x = Math::Lerp(a.x, b.x, f); + retVal.y = Math::Lerp(a.y, b.y, f); + retVal.z = Math::Lerp(a.z, b.z, f); + retVal.w = Math::Lerp(a.w, b.w, f); + retVal.Normalize(); + return retVal; + } + + static float Dot(const Quaternion& a, const Quaternion& b) + { + return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; + } + + // Spherical Linear Interpolation + static Quaternion Slerp(const Quaternion& a, const Quaternion& b, float f) + { + float rawCosm = Quaternion::Dot(a, b); + + float cosom = -rawCosm; + if (rawCosm >= 0.0f) + { + cosom = rawCosm; + } + + float scale0, scale1; + + if (cosom < 0.9999f) + { + const float omega = Math::Acos(cosom); + const float invSin = 1.f / Math::Sin(omega); + scale0 = Math::Sin((1.f - f) * omega) * invSin; + scale1 = Math::Sin(f * omega) * invSin; + } + else + { + // Use linear interpolation if the quaternions + // are collinear + scale0 = 1.0f - f; + scale1 = f; + } + + if (rawCosm < 0.0f) + { + scale1 = -scale1; + } + + Quaternion retVal; + retVal.x = scale0 * a.x + scale1 * b.x; + retVal.y = scale0 * a.y + scale1 * b.y; + retVal.z = scale0 * a.z + scale1 * b.z; + retVal.w = scale0 * a.w + scale1 * b.w; + retVal.Normalize(); + return retVal; + } + + // Concatenate + // Rotate by q FOLLOWED BY p + static Quaternion Concatenate(const Quaternion& q, const Quaternion& p) + { + Quaternion retVal; + + // Vector component is: + // ps * qv + qs * pv + pv x qv + Vector3 qv(q.x, q.y, q.z); + Vector3 pv(p.x, p.y, p.z); + Vector3 newVec = p.w * qv + q.w * pv + Vector3::Cross(pv, qv); + retVal.x = newVec.x; + retVal.y = newVec.y; + retVal.z = newVec.z; + + // Scalar component is: + // ps * qs - pv . qv + retVal.w = p.w * q.w - Vector3::Dot(pv, qv); + + return retVal; + } + + static const Quaternion Identity; +}; + +namespace Color +{ + static const Vector3 Black(0.0f, 0.0f, 0.0f); + static const Vector3 White(1.0f, 1.0f, 1.0f); + static const Vector3 Red(1.0f, 0.0f, 0.0f); + static const Vector3 Green(0.0f, 1.0f, 0.0f); + static const Vector3 Blue(0.0f, 0.0f, 1.0f); + static const Vector3 Yellow(1.0f, 1.0f, 0.0f); + static const Vector3 LightYellow(1.0f, 1.0f, 0.88f); + static const Vector3 LightBlue(0.68f, 0.85f, 0.9f); + static const Vector3 LightPink(1.0f, 0.71f, 0.76f); + static const Vector3 LightGreen(0.56f, 0.93f, 0.56f); +} diff --git a/Chapter06/Mesh.cpp b/Chapter06/Mesh.cpp new file mode 100644 index 00000000..1673b2b2 --- /dev/null +++ b/Chapter06/Mesh.cpp @@ -0,0 +1,175 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#include "Mesh.h" +#include "Renderer.h" +#include "Texture.h" +#include "VertexArray.h" +#include +#include +#include +#include +#include "Math.h" + +Mesh::Mesh() + :mVertexArray(nullptr) + ,mRadius(0.0f) + ,mSpecPower(100.0f) +{ +} + +Mesh::~Mesh() +{ +} + +bool Mesh::Load(const std::string & fileName, Renderer* renderer) +{ + std::ifstream file(fileName); + if (!file.is_open()) + { + SDL_Log("File not found: Mesh %s", fileName.c_str()); + return false; + } + + std::stringstream fileStream; + fileStream << file.rdbuf(); + std::string contents = fileStream.str(); + rapidjson::StringStream jsonStr(contents.c_str()); + rapidjson::Document doc; + doc.ParseStream(jsonStr); + + if (!doc.IsObject()) + { + SDL_Log("Mesh %s is not valid json", fileName.c_str()); + return false; + } + + int ver = doc["version"].GetInt(); + + // Check the version + if (ver != 1) + { + SDL_Log("Mesh %s not version 1", fileName.c_str()); + return false; + } + + mShaderName = doc["shader"].GetString(); + + // Skip the vertex format/shader for now + // (This is changed in a later chapter's code) + size_t vertSize = 8; + + // Load textures + const rapidjson::Value& textures = doc["textures"]; + if (!textures.IsArray() || textures.Size() < 1) + { + SDL_Log("Mesh %s has no textures, there should be at least one", fileName.c_str()); + return false; + } + + mSpecPower = static_cast(doc["specularPower"].GetDouble()); + + for (rapidjson::SizeType i = 0; i < textures.Size(); i++) + { + // Is this texture already loaded? + std::string texName = textures[i].GetString(); + Texture* t = renderer->GetTexture(texName); + if (t == nullptr) + { + // Try loading the texture + t = renderer->GetTexture(texName); + if (t == nullptr) + { + // If it's still null, just use the default texture + t = renderer->GetTexture("Assets/Default.png"); + } + } + mTextures.emplace_back(t); + } + + // Load in the vertices + const rapidjson::Value& vertsJson = doc["vertices"]; + if (!vertsJson.IsArray() || vertsJson.Size() < 1) + { + SDL_Log("Mesh %s has no vertices", fileName.c_str()); + return false; + } + + std::vector vertices; + vertices.reserve(vertsJson.Size() * vertSize); + mRadius = 0.0f; + for (rapidjson::SizeType i = 0; i < vertsJson.Size(); i++) + { + // For now, just assume we have 8 elements + const rapidjson::Value& vert = vertsJson[i]; + if (!vert.IsArray() || vert.Size() != 8) + { + SDL_Log("Unexpected vertex format for %s", fileName.c_str()); + return false; + } + + Vector3 pos(vert[0].GetDouble(), vert[1].GetDouble(), vert[2].GetDouble()); + mRadius = Math::Max(mRadius, pos.LengthSq()); + + // Add the floats + for (rapidjson::SizeType i = 0; i < vert.Size(); i++) + { + vertices.emplace_back(static_cast(vert[i].GetDouble())); + } + } + + // We were computing length squared earlier + mRadius = Math::Sqrt(mRadius); + + // Load in the indices + const rapidjson::Value& indJson = doc["indices"]; + if (!indJson.IsArray() || indJson.Size() < 1) + { + SDL_Log("Mesh %s has no indices", fileName.c_str()); + return false; + } + + std::vector indices; + indices.reserve(indJson.Size() * 3); + for (rapidjson::SizeType i = 0; i < indJson.Size(); i++) + { + const rapidjson::Value& ind = indJson[i]; + if (!ind.IsArray() || ind.Size() != 3) + { + SDL_Log("Invalid indices for %s", fileName.c_str()); + return false; + } + + indices.emplace_back(ind[0].GetUint()); + indices.emplace_back(ind[1].GetUint()); + indices.emplace_back(ind[2].GetUint()); + } + + // Now create a vertex array + mVertexArray = new VertexArray(vertices.data(), static_cast(vertices.size()) / vertSize, + indices.data(), static_cast(indices.size())); + return true; +} + +void Mesh::Unload() +{ + delete mVertexArray; + mVertexArray = nullptr; +} + +Texture* Mesh::GetTexture(size_t index) +{ + if (index < mTextures.size()) + { + return mTextures[index]; + } + else + { + return nullptr; + } +} diff --git a/Chapter06/Mesh.h b/Chapter06/Mesh.h new file mode 100644 index 00000000..3c1b5a3e --- /dev/null +++ b/Chapter06/Mesh.h @@ -0,0 +1,42 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#pragma once +#include +#include + +class Mesh +{ +public: + Mesh(); + ~Mesh(); + // Load/unload mesh + bool Load(const std::string& fileName, class Renderer* renderer); + void Unload(); + // Get the vertex array associated with this mesh + class VertexArray* GetVertexArray() { return mVertexArray; } + // Get a texture from specified index + class Texture* GetTexture(size_t index); + // Get name of shader + const std::string& GetShaderName() const { return mShaderName; } + // Get object space bounding sphere radius + float GetRadius() const { return mRadius; } + // Get specular power of mesh + float GetSpecPower() const { return mSpecPower; } +private: + // Textures associated with this mesh + std::vector mTextures; + // Vertex array associated with this mesh + class VertexArray* mVertexArray; + // Name of shader specified by mesh + std::string mShaderName; + // Stores object space bounding sphere radius + float mRadius; + // Specular power of surface + float mSpecPower; +}; \ No newline at end of file diff --git a/Chapter06/MeshComponent.cpp b/Chapter06/MeshComponent.cpp new file mode 100644 index 00000000..1f4cbdb2 --- /dev/null +++ b/Chapter06/MeshComponent.cpp @@ -0,0 +1,52 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#include "MeshComponent.h" +#include "Shader.h" +#include "Mesh.h" +#include "Actor.h" +#include "Game.h" +#include "Renderer.h" +#include "Texture.h" +#include "VertexArray.h" + +MeshComponent::MeshComponent(Actor* owner) + :Component(owner) + ,mMesh(nullptr) + ,mTextureIndex(0) +{ + mOwner->GetGame()->GetRenderer()->AddMeshComp(this); +} + +MeshComponent::~MeshComponent() +{ + mOwner->GetGame()->GetRenderer()->RemoveMeshComp(this); +} + +void MeshComponent::Draw(Shader* shader) +{ + if (mMesh) + { + // Set the world transform + shader->SetMatrixUniform("uWorldTransform", + mOwner->GetWorldTransform()); + // Set specular power + shader->SetFloatUniform("uSpecPower", mMesh->GetSpecPower()); + // Set the active texture + Texture* t = mMesh->GetTexture(mTextureIndex); + if (t) + { + t->SetActive(); + } + // Set the mesh's vertex array as active + VertexArray* va = mMesh->GetVertexArray(); + va->SetActive(); + // Draw + glDrawElements(GL_TRIANGLES, va->GetNumIndices(), GL_UNSIGNED_INT, nullptr); + } +} diff --git a/Chapter06/MeshComponent.h b/Chapter06/MeshComponent.h new file mode 100644 index 00000000..48765568 --- /dev/null +++ b/Chapter06/MeshComponent.h @@ -0,0 +1,26 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#pragma once +#include "Component.h" +#include + +class MeshComponent : public Component +{ +public: + MeshComponent(class Actor* owner); + ~MeshComponent(); + // Draw this mesh component + virtual void Draw(class Shader* shader); + // Set the mesh/texture index used by mesh component + virtual void SetMesh(class Mesh* mesh) { mMesh = mesh; } + void SetTextureIndex(size_t index) { mTextureIndex = index; } +protected: + class Mesh* mMesh; + size_t mTextureIndex; +}; diff --git a/Chapter06/MoveComponent.cpp b/Chapter06/MoveComponent.cpp new file mode 100644 index 00000000..5b51c6fc --- /dev/null +++ b/Chapter06/MoveComponent.cpp @@ -0,0 +1,40 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#include "MoveComponent.h" +#include "Actor.h" + +MoveComponent::MoveComponent(class Actor* owner, int updateOrder) +:Component(owner, updateOrder) +,mAngularSpeed(0.0f) +,mForwardSpeed(0.0f) +{ + +} + +void MoveComponent::Update(float deltaTime) +{ + if (!Math::NearZero(mAngularSpeed)) + { + Quaternion rot = mOwner->GetRotation(); + float angle = mAngularSpeed * deltaTime; + // Create quaternion for incremental rotation + // (Rotate about up axis) + Quaternion inc(Vector3::UnitZ, angle); + // Concatenate old and new quaternion + rot = Quaternion::Concatenate(rot, inc); + mOwner->SetRotation(rot); + } + + if (!Math::NearZero(mForwardSpeed)) + { + Vector3 pos = mOwner->GetPosition(); + pos += mOwner->GetForward() * mForwardSpeed * deltaTime; + mOwner->SetPosition(pos); + } +} diff --git a/Chapter06/MoveComponent.h b/Chapter06/MoveComponent.h new file mode 100644 index 00000000..def7d389 --- /dev/null +++ b/Chapter06/MoveComponent.h @@ -0,0 +1,26 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#pragma once +#include "Component.h" + +class MoveComponent : public Component +{ +public: + // Lower update order to update first + MoveComponent(class Actor* owner, int updateOrder = 10); + void Update(float deltaTime) override; + + float GetAngularSpeed() const { return mAngularSpeed; } + float GetForwardSpeed() const { return mForwardSpeed; } + void SetAngularSpeed(float speed) { mAngularSpeed = speed; } + void SetForwardSpeed(float speed) { mForwardSpeed = speed; } +private: + float mAngularSpeed; + float mForwardSpeed; +}; diff --git a/Chapter06/PlaneActor.cpp b/Chapter06/PlaneActor.cpp new file mode 100644 index 00000000..5398ca4c --- /dev/null +++ b/Chapter06/PlaneActor.cpp @@ -0,0 +1,20 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#include "PlaneActor.h" +#include "Game.h" +#include "Renderer.h" +#include "MeshComponent.h" + +PlaneActor::PlaneActor(Game* game) + :Actor(game) +{ + SetScale(10.0f); + MeshComponent* mc = new MeshComponent(this); + mc->SetMesh(GetGame()->GetRenderer()->GetMesh("Assets/Plane.gpmesh")); +} diff --git a/Chapter06/PlaneActor.h b/Chapter06/PlaneActor.h new file mode 100644 index 00000000..8187b64a --- /dev/null +++ b/Chapter06/PlaneActor.h @@ -0,0 +1,16 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#pragma once +#include "Actor.h" + +class PlaneActor : public Actor +{ +public: + PlaneActor(class Game* game); +}; \ No newline at end of file diff --git a/Chapter06/Renderer.cpp b/Chapter06/Renderer.cpp new file mode 100644 index 00000000..43a25fe8 --- /dev/null +++ b/Chapter06/Renderer.cpp @@ -0,0 +1,307 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#include "Renderer.h" +#include "Texture.h" +#include "Mesh.h" +#include +#include "Shader.h" +#include "VertexArray.h" +#include "SpriteComponent.h" +#include "MeshComponent.h" +#include + +Renderer::Renderer(Game* game) + :mGame(game) + ,mSpriteShader(nullptr) + ,mMeshShader(nullptr) +{ +} + +Renderer::~Renderer() +{ +} + +bool Renderer::Initialize(float screenWidth, float screenHeight) +{ + mScreenWidth = screenWidth; + mScreenHeight = screenHeight; + + // Set OpenGL attributes + // Use the core OpenGL profile + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + // Specify version 3.3 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + // Request a color buffer with 8-bits per RGBA channel + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + // Enable double buffering + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + // Force OpenGL to use hardware acceleration + SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); + + mWindow = SDL_CreateWindow("Game Programming in C++ (Chapter 6)", 100, 100, + static_cast(mScreenWidth), static_cast(mScreenHeight), SDL_WINDOW_OPENGL); + if (!mWindow) + { + SDL_Log("Failed to create window: %s", SDL_GetError()); + return false; + } + + // Create an OpenGL context + mContext = SDL_GL_CreateContext(mWindow); + + // Initialize GLEW + glewExperimental = GL_TRUE; + if (glewInit() != GLEW_OK) + { + SDL_Log("Failed to initialize GLEW."); + return false; + } + + // On some platforms, GLEW will emit a benign error code, + // so clear it + glGetError(); + + // Make sure we can create/compile shaders + if (!LoadShaders()) + { + SDL_Log("Failed to load shaders."); + return false; + } + + // Create quad for drawing sprites + CreateSpriteVerts(); + + return true; +} + +void Renderer::Shutdown() +{ + delete mSpriteVerts; + mSpriteShader->Unload(); + delete mSpriteShader; + mMeshShader->Unload(); + delete mMeshShader; + SDL_GL_DeleteContext(mContext); + SDL_DestroyWindow(mWindow); +} + +void Renderer::UnloadData() +{ + // Destroy textures + for (auto i : mTextures) + { + i.second->Unload(); + delete i.second; + } + mTextures.clear(); + + // Destroy meshes + for (auto i : mMeshes) + { + i.second->Unload(); + delete i.second; + } + mMeshes.clear(); +} + +void Renderer::Draw() +{ + // Set the clear color to light grey + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + // Clear the color buffer + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Draw mesh components + // Enable depth buffering/disable alpha blend + glEnable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + // Set the mesh shader active + mMeshShader->SetActive(); + // Update view-projection matrix + mMeshShader->SetMatrixUniform("uViewProj", mView * mProjection); + // Update lighting uniforms + SetLightUniforms(mMeshShader); + for (auto mc : mMeshComps) + { + mc->Draw(mMeshShader); + } + + // Draw all sprite components + // Disable depth buffering + glDisable(GL_DEPTH_TEST); + // Enable alpha blending on the color buffer + glEnable(GL_BLEND); + glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO); + + // Set shader/vao as active + mSpriteShader->SetActive(); + mSpriteVerts->SetActive(); + for (auto sprite : mSprites) + { + sprite->Draw(mSpriteShader); + } + + // Swap the buffers + SDL_GL_SwapWindow(mWindow); +} + +void Renderer::AddSprite(SpriteComponent* sprite) +{ + // Find the insertion point in the sorted vector + // (The first element with a higher draw order than me) + int myDrawOrder = sprite->GetDrawOrder(); + auto iter = mSprites.begin(); + for (; + iter != mSprites.end(); + ++iter) + { + if (myDrawOrder < (*iter)->GetDrawOrder()) + { + break; + } + } + + // Inserts element before position of iterator + mSprites.insert(iter, sprite); +} + +void Renderer::RemoveSprite(SpriteComponent* sprite) +{ + auto iter = std::find(mSprites.begin(), mSprites.end(), sprite); + mSprites.erase(iter); +} + +void Renderer::AddMeshComp(MeshComponent* mesh) +{ + mMeshComps.emplace_back(mesh); +} + +void Renderer::RemoveMeshComp(MeshComponent* mesh) +{ + auto iter = std::find(mMeshComps.begin(), mMeshComps.end(), mesh); + mMeshComps.erase(iter); +} + +Texture* Renderer::GetTexture(const std::string& fileName) +{ + Texture* tex = nullptr; + auto iter = mTextures.find(fileName); + if (iter != mTextures.end()) + { + tex = iter->second; + } + else + { + tex = new Texture(); + if (tex->Load(fileName)) + { + mTextures.emplace(fileName, tex); + } + else + { + delete tex; + tex = nullptr; + } + } + return tex; +} + +Mesh* Renderer::GetMesh(const std::string & fileName) +{ + Mesh* m = nullptr; + auto iter = mMeshes.find(fileName); + if (iter != mMeshes.end()) + { + m = iter->second; + } + else + { + m = new Mesh(); + if (m->Load(fileName, this)) + { + mMeshes.emplace(fileName, m); + } + else + { + delete m; + m = nullptr; + } + } + return m; +} + +bool Renderer::LoadShaders() +{ + // Create sprite shader + mSpriteShader = new Shader(); + if (!mSpriteShader->Load("Shaders/Sprite.vert", "Shaders/Sprite.frag")) + { + return false; + } + + mSpriteShader->SetActive(); + // Set the view-projection matrix + Matrix4 viewProj = Matrix4::CreateSimpleViewProj(mScreenWidth, mScreenHeight); + mSpriteShader->SetMatrixUniform("uViewProj", viewProj); + + // Create basic mesh shader + mMeshShader = new Shader(); + if (!mMeshShader->Load("Shaders/Phong.vert", "Shaders/Phong.frag")) + { + return false; + } + + mMeshShader->SetActive(); + // Set the view-projection matrix + mView = Matrix4::CreateLookAt(Vector3::Zero, Vector3::UnitX, Vector3::UnitZ); + mProjection = Matrix4::CreatePerspectiveFOV(Math::ToRadians(70.0f), + mScreenWidth, mScreenHeight, 25.0f, 10000.0f); + mMeshShader->SetMatrixUniform("uViewProj", mView * mProjection); + return true; +} + +void Renderer::CreateSpriteVerts() +{ + float vertices[] = { + -0.5f, 0.5f, 0.f, 0.f, 0.f, 0.0f, 0.f, 0.f, // top left + 0.5f, 0.5f, 0.f, 0.f, 0.f, 0.0f, 1.f, 0.f, // top right + 0.5f,-0.5f, 0.f, 0.f, 0.f, 0.0f, 1.f, 1.f, // bottom right + -0.5f,-0.5f, 0.f, 0.f, 0.f, 0.0f, 0.f, 1.f // bottom left + }; + + unsigned int indices[] = { + 0, 1, 2, + 2, 3, 0 + }; + + mSpriteVerts = new VertexArray(vertices, 4, indices, 6); +} + +void Renderer::SetLightUniforms(Shader* shader) +{ + // Camera position is from inverted view + Matrix4 invView = mView; + invView.Invert(); + shader->SetVectorUniform("uCameraPos", invView.GetTranslation()); + // Ambient light + shader->SetVectorUniform("uAmbientLight", mAmbientLight); + // Directional light + shader->SetVectorUniform("uDirLight.mDirection", + mDirLight.mDirection); + shader->SetVectorUniform("uDirLight.mDiffuseColor", + mDirLight.mDiffuseColor); + shader->SetVectorUniform("uDirLight.mSpecColor", + mDirLight.mSpecColor); +} diff --git a/Chapter06/Renderer.h b/Chapter06/Renderer.h new file mode 100644 index 00000000..12746df2 --- /dev/null +++ b/Chapter06/Renderer.h @@ -0,0 +1,96 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#pragma once +#include +#include +#include +#include +#include "Math.h" + +struct DirectionalLight +{ + // Direction of light + Vector3 mDirection; + // Diffuse color + Vector3 mDiffuseColor; + // Specular color + Vector3 mSpecColor; +}; + +class Renderer +{ +public: + Renderer(class Game* game); + ~Renderer(); + + bool Initialize(float screenWidth, float screenHeight); + void Shutdown(); + void UnloadData(); + + void Draw(); + + void AddSprite(class SpriteComponent* sprite); + void RemoveSprite(class SpriteComponent* sprite); + + void AddMeshComp(class MeshComponent* mesh); + void RemoveMeshComp(class MeshComponent* mesh); + + class Texture* GetTexture(const std::string& fileName); + class Mesh* GetMesh(const std::string& fileName); + + void SetViewMatrix(const Matrix4& view) { mView = view; } + + void SetAmbientLight(const Vector3& ambient) { mAmbientLight = ambient; } + DirectionalLight& GetDirectionalLight() { return mDirLight; } + + float GetScreenWidth() const { return mScreenWidth; } + float GetScreenHeight() const { return mScreenHeight; } +private: + bool LoadShaders(); + void CreateSpriteVerts(); + void SetLightUniforms(class Shader* shader); + + // Map of textures loaded + std::unordered_map mTextures; + // Map of meshes loaded + std::unordered_map mMeshes; + + // All the sprite components drawn + std::vector mSprites; + + // All mesh components drawn + std::vector mMeshComps; + + // Game + class Game* mGame; + + // Sprite shader + class Shader* mSpriteShader; + // Sprite vertex array + class VertexArray* mSpriteVerts; + + // Mesh shader + class Shader* mMeshShader; + + // View/projection for 3D shaders + Matrix4 mView; + Matrix4 mProjection; + // Width/height of screen + float mScreenWidth; + float mScreenHeight; + + // Lighting data + Vector3 mAmbientLight; + DirectionalLight mDirLight; + + // Window + SDL_Window* mWindow; + // OpenGL context + SDL_GLContext mContext; +}; \ No newline at end of file diff --git a/Chapter06/Shader.cpp b/Chapter06/Shader.cpp new file mode 100644 index 00000000..cae3ac07 --- /dev/null +++ b/Chapter06/Shader.cpp @@ -0,0 +1,162 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#include "Shader.h" +#include "Texture.h" +#include +#include +#include + +Shader::Shader() + : mShaderProgram(0) + , mVertexShader(0) + , mFragShader(0) +{ + +} + +Shader::~Shader() +{ + +} + +bool Shader::Load(const std::string& vertName, const std::string& fragName) +{ + // Compile vertex and pixel shaders + if (!CompileShader(vertName, + GL_VERTEX_SHADER, + mVertexShader) || + !CompileShader(fragName, + GL_FRAGMENT_SHADER, + mFragShader)) + { + return false; + } + + // Now create a shader program that + // links together the vertex/frag shaders + mShaderProgram = glCreateProgram(); + glAttachShader(mShaderProgram, mVertexShader); + glAttachShader(mShaderProgram, mFragShader); + glLinkProgram(mShaderProgram); + + // Verify that the program linked successfully + if (!IsValidProgram()) + { + return false; + } + + return true; +} + +void Shader::Unload() +{ + // Delete the program/shaders + glDeleteProgram(mShaderProgram); + glDeleteShader(mVertexShader); + glDeleteShader(mFragShader); +} + +void Shader::SetActive() +{ + // Set this program as the active one + glUseProgram(mShaderProgram); +} + +void Shader::SetMatrixUniform(const char* name, const Matrix4& matrix) +{ + // Find the uniform by this name + GLuint loc = glGetUniformLocation(mShaderProgram, name); + // Send the matrix data to the uniform + glUniformMatrix4fv(loc, 1, GL_TRUE, matrix.GetAsFloatPtr()); +} + +void Shader::SetVectorUniform(const char* name, const Vector3& vector) +{ + GLuint loc = glGetUniformLocation(mShaderProgram, name); + // Send the vector data + glUniform3fv(loc, 1, vector.GetAsFloatPtr()); +} + +void Shader::SetFloatUniform(const char* name, float value) +{ + GLuint loc = glGetUniformLocation(mShaderProgram, name); + // Send the float data + glUniform1f(loc, value); +} + +bool Shader::CompileShader(const std::string& fileName, + GLenum shaderType, + GLuint& outShader) +{ + // Open file + std::ifstream shaderFile(fileName); + if (shaderFile.is_open()) + { + // Read all the text into a string + std::stringstream sstream; + sstream << shaderFile.rdbuf(); + std::string contents = sstream.str(); + const char* contentsChar = contents.c_str(); + + // Create a shader of the specified type + outShader = glCreateShader(shaderType); + // Set the source characters and try to compile + glShaderSource(outShader, 1, &(contentsChar), nullptr); + glCompileShader(outShader); + + if (!IsCompiled(outShader)) + { + SDL_Log("Failed to compile shader %s", fileName.c_str()); + return false; + } + } + else + { + SDL_Log("Shader file not found: %s", fileName.c_str()); + return false; + } + + return true; +} + +bool Shader::IsCompiled(GLuint shader) +{ + GLint status; + // Query the compile status + glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + + if (status != GL_TRUE) + { + char buffer[512]; + memset(buffer, 0, 512); + glGetShaderInfoLog(shader, 511, nullptr, buffer); + SDL_Log("GLSL Compile Failed:\n%s", buffer); + return false; + } + + return true; +} + +bool Shader::IsValidProgram() +{ + + GLint status; + // Query the link status + glGetProgramiv(mShaderProgram, GL_LINK_STATUS, &status); + if (status != GL_TRUE) + { + char buffer[512]; + memset(buffer, 0, 512); + glGetProgramInfoLog(mShaderProgram, 511, nullptr, buffer); + SDL_Log("GLSL Link Status:\n%s", buffer); + return false; + } + + return true; +} diff --git a/Chapter06/Shader.h b/Chapter06/Shader.h new file mode 100644 index 00000000..929c9e41 --- /dev/null +++ b/Chapter06/Shader.h @@ -0,0 +1,45 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#pragma once +#include +#include +#include "Math.h" + +class Shader +{ +public: + Shader(); + ~Shader(); + // Load the vertex/fragment shaders with the given names + bool Load(const std::string& vertName, const std::string& fragName); + void Unload(); + // Set this as the active shader program + void SetActive(); + // Sets a Matrix uniform + void SetMatrixUniform(const char* name, const Matrix4& matrix); + // Sets a Vector3 uniform + void SetVectorUniform(const char* name, const Vector3& vector); + // Sets a float uniform + void SetFloatUniform(const char* name, float value); +private: + // Tries to compile the specified shader + bool CompileShader(const std::string& fileName, + GLenum shaderType, + GLuint& outShader); + + // Tests whether shader compiled successfully + bool IsCompiled(GLuint shader); + // Tests whether vertex/fragment programs link + bool IsValidProgram(); +private: + // Store the shader object IDs + GLuint mVertexShader; + GLuint mFragShader; + GLuint mShaderProgram; +}; diff --git a/Chapter06/Shaders/BasicMesh.frag b/Chapter06/Shaders/BasicMesh.frag new file mode 100644 index 00000000..b1bd6105 --- /dev/null +++ b/Chapter06/Shaders/BasicMesh.frag @@ -0,0 +1,25 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE.txt for full details. +// ---------------------------------------------------------------- + +// Request GLSL 3.3 +#version 330 + +// Tex coord input from vertex shader +in vec2 fragTexCoord; + +// This corresponds to the output color to the color buffer +out vec4 outColor; + +// This is used for the texture sampling +uniform sampler2D uTexture; + +void main() +{ + // Sample color from texture + outColor = texture(uTexture, fragTexCoord); +} diff --git a/Chapter06/Shaders/BasicMesh.vert b/Chapter06/Shaders/BasicMesh.vert new file mode 100644 index 00000000..428db6fa --- /dev/null +++ b/Chapter06/Shaders/BasicMesh.vert @@ -0,0 +1,33 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE.txt for full details. +// ---------------------------------------------------------------- + +// Request GLSL 3.3 +#version 330 + +// Uniforms for world transform and view-proj +uniform mat4 uWorldTransform; +uniform mat4 uViewProj; + +// Attribute 0 is position, 1 is normal, 2 is tex coords. +layout(location = 0) in vec3 inPosition; +layout(location = 1) in vec3 inNormal; +layout(location = 2) in vec2 inTexCoord; + +// Any vertex outputs (other than position) +out vec2 fragTexCoord; + +void main() +{ + // Convert position to homogeneous coordinates + vec4 pos = vec4(inPosition, 1.0); + // Transform to position world space, then clip space + gl_Position = pos * uWorldTransform * uViewProj; + + // Pass along the texture coordinate to frag shader + fragTexCoord = inTexCoord; +} diff --git a/Chapter06/Shaders/Phong.frag b/Chapter06/Shaders/Phong.frag new file mode 100644 index 00000000..4b334fe0 --- /dev/null +++ b/Chapter06/Shaders/Phong.frag @@ -0,0 +1,71 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE.txt for full details. +// ---------------------------------------------------------------- + +// Request GLSL 3.3 +#version 330 + +// Inputs from vertex shader +// Tex coord +in vec2 fragTexCoord; +// Normal (in world space) +in vec3 fragNormal; +// Position (in world space) +in vec3 fragWorldPos; + +// This corresponds to the output color to the color buffer +out vec4 outColor; + +// This is used for the texture sampling +uniform sampler2D uTexture; + +// Create a struct for directional light +struct DirectionalLight +{ + // Direction of light + vec3 mDirection; + // Diffuse color + vec3 mDiffuseColor; + // Specular color + vec3 mSpecColor; +}; + +// Uniforms for lighting +// Camera position (in world space) +uniform vec3 uCameraPos; +// Specular power for this surface +uniform float uSpecPower; +// Ambient light level +uniform vec3 uAmbientLight; + +// Directional Light +uniform DirectionalLight uDirLight; + +void main() +{ + // Surface normal + vec3 N = normalize(fragNormal); + // Vector from surface to light + vec3 L = normalize(-uDirLight.mDirection); + // Vector from surface to camera + vec3 V = normalize(uCameraPos - fragWorldPos); + // Reflection of -L about N + vec3 R = normalize(reflect(-L, N)); + + // Compute phong reflection + vec3 Phong = uAmbientLight; + float NdotL = dot(N, L); + if (NdotL > 0) + { + vec3 Diffuse = uDirLight.mDiffuseColor * NdotL; + vec3 Specular = uDirLight.mSpecColor * pow(max(0.0, dot(R, V)), uSpecPower); + Phong += Diffuse + Specular; + } + + // Final color is texture color times phong light (alpha = 1) + outColor = texture(uTexture, fragTexCoord) * vec4(Phong, 1.0f); +} diff --git a/Chapter06/Shaders/Phong.vert b/Chapter06/Shaders/Phong.vert new file mode 100644 index 00000000..b88067e2 --- /dev/null +++ b/Chapter06/Shaders/Phong.vert @@ -0,0 +1,44 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE.txt for full details. +// ---------------------------------------------------------------- + +// Request GLSL 3.3 +#version 330 + +// Uniforms for world transform and view-proj +uniform mat4 uWorldTransform; +uniform mat4 uViewProj; + +// Attribute 0 is position, 1 is normal, 2 is tex coords. +layout(location = 0) in vec3 inPosition; +layout(location = 1) in vec3 inNormal; +layout(location = 2) in vec2 inTexCoord; + +// Any vertex outputs (other than position) +out vec2 fragTexCoord; +// Normal (in world space) +out vec3 fragNormal; +// Position (in world space) +out vec3 fragWorldPos; + +void main() +{ + // Convert position to homogeneous coordinates + vec4 pos = vec4(inPosition, 1.0); + // Transform position to world space + pos = pos * uWorldTransform; + // Save world position + fragWorldPos = pos.xyz; + // Transform to clip space + gl_Position = pos * uViewProj; + + // Transform normal into world space (w = 0) + fragNormal = (vec4(inNormal, 0.0f) * uWorldTransform).xyz; + + // Pass along the texture coordinate to frag shader + fragTexCoord = inTexCoord; +} diff --git a/Chapter06/Shaders/Sprite.frag b/Chapter06/Shaders/Sprite.frag new file mode 100644 index 00000000..b1bd6105 --- /dev/null +++ b/Chapter06/Shaders/Sprite.frag @@ -0,0 +1,25 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE.txt for full details. +// ---------------------------------------------------------------- + +// Request GLSL 3.3 +#version 330 + +// Tex coord input from vertex shader +in vec2 fragTexCoord; + +// This corresponds to the output color to the color buffer +out vec4 outColor; + +// This is used for the texture sampling +uniform sampler2D uTexture; + +void main() +{ + // Sample color from texture + outColor = texture(uTexture, fragTexCoord); +} diff --git a/Chapter06/Shaders/Sprite.vert b/Chapter06/Shaders/Sprite.vert new file mode 100644 index 00000000..428db6fa --- /dev/null +++ b/Chapter06/Shaders/Sprite.vert @@ -0,0 +1,33 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE.txt for full details. +// ---------------------------------------------------------------- + +// Request GLSL 3.3 +#version 330 + +// Uniforms for world transform and view-proj +uniform mat4 uWorldTransform; +uniform mat4 uViewProj; + +// Attribute 0 is position, 1 is normal, 2 is tex coords. +layout(location = 0) in vec3 inPosition; +layout(location = 1) in vec3 inNormal; +layout(location = 2) in vec2 inTexCoord; + +// Any vertex outputs (other than position) +out vec2 fragTexCoord; + +void main() +{ + // Convert position to homogeneous coordinates + vec4 pos = vec4(inPosition, 1.0); + // Transform to position world space, then clip space + gl_Position = pos * uWorldTransform * uViewProj; + + // Pass along the texture coordinate to frag shader + fragTexCoord = inTexCoord; +} diff --git a/Chapter06/SpriteComponent.cpp b/Chapter06/SpriteComponent.cpp new file mode 100644 index 00000000..eb7b77aa --- /dev/null +++ b/Chapter06/SpriteComponent.cpp @@ -0,0 +1,61 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#include "SpriteComponent.h" +#include "Texture.h" +#include "Shader.h" +#include "Actor.h" +#include "Game.h" +#include "Renderer.h" + +SpriteComponent::SpriteComponent(Actor* owner, int drawOrder) + :Component(owner) + ,mTexture(nullptr) + ,mDrawOrder(drawOrder) + ,mTexWidth(0) + ,mTexHeight(0) +{ + mOwner->GetGame()->GetRenderer()->AddSprite(this); +} + +SpriteComponent::~SpriteComponent() +{ + mOwner->GetGame()->GetRenderer()->RemoveSprite(this); +} + +void SpriteComponent::Draw(Shader* shader) +{ + if (mTexture) + { + // Scale the quad by the width/height of texture + Matrix4 scaleMat = Matrix4::CreateScale( + static_cast(mTexWidth), + static_cast(mTexHeight), + 1.0f); + + Matrix4 world = scaleMat * mOwner->GetWorldTransform(); + + // Since all sprites use the same shader/vertices, + // the game first sets them active before any sprite draws + + // Set world transform + shader->SetMatrixUniform("uWorldTransform", world); + // Set current texture + mTexture->SetActive(); + // Draw quad + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); + } +} + +void SpriteComponent::SetTexture(Texture* texture) +{ + mTexture = texture; + // Set width/height + mTexWidth = texture->GetWidth(); + mTexHeight = texture->GetHeight(); +} diff --git a/Chapter06/SpriteComponent.h b/Chapter06/SpriteComponent.h new file mode 100644 index 00000000..6c5642f2 --- /dev/null +++ b/Chapter06/SpriteComponent.h @@ -0,0 +1,30 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#pragma once +#include "Component.h" +#include "SDL/SDL.h" +class SpriteComponent : public Component +{ +public: + // (Lower draw order corresponds with further back) + SpriteComponent(class Actor* owner, int drawOrder = 100); + ~SpriteComponent(); + + virtual void Draw(class Shader* shader); + virtual void SetTexture(class Texture* texture); + + int GetDrawOrder() const { return mDrawOrder; } + int GetTexHeight() const { return mTexHeight; } + int GetTexWidth() const { return mTexWidth; } +protected: + class Texture* mTexture; + int mDrawOrder; + int mTexWidth; + int mTexHeight; +}; diff --git a/Chapter06/Texture.cpp b/Chapter06/Texture.cpp new file mode 100644 index 00000000..ddde35f0 --- /dev/null +++ b/Chapter06/Texture.cpp @@ -0,0 +1,69 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#include "Texture.h" +#include +#include +#include + +Texture::Texture() +:mTextureID(0) +,mWidth(0) +,mHeight(0) +{ + +} + +Texture::~Texture() +{ + +} + +bool Texture::Load(const std::string& fileName) +{ + int channels = 0; + + unsigned char* image = SOIL_load_image(fileName.c_str(), + &mWidth, &mHeight, &channels, SOIL_LOAD_AUTO); + + if (image == nullptr) + { + SDL_Log("SOIL failed to load image %s: %s", fileName.c_str(), SOIL_last_result()); + return false; + } + + int format = GL_RGB; + if (channels == 4) + { + format = GL_RGBA; + } + + glGenTextures(1, &mTextureID); + glBindTexture(GL_TEXTURE_2D, mTextureID); + + glTexImage2D(GL_TEXTURE_2D, 0, format, mWidth, mHeight, 0, format, + GL_UNSIGNED_BYTE, image); + + SOIL_free_image_data(image); + + // Enable linear filtering + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + return true; +} + +void Texture::Unload() +{ + glDeleteTextures(1, &mTextureID); +} + +void Texture::SetActive() +{ + glBindTexture(GL_TEXTURE_2D, mTextureID); +} diff --git a/Chapter06/Texture.h b/Chapter06/Texture.h new file mode 100644 index 00000000..6c8892fd --- /dev/null +++ b/Chapter06/Texture.h @@ -0,0 +1,28 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#include + +class Texture +{ +public: + Texture(); + ~Texture(); + + bool Load(const std::string& fileName); + void Unload(); + + void SetActive(); + + int GetWidth() const { return mWidth; } + int GetHeight() const { return mHeight; } +private: + unsigned int mTextureID; + int mWidth; + int mHeight; +}; diff --git a/Chapter06/VertexArray.cpp b/Chapter06/VertexArray.cpp new file mode 100644 index 00000000..faddcf6c --- /dev/null +++ b/Chapter06/VertexArray.cpp @@ -0,0 +1,56 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#include "VertexArray.h" +#include + +VertexArray::VertexArray(const float* verts, unsigned int numVerts, + const unsigned int* indices, unsigned int numIndices) + :mNumVerts(numVerts) + ,mNumIndices(numIndices) +{ + // Create vertex array + glGenVertexArrays(1, &mVertexArray); + glBindVertexArray(mVertexArray); + + // Create vertex buffer + glGenBuffers(1, &mVertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer); + glBufferData(GL_ARRAY_BUFFER, numVerts * 8 * sizeof(float), verts, GL_STATIC_DRAW); + + // Create index buffer + glGenBuffers(1, &mIndexBuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof(unsigned int), indices, GL_STATIC_DRAW); + + // Specify the vertex attributes + // (For now, assume one vertex format) + // Position is 3 floats + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), 0); + // Normal is 3 floats + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), + reinterpret_cast(sizeof(float) * 3)); + // Texture coordinates is 2 floats + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), + reinterpret_cast(sizeof(float) * 6)); +} + +VertexArray::~VertexArray() +{ + glDeleteBuffers(1, &mVertexBuffer); + glDeleteBuffers(1, &mIndexBuffer); + glDeleteVertexArrays(1, &mVertexArray); +} + +void VertexArray::SetActive() +{ + glBindVertexArray(mVertexArray); +} diff --git a/Chapter06/VertexArray.h b/Chapter06/VertexArray.h new file mode 100644 index 00000000..5deddc4d --- /dev/null +++ b/Chapter06/VertexArray.h @@ -0,0 +1,31 @@ +// ---------------------------------------------------------------- +// From Game Programming in C++ by Sanjay Madhav +// Copyright (C) 2017 Sanjay Madhav. All rights reserved. +// +// Released under the BSD License +// See LICENSE in root directory for full details. +// ---------------------------------------------------------------- + +#pragma once +class VertexArray +{ +public: + VertexArray(const float* verts, unsigned int numVerts, + const unsigned int* indices, unsigned int numIndices); + ~VertexArray(); + + void SetActive(); + unsigned int GetNumIndices() const { return mNumIndices; } + unsigned int GetNumVerts() const { return mNumVerts; } +private: + // How many vertices in the vertex buffer? + unsigned int mNumVerts; + // How many indices in the index buffer + unsigned int mNumIndices; + // OpenGL ID of the vertex buffer + unsigned int mVertexBuffer; + // OpenGL ID of the index buffer + unsigned int mIndexBuffer; + // OpenGL ID of the vertex array object + unsigned int mVertexArray; +}; \ No newline at end of file