diff --git a/assets/textures/multi/1.png b/assets/textures/multi/1.png new file mode 100644 index 0000000..67b2b4e Binary files /dev/null and b/assets/textures/multi/1.png differ diff --git a/assets/textures/multi/default.png b/assets/textures/multi/default.png index 67b2b4e..abdfa4e 100644 Binary files a/assets/textures/multi/default.png and b/assets/textures/multi/default.png differ diff --git a/include/Redacted3D/types/entity/entity.h b/include/Redacted3D/types/entity/entity.h index 634fe30..556eb82 100644 --- a/include/Redacted3D/types/entity/entity.h +++ b/include/Redacted3D/types/entity/entity.h @@ -18,23 +18,25 @@ private: ///Pitch Yaw Roll, The orientation of the entity in the world, Vector3 angle = {0,0,0}; ///Loads the texture for the entity. - virtual void loadTexture(); - ///Loads the geometry for it. - void loadGeometry(); + ///The scale it should be rendered at. Vector3 scale = {1.0f, 1.0f, 1.0f}; protected: - std::string modelPath; - std::string texturePath; ///If the entity has a parent entity, It's here. Entity* parent; ///Entity list of child entities. std::vector children; + +///Loads the geometry for it. +void loadGeometry(const std::string& file); +void loadTexture(const std::string& file); +void loadMultiTexture(const std::vector& files); +void loadMotionTexture(const std::vector& files, u16 frameDelta, bool doAnim = true); + public: std::string name; //Entity name. TODO remove this. bool alive; - virtual std::vector GetEntityUUIDList() const { return std::vector { "" }; } template diff --git a/include/Redacted3D/types/texture.h b/include/Redacted3D/types/texture.h index b420d1c..572697b 100644 --- a/include/Redacted3D/types/texture.h +++ b/include/Redacted3D/types/texture.h @@ -33,22 +33,24 @@ public: void erase() override; ///Every texture other than the base texture. std::vector multi; - ///Loads a multi-texture from a given directory. One must be called "default.png" - MultiTexture(Entity* entity, const char* pathContainingTextures, bool storeOnTextureList); + ///Loads a list of Textures into a MultiTexture. + MultiTexture(Entity* entity, const std::vector& textures, bool storeOnTextureList); MultiTexture() = default; - //TODO load multi-texture from array of std::string of file names. }; ///A list of textures where the one actually displayed depends on how much time has elapsed. class MotionTexture : public Texture { private: std::chrono::high_resolution_clock::time_point lastUpdate; - int lastDisplayedIndex; - u16 msDelay; -public: + int lastDisplayedIndex = 0; + u16 msDelay = 0; bool doAnim = true; +public: std::vector motion; Texture* current(); - MotionTexture(Entity* entity, const std::vector& textures,u16 msBetweenFrames, bool storeOnTextureList); + Texture* base(); + void advance(); + void toggleAnim(); + MotionTexture(Entity* entity, const std::vector& textures,u16 msBetweenFrames, bool storeOnTextureList, bool doAnim = true); MotionTexture() = default; }; \ No newline at end of file diff --git a/src/demo/RuntimeTest/include/cube.h b/src/demo/RuntimeTest/include/cube.h index 84432ee..20bb6c5 100644 --- a/src/demo/RuntimeTest/include/cube.h +++ b/src/demo/RuntimeTest/include/cube.h @@ -19,6 +19,5 @@ public: //We will probably end up having a different camera point class controlled by the "world". //void update(float elapsed) override; void pre_render() override; - void loadTexture() override; Cube(); }; \ No newline at end of file diff --git a/src/demo/RuntimeTest/src/ball.cpp b/src/demo/RuntimeTest/src/ball.cpp index ada22f0..85ab380 100644 --- a/src/demo/RuntimeTest/src/ball.cpp +++ b/src/demo/RuntimeTest/src/ball.cpp @@ -10,7 +10,7 @@ void Ball::update(float elapsed) { Ball::Ball() { name = "ball"; - modelPath = "assets/models/sphere_lo.obj"; - texturePath = "assets/textures/missing.png"; + loadGeometry("assets/models/sphere_lo.obj"); + loadTexture("assets/textures/missing.png"); setScale(1.0f); -} +} \ No newline at end of file diff --git a/src/demo/RuntimeTest/src/cube.cpp b/src/demo/RuntimeTest/src/cube.cpp index 9eb5284..93a75e7 100644 --- a/src/demo/RuntimeTest/src/cube.cpp +++ b/src/demo/RuntimeTest/src/cube.cpp @@ -8,20 +8,20 @@ void Cube::pre_render() { Cube::Cube() { name = "cube"; - modelPath = "assets/models/cube.obj"; - texturePath = "assets/textures/multi/"; setScale(0.5f); -} -void Cube::loadTexture() { - //MultiTexture texture(this, texturePath.c_str(), true); - - - std::vector textures = { + loadGeometry("assets/models/cube.obj"); + std::vector motionTextures = { "assets/textures/motion/default.png", "assets/textures/motion/1.png", "assets/textures/motion/2.png", - "assets/textures/motion/3.png", "assets/textures/motion/4.png", "assets/textures/motion/5.png", - "assets/textures/motion/6.png" - }; + "assets/textures/motion/3.png", "assets/textures/motion/4.png", "assets/textures/motion/5.png", + "assets/textures/motion/6.png" + }; - MotionTexture texture(this, textures, 250, true); + std::vector multiTextures = { + "assets/textures/multi/default.png", "assets/textures/multi/1.png", "assets/textures/multi/2.png", "assets/textures/multi/3.png", + "assets/textures/multi/4.png", "assets/textures/multi/5.png", "assets/textures/multi/6.png" + }; + + loadMultiTexture(multiTextures); + //loadMotionTexture(motionTextures, 250, true); } diff --git a/src/demo/RuntimeTest/src/demoSky.cpp b/src/demo/RuntimeTest/src/demoSky.cpp index b1c0774..17113a4 100644 --- a/src/demo/RuntimeTest/src/demoSky.cpp +++ b/src/demo/RuntimeTest/src/demoSky.cpp @@ -3,7 +3,7 @@ DemoSkybox::DemoSkybox() { name = "skybox"; - modelPath = engine->workingDir + "/assets/models/sphere_vlo.obj"; - texturePath = engine->workingDir + "/assets/textures/skybox.png"; + loadGeometry("assets/models/sphere_vlo.obj"); + loadTexture("assets/textures/skybox.png"); setScale(engine->farPlane); } \ No newline at end of file diff --git a/src/types/entity/entity.cpp b/src/types/entity/entity.cpp index 1b217a7..163a926 100644 --- a/src/types/entity/entity.cpp +++ b/src/types/entity/entity.cpp @@ -57,17 +57,23 @@ Vector3 Entity::getScale() const { return scale; } -void Entity::loadTexture() { - Texture texture(this, texturePath.c_str(), true); +void Entity::loadTexture(const std::string& file) { + Texture texture(this, file.c_str(), true); } -void Entity::loadGeometry() { - VertexArray vArray(this, modelPath, true); +void Entity::loadMultiTexture(const std::vector& files) { + MultiTexture texture(this, files, true); +} + +void Entity::loadMotionTexture(const std::vector& files, u16 frameDelta, bool doAnim) { + MotionTexture(this, files, frameDelta, true, doAnim); +} + +void Entity::loadGeometry(const std::string& file) { + VertexArray vArray(this, file, true); } VertexArray* Entity::getGeometry() { - if (engine->world->geometryList.empty()) - loadGeometry(); for (auto& vArray : engine->world->geometryList) for (auto& entity : vArray->usedBy) if (instanceOf(this, entity)) { @@ -75,8 +81,18 @@ VertexArray* Entity::getGeometry() { vArray->usedBy.push_back(this); return vArray; } - loadGeometry(); - return getGeometry(); + return nullptr; +} + +Texture* Entity::getTexture() { + for (auto& texture : engine->world->textureList) + for (auto& entity : texture->usedBy) + if (instanceOf(this, entity)) { + if (std::find(texture->usedBy.begin(), texture->usedBy.end(), this) == texture->usedBy.end()) //If this is the first time the entity is using it. + texture->usedBy.push_back(this); + return texture; + } + return nullptr; } inline Texture* baseTexture = new Texture; @@ -100,7 +116,6 @@ void Entity::render() { MultiTexture texture; texture.id = baseTexture->id; - if (auto* t = dynamic_cast(getTexture())) { texture.multi.emplace_back(*t); for (const auto &item: t->multi) @@ -164,7 +179,7 @@ void Entity::render() { getGeometry()->draw(); //Reset the multi-texture units. - for (int j = 0; j <= i; j++) { + for (int j = 0; j < i; j++) { glActiveTexture(GL_TEXTURE1 + j); glClientActiveTexture(GL_TEXTURE1 + j); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); @@ -195,20 +210,6 @@ void Entity::render() { //bool Entity::isCollidingWith(Entity *entity) {} -Texture* Entity::getTexture() { - if (engine->world->textureList.empty()) - loadTexture(); - for (auto& texture : engine->world->textureList) - for (auto& entity : texture->usedBy) - if (instanceOf(this, entity)) { - if (std::find(texture->usedBy.begin(), texture->usedBy.end(), this) == texture->usedBy.end()) //If this is the first time the entity is using it. - texture->usedBy.push_back(this); - return texture; - } - loadTexture(); - return getTexture(); -} - void Entity::erase() { Texture* t = getTexture(); VertexArray* vA = getGeometry(); diff --git a/src/types/entity/skybox.cpp b/src/types/entity/skybox.cpp index c15d978..941b45c 100644 --- a/src/types/entity/skybox.cpp +++ b/src/types/entity/skybox.cpp @@ -21,7 +21,5 @@ void Skybox::render() { Skybox::Skybox() { name = "skybox"; - modelPath = engine->workingDir + "/assets/models/sphere_vlo.obj"; - texturePath = engine->workingDir + "/assets/textures/missing.png"; setScale(engine->farPlane); } \ No newline at end of file diff --git a/src/types/texture.cpp b/src/types/texture.cpp index 21155af..d30afb4 100644 --- a/src/types/texture.cpp +++ b/src/types/texture.cpp @@ -57,35 +57,31 @@ void Texture::erase(Texture* texture) const { engine->world->textureList.erase(engine->world->textureList.begin() + i); } - -MultiTexture::MultiTexture(Entity* entity, const char* pathContainingTextures, bool storeOnTextureList) { - for (const auto& entry : std::filesystem::directory_iterator(pathContainingTextures)) - if (entry.is_regular_file() && entry.path().extension() == ".png") { - Texture texture(entity, (const char*) entry.path().c_str(), false); - - //The base texture *must* go in the first slot. - if (entry.path().filename() == "default.png") - this->id = texture.id, - this->usedBy = texture.usedBy; - else multi.push_back(texture); - } +MultiTexture::MultiTexture(Entity* entity, const std::vector& textures, bool storeOnTextureList) { + Texture base; + for (const auto& t : textures) { + if (id != 0) + multi.emplace_back(entity, t.c_str(), false); + else + base = Texture(entity, t.c_str(), false), + id = base.id, + usedBy = base.usedBy; + } if (storeOnTextureList) engine->world->textureList.push_back(new MultiTexture(*this)); - //You cannot have more than 8 total textures rendered in one pass. - //In Fixed-Function OpenGL you only have 8 TMUs available. - //TODO: multi-pass multi-texturing (will be slower). if (multi.size() > 6) - engine->setError(ENGINE_ERROR_CODE::MULTI_TEXTURE_SIZE_EXCEEDS, true); + engine->setError(ENGINE_ERROR_CODE::MULTI_TEXTURE_SIZE_EXCEEDS, false); } void MultiTexture::erase() { Texture::erase(this); } -MotionTexture::MotionTexture(Entity* entity, const std::vector& textures, u16 msBetweenFrames, bool storeOnTextureList) { +MotionTexture::MotionTexture(Entity* entity, const std::vector& textures, u16 msBetweenFrames, bool storeOnTextureList, bool doAnim) { msDelay = msBetweenFrames; + this->doAnim = doAnim; Texture base(entity, textures[0].c_str(), false); std::vector extra(textures.begin()+1, textures.end()); @@ -126,4 +122,18 @@ Texture* MotionTexture::current() { return this; return &motion[lastDisplayedIndex - 1]; -} \ No newline at end of file +} + +void MotionTexture::advance() { + lastDisplayedIndex++; + if (lastDisplayedIndex > motion.size()) + lastDisplayedIndex = 0; +} + +void MotionTexture::toggleAnim() { + doAnim = !doAnim; +} + +Texture* MotionTexture::base() { + return this; +}