10 enemies in demo
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
#endif
|
||||
|
||||
#include "math/math.hpp"
|
||||
#include <stdlib.h>
|
||||
|
||||
extern volatile const u32 TYRA_MATH_ATAN_TABLE[9] alignas(sizeof(float)) = {
|
||||
0x3f7ffff5, 0xbeaaa61c, 0x3e4c40a6, 0xbe0e6c63, 0x3dc577df,
|
||||
@@ -91,7 +92,7 @@ float Math::cos(float x) {
|
||||
return r;
|
||||
}
|
||||
|
||||
float Math::invSqrt(float x) { return 1.0F / sqrt(x); }
|
||||
float Math::invSqrt(const float& x) { return 1.0F / sqrt(x); }
|
||||
|
||||
float Math::atan2(float y, float x) {
|
||||
float r;
|
||||
@@ -185,6 +186,17 @@ float Math::atan2(float y, float x) {
|
||||
return r;
|
||||
}
|
||||
|
||||
float Math::randomf(const float& min, const float& max) {
|
||||
float random = ((float)rand()) / (float)RAND_MAX;
|
||||
float diff = max - min;
|
||||
float r = random * diff;
|
||||
return min + r;
|
||||
}
|
||||
|
||||
int Math::randomi(const int& min, const int& max) {
|
||||
return rand() % (max - min + 1) + min;
|
||||
}
|
||||
|
||||
float Math::asin(float x) {
|
||||
float r;
|
||||
asm volatile(
|
||||
@@ -248,7 +260,7 @@ bool Math::equalf(const float& a, const float& b, const float& epsilon) {
|
||||
return fabs(a - b) < epsilon;
|
||||
}
|
||||
|
||||
float Math::mod(float x, float y) {
|
||||
float Math::mod(const float& x, const float& y) {
|
||||
/*
|
||||
* Portable fmod(x,y) implementation for systems
|
||||
* that don't have it. Adapted from code found here:
|
||||
@@ -270,14 +282,14 @@ float Math::mod(float x, float y) {
|
||||
return f;
|
||||
}
|
||||
|
||||
float Math::acos(float x) {
|
||||
float Math::acos(const float& x) {
|
||||
float y = sqrt(1.0f - x * x);
|
||||
float t = atan2(y, x);
|
||||
return t;
|
||||
}
|
||||
|
||||
float Math::sin(float x) { return cos(x - HALF_PI); }
|
||||
float Math::sin(const float& x) { return cos(x - HALF_PI); }
|
||||
|
||||
float Math::tan(float x) { return sin(x) / cos(x); }
|
||||
float Math::tan(const float& x) { return sin(x) / cos(x); }
|
||||
|
||||
} // namespace Tyra
|
||||
|
||||
@@ -26,7 +26,7 @@ DynamicMesh::DynamicMesh(const MeshBuilderData& data) : Mesh(data) {
|
||||
frames.push_back(new MeshFrame(data, i));
|
||||
}
|
||||
|
||||
initAnimation();
|
||||
animation.resetAll(frames);
|
||||
}
|
||||
|
||||
DynamicMesh::DynamicMesh(const DynamicMesh& mesh) : Mesh(mesh) {
|
||||
@@ -34,7 +34,7 @@ DynamicMesh::DynamicMesh(const DynamicMesh& mesh) : Mesh(mesh) {
|
||||
frames.push_back(new MeshFrame(*mesh.frames[i]));
|
||||
}
|
||||
|
||||
initAnimation();
|
||||
animation.resetAll(frames);
|
||||
}
|
||||
|
||||
DynamicMesh::~DynamicMesh() {
|
||||
@@ -43,71 +43,4 @@ DynamicMesh::~DynamicMesh() {
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicMesh::initAnimation() {
|
||||
animState.startFrame = 0;
|
||||
animState.endFrame = 0;
|
||||
animState.interpolation = 0.0F;
|
||||
animState.animType = 0;
|
||||
animState.currentFrame = 0;
|
||||
animState.stayFrame = 0;
|
||||
animState.isStayFrameSet = false;
|
||||
animState.nextFrame = 0;
|
||||
animState.speed = 0.1F;
|
||||
}
|
||||
|
||||
void DynamicMesh::playAnimation(const u32& t_frame) {
|
||||
playAnimation(t_frame, t_frame);
|
||||
}
|
||||
|
||||
void DynamicMesh::playAnimation(const u32& t_startFrame,
|
||||
const u32& t_endFrame) {
|
||||
TYRA_ASSERT(frames.size() > 0,
|
||||
"Cant play animation, because no mesh data was loaded!");
|
||||
TYRA_ASSERT(frames.size() != 1,
|
||||
"Cant play animation, because this mesh have only one frame.");
|
||||
TYRA_ASSERT(
|
||||
t_endFrame < frames.size(),
|
||||
"End frame value is too high. Valid range: (0, getFramesCount()-1)");
|
||||
animState.startFrame = t_startFrame;
|
||||
animState.endFrame = t_endFrame;
|
||||
if (animState.currentFrame == t_startFrame)
|
||||
animState.nextFrame = t_endFrame;
|
||||
else
|
||||
animState.nextFrame = t_startFrame;
|
||||
}
|
||||
|
||||
void DynamicMesh::playAnimation(const u32& t_startFrame, const u32& t_endFrame,
|
||||
const u32& t_stayFrame) {
|
||||
TYRA_ASSERT(frames.size() > 0,
|
||||
"Cant play animation, because no mesh data was loaded!");
|
||||
TYRA_ASSERT(frames.size() != 1,
|
||||
"Cant play animation, because this mesh have only one frame.");
|
||||
TYRA_ASSERT(
|
||||
t_endFrame < frames.size(),
|
||||
"End frame value is too high. Valid range: (0, getFramesCount()-1)");
|
||||
animState.startFrame = t_startFrame;
|
||||
animState.endFrame = t_endFrame;
|
||||
animState.isStayFrameSet = true;
|
||||
animState.stayFrame = t_stayFrame;
|
||||
animState.nextFrame = t_startFrame;
|
||||
}
|
||||
|
||||
void DynamicMesh::animate() {
|
||||
animState.interpolation += animState.speed;
|
||||
if (animState.interpolation >= 1.0F) {
|
||||
animState.interpolation = 0.0F;
|
||||
animState.currentFrame = animState.nextFrame;
|
||||
if (++animState.nextFrame > animState.endFrame) {
|
||||
if (animState.isStayFrameSet) {
|
||||
animState.isStayFrameSet = false;
|
||||
animState.nextFrame = animState.stayFrame;
|
||||
animState.startFrame = animState.stayFrame;
|
||||
animState.endFrame = animState.stayFrame;
|
||||
} else {
|
||||
animState.nextFrame = animState.startFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "math/m4x4.hpp"
|
||||
#include "renderer/3d/mesh/dynamic/dynamic_mesh_animation.hpp"
|
||||
#include "debug/debug.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
DynamicMeshAnimation::DynamicMeshAnimation() {
|
||||
callback = nullptr;
|
||||
currentFrameSequenceIndex = 0;
|
||||
framesCount = 0;
|
||||
}
|
||||
|
||||
DynamicMeshAnimation::~DynamicMeshAnimation() {}
|
||||
|
||||
void DynamicMeshAnimation::resetAll(const std::vector<MeshFrame*>& frames) {
|
||||
framesCount = frames.size();
|
||||
speed = 0.1F;
|
||||
loop = true;
|
||||
|
||||
state.interpolation = 0.0F;
|
||||
state.currentFrame = 0;
|
||||
state.nextFrame = 0;
|
||||
|
||||
sequence.clear();
|
||||
for (std::size_t i = 0; i < frames.size(); i++) {
|
||||
sequence.push_back(i);
|
||||
}
|
||||
|
||||
restart();
|
||||
}
|
||||
|
||||
void DynamicMeshAnimation::setSequence(const std::vector<u32>& t_sequence) {
|
||||
TYRA_ASSERT(framesCount != 1,
|
||||
"Cant set sequence, because this mesh have only one frame.");
|
||||
|
||||
TYRA_ASSERT(sequence.size() > 0,
|
||||
"Cant set sequence, because sequence is empty.");
|
||||
|
||||
for (std::size_t i = 0; i < t_sequence.size(); i++) {
|
||||
TYRA_ASSERT(t_sequence[i] < framesCount && t_sequence[i] >= 0,
|
||||
"Cant set sequence, because value: ", t_sequence[i],
|
||||
" At index: ", i, " Is out of range!");
|
||||
}
|
||||
|
||||
sequence = t_sequence;
|
||||
|
||||
restart();
|
||||
}
|
||||
|
||||
const DynamicMeshAnimState& DynamicMeshAnimation::getState() const {
|
||||
return state;
|
||||
}
|
||||
|
||||
void DynamicMeshAnimation::update() {
|
||||
AnimationSequenceCallback callbackInfo =
|
||||
AnimationSequenceCallback::AnimationSequenceCallback_NextFrame;
|
||||
bool sendCallback = true;
|
||||
|
||||
state.interpolation += speed;
|
||||
|
||||
if (state.interpolation >= 1.0F) {
|
||||
state.interpolation = 0.0F;
|
||||
|
||||
if (loop) {
|
||||
updateLoopState(&callbackInfo);
|
||||
} else {
|
||||
auto anythingChanged = updateNoLoopState(&callbackInfo);
|
||||
if (!anythingChanged) {
|
||||
sendCallback = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (callback != nullptr && sendCallback) callback(callbackInfo);
|
||||
}
|
||||
|
||||
void DynamicMeshAnimation::restart() {
|
||||
currentFrameSequenceIndex = 0;
|
||||
|
||||
auto firstIndex = sequence[0];
|
||||
auto secondIndex = sequence.size() > 1 ? sequence[1] : firstIndex;
|
||||
|
||||
state.currentFrame = sequence[firstIndex];
|
||||
state.nextFrame = sequence[secondIndex];
|
||||
}
|
||||
|
||||
void DynamicMeshAnimation::updateLoopState(
|
||||
AnimationSequenceCallback* callbackInfo) {
|
||||
auto n1SequenceIndex = getNextSequenceIndexFrom(currentFrameSequenceIndex);
|
||||
|
||||
state.currentFrame = state.nextFrame;
|
||||
|
||||
auto isN1SequenceIndexEndOfSequence = n1SequenceIndex == sequence.size() - 1;
|
||||
if (isN1SequenceIndexEndOfSequence) {
|
||||
*callbackInfo = AnimationSequenceCallback::AnimationSequenceCallback_Loop;
|
||||
}
|
||||
|
||||
state.nextFrame = sequence[getNextSequenceIndexFrom(n1SequenceIndex)];
|
||||
currentFrameSequenceIndex = n1SequenceIndex;
|
||||
}
|
||||
|
||||
bool DynamicMeshAnimation::updateNoLoopState(
|
||||
AnimationSequenceCallback* callbackInfo) {
|
||||
if (state.currentFrame == state.nextFrame) {
|
||||
return false; // Animation is finished.
|
||||
}
|
||||
|
||||
auto n1SequenceIndex = getNextSequenceIndexFrom(currentFrameSequenceIndex);
|
||||
|
||||
state.currentFrame = state.nextFrame;
|
||||
|
||||
auto isN1SequenceIndexEndOfSequence = n1SequenceIndex == sequence.size() - 1;
|
||||
if (isN1SequenceIndexEndOfSequence) {
|
||||
state.nextFrame = sequence[sequence.size() - 1];
|
||||
*callbackInfo = AnimationSequenceCallback::AnimationSequenceCallback_End;
|
||||
currentFrameSequenceIndex = sequence.size() - 1;
|
||||
} else {
|
||||
state.nextFrame = sequence[getNextSequenceIndexFrom(n1SequenceIndex)];
|
||||
currentFrameSequenceIndex = n1SequenceIndex;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
u32 DynamicMeshAnimation::getNextSequenceIndexFrom(const u32& index) const {
|
||||
return index == sequence.size() - 1 ? 0 : index + 1;
|
||||
}
|
||||
|
||||
void DynamicMeshAnimation::setCallback(
|
||||
const std::function<void(const AnimationSequenceCallback&)>& t_callback) {
|
||||
callback = t_callback;
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -46,6 +46,16 @@ Mesh::Mesh(const Mesh& mesh) {
|
||||
|
||||
M4x4 Mesh::getModelMatrix() const { return translation * rotation * scale; }
|
||||
|
||||
MeshMaterial* Mesh::getMaterialByName(const std::string& name) {
|
||||
for (auto* material : materials) {
|
||||
if (material->name == name) {
|
||||
return material;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Mesh::~Mesh() {
|
||||
for (u32 i = 0; i < materials.size(); i++) {
|
||||
delete materials[i];
|
||||
|
||||
@@ -62,7 +62,7 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) {
|
||||
PipelineDirLightsBag* dirLights = nullptr;
|
||||
|
||||
if (options->frustumCulling == PipelineFrustumCulling_Simple) {
|
||||
auto* frameTo = mesh->frames[mesh->animState.nextFrame];
|
||||
auto* frameTo = mesh->frames[mesh->animation.getState().nextFrame];
|
||||
if (frameTo->bbox->isInFrustum(
|
||||
rendererCore->renderer3D.frustumPlanes.getAll(), model) ==
|
||||
CoreBBoxFrustum::OUTSIDE_FRUSTUM) {
|
||||
@@ -84,8 +84,8 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) {
|
||||
|
||||
for (u32 i = 0; i < mesh->materials.size(); i++) {
|
||||
auto* material = mesh->materials[i];
|
||||
auto* frameFrom = material->frames[mesh->animState.currentFrame];
|
||||
auto* frameTo = material->frames[mesh->animState.nextFrame];
|
||||
auto* frameFrom = material->frames[mesh->animation.getState().currentFrame];
|
||||
auto* frameTo = material->frames[mesh->animation.getState().nextFrame];
|
||||
|
||||
auto partSize = core.getMaxVertCountByParams(
|
||||
options && options->lighting, material->frames[0]->textureCoords);
|
||||
@@ -97,6 +97,13 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) {
|
||||
setBuffersColorBag(buffers, colorBag);
|
||||
u8 isPartInitialized = false;
|
||||
|
||||
auto* texture =
|
||||
rendererCore->texture.repository.getBySpriteOrMesh(material->id);
|
||||
|
||||
TYRA_ASSERT(
|
||||
texture, "Texture for material: ", material->name, "Id: ", material->id,
|
||||
"Was not found in texture repository! Did you forget to add texture?");
|
||||
|
||||
for (u32 k = 0; k < partsCount; k++) {
|
||||
auto& buffer = buffers[bufferIndex];
|
||||
|
||||
@@ -107,7 +114,7 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) {
|
||||
u32 startIndex = k * partSize;
|
||||
|
||||
addVertices(frameFrom, frameTo, &buffer, startIndex);
|
||||
buffer.texture = getTextureBag(material, frameFrom, frameTo, startIndex);
|
||||
buffer.texture = getTextureBag(texture, frameFrom, frameTo, startIndex);
|
||||
buffer.lighting = getLightingBag(frameFrom, frameTo, &model, options,
|
||||
dirLights, startIndex);
|
||||
|
||||
@@ -180,7 +187,7 @@ void DynamicPipeline::setBuffersDefaultVars(DynPipBag* buffers,
|
||||
DynPipInfoBag* infoBag) {
|
||||
for (u32 i = 0; i < buffersCount; i++) {
|
||||
buffers[i].info = infoBag;
|
||||
buffers[i].interpolation = mesh->animState.interpolation;
|
||||
buffers[i].interpolation = mesh->animation.getState().interpolation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,19 +241,13 @@ DynPipColorBag* DynamicPipeline::getColorBag(MeshMaterial* material) const {
|
||||
}
|
||||
|
||||
DynPipTextureBag* DynamicPipeline::getTextureBag(
|
||||
MeshMaterial* material, MeshMaterialFrame* materialFrameFrom,
|
||||
Texture* texture, MeshMaterialFrame* materialFrameFrom,
|
||||
MeshMaterialFrame* materialFrameTo, const u32& startIndex) {
|
||||
if (!materialFrameFrom->textureCoords) return nullptr;
|
||||
|
||||
auto* result = new DynPipTextureBag();
|
||||
|
||||
result->texture =
|
||||
rendererCore->texture.repository.getBySpriteOrMesh(material->id);
|
||||
|
||||
TYRA_ASSERT(
|
||||
result->texture, "Texture for material: ", material->name,
|
||||
"Id: ", material->id,
|
||||
"Was not found in texture repository! Did you forget to add texture?");
|
||||
result->texture = texture;
|
||||
|
||||
result->coordinatesFrom = &materialFrameFrom->textureCoords[startIndex];
|
||||
result->coordinatesTo = &materialFrameTo->textureCoords[startIndex];
|
||||
|
||||
Reference in New Issue
Block a user