Auto format C++ source

This commit is contained in:
2022-08-08 01:07:26 -07:00
parent c5a640e22d
commit 7433d54c16
155 changed files with 17259 additions and 16879 deletions

View File

@@ -42,152 +42,153 @@ void KRAmbientZone::InitNodeInfo(KrNodeInfo* nodeInfo)
nodeInfo->ambient_zone.sample = -1; nodeInfo->ambient_zone.sample = -1;
} }
KRAmbientZone::KRAmbientZone(KRScene &scene, std::string name) : KRNode(scene, name) KRAmbientZone::KRAmbientZone(KRScene& scene, std::string name) : KRNode(scene, name)
{ {
m_ambient = ""; m_ambient = "";
m_ambient_gain = 1.0f; m_ambient_gain = 1.0f;
m_gradient_distance = 0.25f;
m_gradient_distance = 0.25f;
} }
KRAmbientZone::~KRAmbientZone() KRAmbientZone::~KRAmbientZone()
{}
std::string KRAmbientZone::getElementName()
{ {
return "ambient_zone";
} }
std::string KRAmbientZone::getElementName() { tinyxml2::XMLElement* KRAmbientZone::saveXML(tinyxml2::XMLNode* parent)
return "ambient_zone"; {
tinyxml2::XMLElement* e = KRNode::saveXML(parent);
e->SetAttribute("zone", m_zone.c_str());
e->SetAttribute("sample", m_ambient.c_str());
e->SetAttribute("gain", m_ambient_gain);
e->SetAttribute("gradient", m_gradient_distance);
return e;
} }
tinyxml2::XMLElement *KRAmbientZone::saveXML( tinyxml2::XMLNode *parent) void KRAmbientZone::loadXML(tinyxml2::XMLElement* e)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); KRNode::loadXML(e);
e->SetAttribute("zone", m_zone.c_str());
e->SetAttribute("sample", m_ambient.c_str());
e->SetAttribute("gain", m_ambient_gain);
e->SetAttribute("gradient", m_gradient_distance);
return e;
}
void KRAmbientZone::loadXML(tinyxml2::XMLElement *e) m_zone = e->Attribute("zone");
{
KRNode::loadXML(e); m_gradient_distance = 0.25f;
if (e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
m_zone = e->Attribute("zone");
m_gradient_distance = 0.25f; m_gradient_distance = 0.25f;
if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) { }
m_gradient_distance = 0.25f;
} m_ambient = e->Attribute("sample");
m_ambient = e->Attribute("sample"); m_ambient_gain = 1.0f;
if (e->QueryFloatAttribute("gain", &m_ambient_gain) != tinyxml2::XML_SUCCESS) {
m_ambient_gain = 1.0f; m_ambient_gain = 1.0f;
if(e->QueryFloatAttribute("gain", &m_ambient_gain) != tinyxml2::XML_SUCCESS) { }
m_ambient_gain = 1.0f;
}
} }
std::string KRAmbientZone::getAmbient() std::string KRAmbientZone::getAmbient()
{ {
return m_ambient; return m_ambient;
} }
void KRAmbientZone::setAmbient(const std::string &ambient) void KRAmbientZone::setAmbient(const std::string& ambient)
{ {
m_ambient = ambient; m_ambient = ambient;
} }
float KRAmbientZone::getAmbientGain() float KRAmbientZone::getAmbientGain()
{ {
return m_ambient_gain; return m_ambient_gain;
} }
void KRAmbientZone::setAmbientGain(float ambient_gain) void KRAmbientZone::setAmbientGain(float ambient_gain)
{ {
m_ambient_gain = ambient_gain; m_ambient_gain = ambient_gain;
} }
std::string KRAmbientZone::getZone() std::string KRAmbientZone::getZone()
{ {
return m_zone; return m_zone;
} }
void KRAmbientZone::setZone(const std::string &zone) void KRAmbientZone::setZone(const std::string& zone)
{ {
m_zone = zone; m_zone = zone;
} }
void KRAmbientZone::render(RenderInfo& ri) void KRAmbientZone::render(RenderInfo& ri)
{ {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if (m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(ri);
bool bVisualize = ri.camera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_AMBIENT_ZONES;
if(ri.renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
KRMesh* sphereModel = getContext().getMeshManager()->getMaxLODModel("__sphere");
if (sphereModel) {
Matrix4 sphereModelMatrix = getModelMatrix(); KRNode::render(ri);
PipelineInfo info{}; bool bVisualize = ri.camera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_AMBIENT_ZONES;
std::string shader_name("visualize_overlay");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &ri.point_lights;
info.directional_lights = &ri.directional_lights;
info.spot_lights = &ri.spot_lights;
info.renderPass = ri.renderPass;
info.rasterMode = RasterMode::kAdditive;
info.modelFormat = sphereModel->getModelFormat();
info.vertexAttributes = sphereModel->getVertexAttributes();
KRPipeline *pPipeline = getContext().getPipelineManager()->getPipeline(*ri.surface, info);
pPipeline->bind(ri.commandBuffer, *ri.camera, ri.viewport, sphereModelMatrix, &ri.point_lights, &ri.directional_lights, &ri.spot_lights, ri.renderPass);
sphereModel->renderNoMaterials(ri.commandBuffer, ri.renderPass, getName(), "visualize_overlay", 1.0f); if (ri.renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
} // sphereModel KRMesh* sphereModel = getContext().getMeshManager()->getMaxLODModel("__sphere");
} if (sphereModel) {
Matrix4 sphereModelMatrix = getModelMatrix();
PipelineInfo info{};
std::string shader_name("visualize_overlay");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &ri.point_lights;
info.directional_lights = &ri.directional_lights;
info.spot_lights = &ri.spot_lights;
info.renderPass = ri.renderPass;
info.rasterMode = RasterMode::kAdditive;
info.modelFormat = sphereModel->getModelFormat();
info.vertexAttributes = sphereModel->getVertexAttributes();
KRPipeline* pPipeline = getContext().getPipelineManager()->getPipeline(*ri.surface, info);
pPipeline->bind(ri.commandBuffer, *ri.camera, ri.viewport, sphereModelMatrix, &ri.point_lights, &ri.directional_lights, &ri.spot_lights, ri.renderPass);
sphereModel->renderNoMaterials(ri.commandBuffer, ri.renderPass, getName(), "visualize_overlay", 1.0f);
} // sphereModel
}
} }
float KRAmbientZone::getGradientDistance() float KRAmbientZone::getGradientDistance()
{ {
return m_gradient_distance; return m_gradient_distance;
} }
void KRAmbientZone::setGradientDistance(float gradient_distance) void KRAmbientZone::setGradientDistance(float gradient_distance)
{ {
m_gradient_distance = gradient_distance; m_gradient_distance = gradient_distance;
} }
AABB KRAmbientZone::getBounds() { AABB KRAmbientZone::getBounds()
// Ambient zones always have a -1, -1, -1 to 1, 1, 1 bounding box
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
}
float KRAmbientZone::getContainment(const Vector3 &pos)
{ {
AABB bounds = getBounds(); // Ambient zones always have a -1, -1, -1 to 1, 1, 1 bounding box
if(bounds.contains(pos)) { return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
Vector3 size = bounds.size(); }
Vector3 diff = pos - bounds.center();
diff = diff * 2.0f; float KRAmbientZone::getContainment(const Vector3& pos)
diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z); {
float d = diff.magnitude(); AABB bounds = getBounds();
if (bounds.contains(pos)) {
if(m_gradient_distance <= 0.0f) { Vector3 size = bounds.size();
// Avoid division by zero Vector3 diff = pos - bounds.center();
d = d > 1.0f ? 0.0f : 1.0f; diff = diff * 2.0f;
} else { diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z);
d = (1.0f - d) / m_gradient_distance; float d = diff.magnitude();
d = KRCLAMP(d, 0.0f, 1.0f);
} if (m_gradient_distance <= 0.0f) {
return d; // Avoid division by zero
d = d > 1.0f ? 0.0f : 1.0f;
} else { } else {
return 0.0f; d = (1.0f - d) / m_gradient_distance;
d = KRCLAMP(d, 0.0f, 1.0f);
} }
return d;
} else {
return 0.0f;
}
} }

View File

@@ -35,39 +35,40 @@
#include "KRNode.h" #include "KRNode.h"
#include "KRTexture.h" #include "KRTexture.h"
class KRAmbientZone : public KRNode { class KRAmbientZone : public KRNode
{
public: public:
static void InitNodeInfo(KrNodeInfo* nodeInfo); static void InitNodeInfo(KrNodeInfo* nodeInfo);
KRAmbientZone(KRScene& scene, std::string name);
virtual ~KRAmbientZone();
virtual std::string getElementName();
virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
virtual void loadXML(tinyxml2::XMLElement* e);
void render(RenderInfo& ri);
std::string getZone();
void setZone(const std::string& zone);
float getGradientDistance();
void setGradientDistance(float gradient_distance);
std::string getAmbient();
void setAmbient(const std::string& ambient);
float getAmbientGain();
void setAmbientGain(float ambient_gain);
virtual AABB getBounds();
float getContainment(const Vector3& pos);
KRAmbientZone(KRScene &scene, std::string name);
virtual ~KRAmbientZone();
virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
virtual void loadXML(tinyxml2::XMLElement *e);
void render(RenderInfo& ri);
std::string getZone();
void setZone(const std::string &zone);
float getGradientDistance();
void setGradientDistance(float gradient_distance);
std::string getAmbient();
void setAmbient(const std::string &ambient);
float getAmbientGain();
void setAmbientGain(float ambient_gain);
virtual AABB getBounds();
float getContainment(const Vector3 &pos);
private: private:
std::string m_zone; std::string m_zone;
float m_gradient_distance; float m_gradient_distance;
std::string m_ambient; std::string m_ambient;
float m_ambient_gain; float m_ambient_gain;
}; };

View File

@@ -35,313 +35,315 @@
#include "KRAnimationCurve.h" #include "KRAnimationCurve.h"
#include "KREngine-common.h" #include "KREngine-common.h"
KRAnimation::KRAnimation(KRContext &context, std::string name) : KRResource(context, name) KRAnimation::KRAnimation(KRContext& context, std::string name) : KRResource(context, name)
{ {
m_auto_play = false; m_auto_play = false;
m_loop = false; m_loop = false;
m_playing = false; m_playing = false;
m_local_time = 0.0f; m_local_time = 0.0f;
m_duration = 0.0f; m_duration = 0.0f;
m_start_time = 0.0f; m_start_time = 0.0f;
} }
KRAnimation::~KRAnimation() KRAnimation::~KRAnimation()
{ {
for(unordered_map<std::string, KRAnimationLayer *>::iterator itr = m_layers.begin(); itr != m_layers.end(); ++itr){ for (unordered_map<std::string, KRAnimationLayer*>::iterator itr = m_layers.begin(); itr != m_layers.end(); ++itr) {
delete (*itr).second; delete (*itr).second;
} }
} }
std::string KRAnimation::getExtension() { std::string KRAnimation::getExtension()
return "kranimation";
}
void KRAnimation::addLayer(KRAnimationLayer *layer)
{ {
m_layers[layer->getName()] = layer; return "kranimation";
} }
bool KRAnimation::save(KRDataBlock &data) { void KRAnimation::addLayer(KRAnimationLayer* layer)
tinyxml2::XMLDocument doc;
tinyxml2::XMLElement *animation_node = doc.NewElement( "animation" );
doc.InsertEndChild(animation_node);
animation_node->SetAttribute("loop", m_loop ? "true" : "false");
animation_node->SetAttribute("auto_play", m_auto_play ? "true" : "false");
animation_node->SetAttribute("duration", m_duration);
animation_node->SetAttribute("start_time", m_start_time);
for(unordered_map<std::string, KRAnimationLayer *>::iterator itr = m_layers.begin(); itr != m_layers.end(); ++itr){
(*itr).second->saveXML(animation_node);
}
tinyxml2::XMLPrinter p;
doc.Print(&p);
data.append((void *)p.CStr(), strlen(p.CStr())+1);
return true;
}
KRAnimation *KRAnimation::Load(KRContext &context, const std::string &name, KRDataBlock *data)
{ {
std::string xml_string = data->getString(); m_layers[layer->getName()] = layer;
}
tinyxml2::XMLDocument doc;
doc.Parse(xml_string.c_str());
KRAnimation *new_animation = new KRAnimation(context, name);
tinyxml2::XMLElement *animation_node = doc.RootElement();
if(animation_node->QueryFloatAttribute("duration", &new_animation->m_duration) != tinyxml2::XML_SUCCESS) {
new_animation->m_duration = 0.0f; // Default value
}
if(animation_node->QueryFloatAttribute("start_time", &new_animation->m_start_time) != tinyxml2::XML_SUCCESS) {
new_animation->m_start_time = 0.0f; // Default value
}
if(animation_node->QueryBoolAttribute("loop", &new_animation->m_loop) != tinyxml2::XML_SUCCESS) {
new_animation->m_loop = false; // Default value
}
if(animation_node->QueryBoolAttribute("auto_play", &new_animation->m_auto_play) != tinyxml2::XML_SUCCESS) {
new_animation->m_auto_play = false; // Default value
}
for(tinyxml2::XMLElement *child_element=animation_node->FirstChildElement(); child_element != NULL; child_element = child_element->NextSiblingElement()) { bool KRAnimation::save(KRDataBlock& data)
if(strcmp(child_element->Name(), "layer") == 0) { {
KRAnimationLayer *new_layer = new KRAnimationLayer(context); tinyxml2::XMLDocument doc;
new_layer->loadXML(child_element); tinyxml2::XMLElement* animation_node = doc.NewElement("animation");
new_animation->m_layers[new_layer->getName()] = new_layer; doc.InsertEndChild(animation_node);
} animation_node->SetAttribute("loop", m_loop ? "true" : "false");
animation_node->SetAttribute("auto_play", m_auto_play ? "true" : "false");
animation_node->SetAttribute("duration", m_duration);
animation_node->SetAttribute("start_time", m_start_time);
for (unordered_map<std::string, KRAnimationLayer*>::iterator itr = m_layers.begin(); itr != m_layers.end(); ++itr) {
(*itr).second->saveXML(animation_node);
}
tinyxml2::XMLPrinter p;
doc.Print(&p);
data.append((void*)p.CStr(), strlen(p.CStr()) + 1);
return true;
}
KRAnimation* KRAnimation::Load(KRContext& context, const std::string& name, KRDataBlock* data)
{
std::string xml_string = data->getString();
tinyxml2::XMLDocument doc;
doc.Parse(xml_string.c_str());
KRAnimation* new_animation = new KRAnimation(context, name);
tinyxml2::XMLElement* animation_node = doc.RootElement();
if (animation_node->QueryFloatAttribute("duration", &new_animation->m_duration) != tinyxml2::XML_SUCCESS) {
new_animation->m_duration = 0.0f; // Default value
}
if (animation_node->QueryFloatAttribute("start_time", &new_animation->m_start_time) != tinyxml2::XML_SUCCESS) {
new_animation->m_start_time = 0.0f; // Default value
}
if (animation_node->QueryBoolAttribute("loop", &new_animation->m_loop) != tinyxml2::XML_SUCCESS) {
new_animation->m_loop = false; // Default value
}
if (animation_node->QueryBoolAttribute("auto_play", &new_animation->m_auto_play) != tinyxml2::XML_SUCCESS) {
new_animation->m_auto_play = false; // Default value
}
for (tinyxml2::XMLElement* child_element = animation_node->FirstChildElement(); child_element != NULL; child_element = child_element->NextSiblingElement()) {
if (strcmp(child_element->Name(), "layer") == 0) {
KRAnimationLayer* new_layer = new KRAnimationLayer(context);
new_layer->loadXML(child_element);
new_animation->m_layers[new_layer->getName()] = new_layer;
} }
}
if(new_animation->m_auto_play) {
new_animation->m_playing = true; if (new_animation->m_auto_play) {
} new_animation->m_playing = true;
}
// KRNode *n = KRNode::LoadXML(*new_scene, scene_element->FirstChildElement());
// KRNode *n = KRNode::LoadXML(*new_scene, scene_element->FirstChildElement());
delete data;
return new_animation; delete data;
return new_animation;
} }
unordered_map<std::string, KRAnimationLayer *> &KRAnimation::getLayers() unordered_map<std::string, KRAnimationLayer*>& KRAnimation::getLayers()
{ {
return m_layers; return m_layers;
} }
KRAnimationLayer *KRAnimation::getLayer(const char *szName) KRAnimationLayer* KRAnimation::getLayer(const char* szName)
{ {
return m_layers[szName]; return m_layers[szName];
} }
void KRAnimation::update(float deltaTime) void KRAnimation::update(float deltaTime)
{ {
if(m_playing) { if (m_playing) {
m_local_time += deltaTime; m_local_time += deltaTime;
}
if (m_loop) {
while (m_local_time > m_duration) {
m_local_time -= m_duration;
} }
if(m_loop) { } else if (m_local_time > m_duration) {
while(m_local_time > m_duration) { m_local_time = m_duration;
m_local_time -= m_duration; m_playing = false;
} getContext().getAnimationManager()->updateActiveAnimations(this);
} else if(m_local_time > m_duration) { }
m_local_time = m_duration;
m_playing = false; for (unordered_map<std::string, KRAnimationLayer*>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
getContext().getAnimationManager()->updateActiveAnimations(this); KRAnimationLayer* layer = (*layer_itr).second;
} for (std::vector<KRAnimationAttribute*>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
KRAnimationAttribute* attribute = *attribute_itr;
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
KRAnimationLayer *layer = (*layer_itr).second;
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) { // TODO - Currently only a single layer supported per animation -- need to either implement combining of multiple layers or ask the FBX sdk to bake all layers into one
KRAnimationAttribute *attribute = *attribute_itr; KRAnimationCurve* curve = attribute->getCurve();
KRNode* target = attribute->getTarget();
KRNode::node_attribute_type attribute_type = attribute->getTargetAttribute();
// TODO - Currently only a single layer supported per animation -- need to either implement combining of multiple layers or ask the FBX sdk to bake all layers into one
KRAnimationCurve *curve = attribute->getCurve(); if (curve != NULL && target != NULL) {
KRNode *target = attribute->getTarget(); target->SetAttribute(attribute_type, curve->getValue(m_local_time + m_start_time));
KRNode::node_attribute_type attribute_type = attribute->getTargetAttribute(); }
if(curve != NULL && target != NULL) {
target->SetAttribute(attribute_type, curve->getValue(m_local_time + m_start_time));
}
}
} }
}
} }
void KRAnimation::Play() void KRAnimation::Play()
{ {
m_playing = true; m_playing = true;
getContext().getAnimationManager()->updateActiveAnimations(this); getContext().getAnimationManager()->updateActiveAnimations(this);
} }
void KRAnimation::Stop() void KRAnimation::Stop()
{ {
m_playing = false; m_playing = false;
getContext().getAnimationManager()->updateActiveAnimations(this); getContext().getAnimationManager()->updateActiveAnimations(this);
} }
float KRAnimation::getTime() float KRAnimation::getTime()
{ {
return m_local_time; return m_local_time;
} }
void KRAnimation::setTime(float time) void KRAnimation::setTime(float time)
{ {
m_local_time = time; m_local_time = time;
} }
float KRAnimation::getDuration() float KRAnimation::getDuration()
{ {
return m_duration; return m_duration;
} }
void KRAnimation::setDuration(float duration) void KRAnimation::setDuration(float duration)
{ {
m_duration = duration; m_duration = duration;
} }
float KRAnimation::getStartTime() float KRAnimation::getStartTime()
{ {
return m_start_time; return m_start_time;
} }
void KRAnimation::setStartTime(float start_time) void KRAnimation::setStartTime(float start_time)
{ {
m_start_time = start_time; m_start_time = start_time;
} }
bool KRAnimation::isPlaying() bool KRAnimation::isPlaying()
{ {
return m_playing; return m_playing;
} }
bool KRAnimation::getAutoPlay() const bool KRAnimation::getAutoPlay() const
{ {
return m_auto_play; return m_auto_play;
} }
void KRAnimation::setAutoPlay(bool auto_play) void KRAnimation::setAutoPlay(bool auto_play)
{ {
m_auto_play = auto_play; m_auto_play = auto_play;
} }
bool KRAnimation::getLooping() const bool KRAnimation::getLooping() const
{ {
return m_loop; return m_loop;
} }
void KRAnimation::setLooping(bool looping) void KRAnimation::setLooping(bool looping)
{ {
m_loop = looping; m_loop = looping;
} }
KRAnimation *KRAnimation::split(const std::string &name, float start_time, float duration, bool strip_unchanging_attributes, bool clone_curves) KRAnimation* KRAnimation::split(const std::string& name, float start_time, float duration, bool strip_unchanging_attributes, bool clone_curves)
{ {
KRAnimation *new_animation = new KRAnimation(getContext(), name); KRAnimation* new_animation = new KRAnimation(getContext(), name);
new_animation->setStartTime(start_time); new_animation->setStartTime(start_time);
new_animation->setDuration(duration); new_animation->setDuration(duration);
new_animation->m_loop = m_loop; new_animation->m_loop = m_loop;
new_animation->m_auto_play = m_auto_play; new_animation->m_auto_play = m_auto_play;
int new_curve_count = 0; int new_curve_count = 0;
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) { for (unordered_map<std::string, KRAnimationLayer*>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
KRAnimationLayer *layer = (*layer_itr).second; KRAnimationLayer* layer = (*layer_itr).second;
KRAnimationLayer *new_layer = new KRAnimationLayer(getContext()); KRAnimationLayer* new_layer = new KRAnimationLayer(getContext());
new_layer->setName(layer->getName()); new_layer->setName(layer->getName());
new_layer->setRotationAccumulationMode(layer->getRotationAccumulationMode()); new_layer->setRotationAccumulationMode(layer->getRotationAccumulationMode());
new_layer->setScaleAccumulationMode(layer->getScaleAccumulationMode()); new_layer->setScaleAccumulationMode(layer->getScaleAccumulationMode());
new_layer->setWeight(layer->getWeight()); new_layer->setWeight(layer->getWeight());
new_animation->m_layers[new_layer->getName()] = new_layer; new_animation->m_layers[new_layer->getName()] = new_layer;
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) { for (std::vector<KRAnimationAttribute*>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
KRAnimationAttribute *attribute = *attribute_itr; KRAnimationAttribute* attribute = *attribute_itr;
// Updated Dec 9, 2013 by Peter to change the way that attributes are stripped.
//
// If we have been asked to strip_unchanging_attributes then we only want to strip those attributes that don't havechanges
// in any of their components (x, y, z). This means that we have to group the attributes before we check for valueChanges().
// The attributes won't come through in order, but they do come through in group order (each group of 3 arrives as x, y, z)
//
// Since this method isn't designed to handle groups, this is a bit of a hack. We simply take whatever channel is coming
// through and then check the other associated curves.
//
int targetAttribute = attribute->getTargetAttribute();
if (targetAttribute > 0) { // we have a valid target that fits within a group of 3
targetAttribute--; // this is now group relative 0,1,2 is the first group .. 3,4,5 is the second group, etc.
KRAnimationCurve *curve = attribute->getCurve(); // this is the curve we are currently handling
int placeInGroup = targetAttribute % 3; // this will be 0, 1 or 2
static long placeLookup[] = { 1, 2, -1, 1, -2, -1 };
KRAnimationAttribute *attribute2 = *(attribute_itr + placeLookup[placeInGroup*2]);
KRAnimationAttribute *attribute3 = *(attribute_itr + placeLookup[placeInGroup*2+1]);
KRAnimationCurve *curve2 = attribute2->getCurve();
KRAnimationCurve *curve3 = attribute3->getCurve();
bool include_attribute = true; // Updated Dec 9, 2013 by Peter to change the way that attributes are stripped.
if(strip_unchanging_attributes) { //
include_attribute = curve->valueChanges(start_time, duration) | // If we have been asked to strip_unchanging_attributes then we only want to strip those attributes that don't havechanges
curve2->valueChanges(start_time, duration) | // in any of their components (x, y, z). This means that we have to group the attributes before we check for valueChanges().
curve3->valueChanges(start_time, duration); // The attributes won't come through in order, but they do come through in group order (each group of 3 arrives as x, y, z)
} //
// Since this method isn't designed to handle groups, this is a bit of a hack. We simply take whatever channel is coming
if(include_attribute) { // through and then check the other associated curves.
KRAnimationAttribute *new_attribute = new KRAnimationAttribute(getContext()); //
KRAnimationCurve *new_curve = curve; int targetAttribute = attribute->getTargetAttribute();
if(clone_curves) { if (targetAttribute > 0) { // we have a valid target that fits within a group of 3
std::string new_curve_name = name + "_curve" + std::to_string(++new_curve_count); targetAttribute--; // this is now group relative 0,1,2 is the first group .. 3,4,5 is the second group, etc.
new_curve = curve->split(new_curve_name, start_time, duration);
} KRAnimationCurve* curve = attribute->getCurve(); // this is the curve we are currently handling
new_attribute->setCurveName(new_curve->getName()); int placeInGroup = targetAttribute % 3; // this will be 0, 1 or 2
new_attribute->setTargetAttribute(attribute->getTargetAttribute()); static long placeLookup[] = { 1, 2, -1, 1, -2, -1 };
new_attribute->setTargetName(attribute->getTargetName());
new_layer->addAttribute(new_attribute); KRAnimationAttribute* attribute2 = *(attribute_itr + placeLookup[placeInGroup * 2]);
} KRAnimationAttribute* attribute3 = *(attribute_itr + placeLookup[placeInGroup * 2 + 1]);
} KRAnimationCurve* curve2 = attribute2->getCurve();
KRAnimationCurve* curve3 = attribute3->getCurve();
bool include_attribute = true;
if (strip_unchanging_attributes) {
include_attribute = curve->valueChanges(start_time, duration) |
curve2->valueChanges(start_time, duration) |
curve3->valueChanges(start_time, duration);
} }
if (include_attribute) {
KRAnimationAttribute* new_attribute = new KRAnimationAttribute(getContext());
KRAnimationCurve* new_curve = curve;
if (clone_curves) {
std::string new_curve_name = name + "_curve" + std::to_string(++new_curve_count);
new_curve = curve->split(new_curve_name, start_time, duration);
}
new_attribute->setCurveName(new_curve->getName());
new_attribute->setTargetAttribute(attribute->getTargetAttribute());
new_attribute->setTargetName(attribute->getTargetName());
new_layer->addAttribute(new_attribute);
}
}
} }
}
getContext().getAnimationManager()->addAnimation(new_animation);
return new_animation; getContext().getAnimationManager()->addAnimation(new_animation);
return new_animation;
} }
void KRAnimation::deleteCurves() void KRAnimation::deleteCurves()
{ {
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) { for (unordered_map<std::string, KRAnimationLayer*>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
KRAnimationLayer *layer = (*layer_itr).second; KRAnimationLayer* layer = (*layer_itr).second;
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) { for (std::vector<KRAnimationAttribute*>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
KRAnimationAttribute *attribute = *attribute_itr; KRAnimationAttribute* attribute = *attribute_itr;
attribute->deleteCurve(); attribute->deleteCurve();
}
} }
}
} }
void KRAnimation::_lockData() void KRAnimation::_lockData()
{ {
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) { for (unordered_map<std::string, KRAnimationLayer*>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
KRAnimationLayer *layer = (*layer_itr).second; KRAnimationLayer* layer = (*layer_itr).second;
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) { for (std::vector<KRAnimationAttribute*>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
KRAnimationAttribute *attribute = *attribute_itr; KRAnimationAttribute* attribute = *attribute_itr;
KRAnimationCurve *curve = attribute->getCurve(); KRAnimationCurve* curve = attribute->getCurve();
if(curve) { if (curve) {
curve->_lockData(); curve->_lockData();
} }
}
} }
}
} }
void KRAnimation::_unlockData() void KRAnimation::_unlockData()
{ {
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) { for (unordered_map<std::string, KRAnimationLayer*>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
KRAnimationLayer *layer = (*layer_itr).second; KRAnimationLayer* layer = (*layer_itr).second;
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) { for (std::vector<KRAnimationAttribute*>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
KRAnimationAttribute *attribute = *attribute_itr; KRAnimationAttribute* attribute = *attribute_itr;
KRAnimationCurve *curve = attribute->getCurve(); KRAnimationCurve* curve = attribute->getCurve();
if(curve) { if (curve) {
curve->_unlockData(); curve->_unlockData();
} }
}
} }
}
} }

View File

@@ -38,47 +38,48 @@
#include "KRAnimationLayer.h" #include "KRAnimationLayer.h"
class KRAnimation : public KRResource { class KRAnimation : public KRResource
{
public: public:
KRAnimation(KRContext &context, std::string name); KRAnimation(KRContext& context, std::string name);
virtual ~KRAnimation(); virtual ~KRAnimation();
virtual std::string getExtension(); virtual std::string getExtension();
virtual bool save(KRDataBlock &data); virtual bool save(KRDataBlock& data);
static KRAnimation *Load(KRContext &context, const std::string &name, KRDataBlock *data); static KRAnimation* Load(KRContext& context, const std::string& name, KRDataBlock* data);
void addLayer(KRAnimationLayer *layer); void addLayer(KRAnimationLayer* layer);
unordered_map<std::string, KRAnimationLayer *> &getLayers(); unordered_map<std::string, KRAnimationLayer*>& getLayers();
KRAnimationLayer *getLayer(const char *szName); KRAnimationLayer* getLayer(const char* szName);
bool getAutoPlay() const; bool getAutoPlay() const;
void setAutoPlay(bool auto_play); void setAutoPlay(bool auto_play);
bool getLooping() const; bool getLooping() const;
void setLooping(bool looping); void setLooping(bool looping);
void Play(); void Play();
void Stop(); void Stop();
void update(float deltaTime); void update(float deltaTime);
float getTime(); float getTime();
void setTime(float time); void setTime(float time);
float getDuration(); float getDuration();
void setDuration(float duration); void setDuration(float duration);
float getStartTime(); float getStartTime();
void setStartTime(float start_time); void setStartTime(float start_time);
bool isPlaying(); bool isPlaying();
KRAnimation *split(const std::string &name, float start_time, float duration, bool strip_unchanging_attributes = true, bool clone_curves = true); KRAnimation* split(const std::string& name, float start_time, float duration, bool strip_unchanging_attributes = true, bool clone_curves = true);
void deleteCurves(); void deleteCurves();
void _lockData(); void _lockData();
void _unlockData(); void _unlockData();
private: private:
unordered_map<std::string, KRAnimationLayer *> m_layers; unordered_map<std::string, KRAnimationLayer*> m_layers;
bool m_auto_play; bool m_auto_play;
bool m_loop; bool m_loop;
bool m_playing; bool m_playing;
float m_local_time; float m_local_time;
float m_duration; float m_duration;
float m_start_time; float m_start_time;
}; };

View File

@@ -35,249 +35,249 @@
#include "KRAnimationCurveManager.h" #include "KRAnimationCurveManager.h"
KRAnimationAttribute::KRAnimationAttribute(KRContext &context) : KRContextObject(context) KRAnimationAttribute::KRAnimationAttribute(KRContext& context) : KRContextObject(context)
{ {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE;
m_target = NULL; m_target = NULL;
m_curve = NULL; m_curve = NULL;
} }
KRAnimationAttribute::~KRAnimationAttribute() KRAnimationAttribute::~KRAnimationAttribute()
{ {
} }
tinyxml2::XMLElement *KRAnimationAttribute::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement* KRAnimationAttribute::saveXML(tinyxml2::XMLNode* parent)
{ {
tinyxml2::XMLDocument *doc = parent->GetDocument(); tinyxml2::XMLDocument* doc = parent->GetDocument();
tinyxml2::XMLElement *e = doc->NewElement("attribute"); tinyxml2::XMLElement* e = doc->NewElement("attribute");
parent->InsertEndChild(e); parent->InsertEndChild(e);
e->SetAttribute("curve", m_curve_name.c_str()); e->SetAttribute("curve", m_curve_name.c_str());
e->SetAttribute("target", m_target_name.c_str()); e->SetAttribute("target", m_target_name.c_str());
const char *szAttribute = "none"; const char* szAttribute = "none";
switch(m_node_attribute) { switch (m_node_attribute) {
case KRNode::KRENGINE_NODE_ATTRIBUTE_NONE: case KRNode::KRENGINE_NODE_ATTRIBUTE_NONE:
szAttribute = "none"; szAttribute = "none";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_X: case KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_X:
szAttribute = "translate_x"; szAttribute = "translate_x";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y: case KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y:
szAttribute = "translate_y"; szAttribute = "translate_y";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z: case KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z:
szAttribute = "translate_z"; szAttribute = "translate_z";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_X: case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_X:
szAttribute = "scale_x"; szAttribute = "scale_x";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Y: case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Y:
szAttribute = "scale_y"; szAttribute = "scale_y";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Z: case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Z:
szAttribute = "scale_z"; szAttribute = "scale_z";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_X: case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_X:
szAttribute = "rotate_x"; szAttribute = "rotate_x";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Y: case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Y:
szAttribute = "rotate_y"; szAttribute = "rotate_y";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Z: case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Z:
szAttribute = "rotate_z"; szAttribute = "rotate_z";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X: case KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X:
szAttribute = "pre_rotate_x"; szAttribute = "pre_rotate_x";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y: case KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y:
szAttribute = "pre_rotate_y"; szAttribute = "pre_rotate_y";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z: case KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z:
szAttribute = "pre_rotate_z"; szAttribute = "pre_rotate_z";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X: case KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X:
szAttribute = "post_rotate_x"; szAttribute = "post_rotate_x";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y: case KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y:
szAttribute = "post_rotate_y"; szAttribute = "post_rotate_y";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z: case KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z:
szAttribute = "post_rotate_z"; szAttribute = "post_rotate_z";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X: case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X:
szAttribute = "rotate_pivot_x"; szAttribute = "rotate_pivot_x";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y: case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y:
szAttribute = "rotate_pivot_y"; szAttribute = "rotate_pivot_y";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z: case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z:
szAttribute = "rotate_pivot_z"; szAttribute = "rotate_pivot_z";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X: case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X:
szAttribute = "scale_pivot_x"; szAttribute = "scale_pivot_x";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y: case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y:
szAttribute = "scale_pivot_y"; szAttribute = "scale_pivot_y";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z: case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z:
szAttribute = "scale_pivot_z"; szAttribute = "scale_pivot_z";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X: case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X:
szAttribute = "rotate_offset_x"; szAttribute = "rotate_offset_x";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y: case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y:
szAttribute = "rotate_offset_y"; szAttribute = "rotate_offset_y";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z: case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z:
szAttribute = "rotate_offset_z"; szAttribute = "rotate_offset_z";
break; break;
case KRNode::KRENGINE_NODE_SCALE_OFFSET_X: case KRNode::KRENGINE_NODE_SCALE_OFFSET_X:
szAttribute = "scale_offset_x"; szAttribute = "scale_offset_x";
break; break;
case KRNode::KRENGINE_NODE_SCALE_OFFSET_Y: case KRNode::KRENGINE_NODE_SCALE_OFFSET_Y:
szAttribute = "scale_offset_y"; szAttribute = "scale_offset_y";
break; break;
case KRNode::KRENGINE_NODE_SCALE_OFFSET_Z: case KRNode::KRENGINE_NODE_SCALE_OFFSET_Z:
szAttribute = "scale_offset_z"; szAttribute = "scale_offset_z";
break; break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_COUNT: case KRNode::KRENGINE_NODE_ATTRIBUTE_COUNT:
// Suppress warning // Suppress warning
break; break;
} }
e->SetAttribute("attribute", szAttribute); e->SetAttribute("attribute", szAttribute);
return e; return e;
} }
void KRAnimationAttribute::loadXML(tinyxml2::XMLElement *e) void KRAnimationAttribute::loadXML(tinyxml2::XMLElement* e)
{ {
m_target = NULL; m_target = NULL;
m_curve = NULL; m_curve = NULL;
m_curve_name = e->Attribute("curve"); m_curve_name = e->Attribute("curve");
m_target_name = e->Attribute("target"); m_target_name = e->Attribute("target");
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE;
const char* szAttribute = e->Attribute("attribute");
if (strcmp(szAttribute, "none") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE;
} else if (strcmp(szAttribute, "translate_x") == 0) {
const char *szAttribute = e->Attribute("attribute"); m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_X;
if(strcmp(szAttribute, "none") == 0) { } else if (strcmp(szAttribute, "translate_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y;
} else if(strcmp(szAttribute, "translate_x") == 0) { } else if (strcmp(szAttribute, "translate_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_X; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z;
} else if(strcmp(szAttribute, "translate_y") == 0) { } else if (strcmp(szAttribute, "rotate_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_X;
} else if(strcmp(szAttribute, "translate_z") == 0) { } else if (strcmp(szAttribute, "rotate_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Y;
} else if(strcmp(szAttribute, "rotate_x") == 0) { } else if (strcmp(szAttribute, "rotate_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_X; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Z;
} else if(strcmp(szAttribute, "rotate_y") == 0) { } else if (strcmp(szAttribute, "scale_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Y; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_X;
} else if(strcmp(szAttribute, "rotate_z") == 0) { } else if (strcmp(szAttribute, "scale_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Z; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Y;
} else if(strcmp(szAttribute, "scale_x") == 0) { } else if (strcmp(szAttribute, "scale_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_X; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Z;
} else if(strcmp(szAttribute, "scale_y") == 0) { } else if (strcmp(szAttribute, "pre_rotate_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Y; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X;
} else if(strcmp(szAttribute, "scale_z") == 0) { } else if (strcmp(szAttribute, "pre_rotate_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Z; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y;
} else if(strcmp(szAttribute, "pre_rotate_x") == 0) { } else if (strcmp(szAttribute, "pre_rotate_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z;
} else if(strcmp(szAttribute, "pre_rotate_y") == 0) { } else if (strcmp(szAttribute, "post_rotate_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X;
} else if(strcmp(szAttribute, "pre_rotate_z") == 0) { } else if (strcmp(szAttribute, "post_rotate_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y;
} else if(strcmp(szAttribute, "post_rotate_x") == 0) { } else if (strcmp(szAttribute, "post_rotate_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z;
} else if(strcmp(szAttribute, "post_rotate_y") == 0) { } else if (strcmp(szAttribute, "rotate_pivot_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X;
} else if(strcmp(szAttribute, "post_rotate_z") == 0) { } else if (strcmp(szAttribute, "rotate_pivot_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y;
} else if(strcmp(szAttribute, "rotate_pivot_x") == 0) { } else if (strcmp(szAttribute, "rotate_pivot_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z;
} else if(strcmp(szAttribute, "rotate_pivot_y") == 0) { } else if (strcmp(szAttribute, "scale_pivot_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X;
} else if(strcmp(szAttribute, "rotate_pivot_z") == 0) { } else if (strcmp(szAttribute, "scale_pivot_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y;
} else if(strcmp(szAttribute, "scale_pivot_x") == 0) { } else if (strcmp(szAttribute, "scale_pivot_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z;
} else if(strcmp(szAttribute, "scale_pivot_y") == 0) { } else if (strcmp(szAttribute, "rotate_offset_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X;
} else if(strcmp(szAttribute, "scale_pivot_z") == 0) { } else if (strcmp(szAttribute, "rotate_offset_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y;
} else if(strcmp(szAttribute, "rotate_offset_x") == 0) { } else if (strcmp(szAttribute, "rotate_offset_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z;
} else if(strcmp(szAttribute, "rotate_offset_y") == 0) { } else if (strcmp(szAttribute, "scale_offset_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y; m_node_attribute = KRNode::KRENGINE_NODE_SCALE_OFFSET_X;
} else if(strcmp(szAttribute, "rotate_offset_z") == 0) { } else if (strcmp(szAttribute, "scale_offset_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z; m_node_attribute = KRNode::KRENGINE_NODE_SCALE_OFFSET_Y;
} else if(strcmp(szAttribute, "scale_offset_x") == 0) { } else if (strcmp(szAttribute, "scale_offset_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_SCALE_OFFSET_X; m_node_attribute = KRNode::KRENGINE_NODE_SCALE_OFFSET_Z;
} else if(strcmp(szAttribute, "scale_offset_y") == 0) { } else {
m_node_attribute = KRNode::KRENGINE_NODE_SCALE_OFFSET_Y; m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE;
} else if(strcmp(szAttribute, "scale_offset_z") == 0) { }
m_node_attribute = KRNode::KRENGINE_NODE_SCALE_OFFSET_Z;
} else {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE;
}
} }
KRNode::node_attribute_type KRAnimationAttribute::getTargetAttribute() const KRNode::node_attribute_type KRAnimationAttribute::getTargetAttribute() const
{ {
return m_node_attribute; return m_node_attribute;
} }
void KRAnimationAttribute::setTargetAttribute(KRNode::node_attribute_type target_attribute) void KRAnimationAttribute::setTargetAttribute(KRNode::node_attribute_type target_attribute)
{ {
m_node_attribute = target_attribute; m_node_attribute = target_attribute;
} }
std::string KRAnimationAttribute::getTargetName() const std::string KRAnimationAttribute::getTargetName() const
{ {
return m_target_name; return m_target_name;
} }
void KRAnimationAttribute::setTargetName(const std::string &target_name) void KRAnimationAttribute::setTargetName(const std::string& target_name)
{ {
m_target_name = target_name; m_target_name = target_name;
m_target = NULL; m_target = NULL;
} }
std::string KRAnimationAttribute::getCurveName() const std::string KRAnimationAttribute::getCurveName() const
{ {
return m_curve_name; return m_curve_name;
} }
void KRAnimationAttribute::setCurveName(const std::string &curve_name) void KRAnimationAttribute::setCurveName(const std::string& curve_name)
{ {
m_curve_name = curve_name; m_curve_name = curve_name;
m_curve = NULL; m_curve = NULL;
} }
KRNode *KRAnimationAttribute::getTarget() KRNode* KRAnimationAttribute::getTarget()
{ {
if(m_target == NULL) { if (m_target == NULL) {
m_target = getContext().getSceneManager()->getFirstScene()->getRootNode()->find<KRNode>(m_target_name); // FINDME, HACK! - This won't work with multiple scenes in a context; we should move the animations out of KRAnimationManager and attach them to the parent nodes of the animated KRNode's m_target = getContext().getSceneManager()->getFirstScene()->getRootNode()->find<KRNode>(m_target_name); // FINDME, HACK! - This won't work with multiple scenes in a context; we should move the animations out of KRAnimationManager and attach them to the parent nodes of the animated KRNode's
} }
if(m_target == NULL) { if (m_target == NULL) {
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Kraken - Animation attribute could not find object: %s", m_target_name.c_str()); KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Kraken - Animation attribute could not find object: %s", m_target_name.c_str());
} }
return m_target; return m_target;
} }
KRAnimationCurve *KRAnimationAttribute::getCurve() KRAnimationCurve* KRAnimationAttribute::getCurve()
{ {
if(m_curve == NULL) { if (m_curve == NULL) {
m_curve = getContext().getAnimationCurveManager()->getAnimationCurve(m_curve_name.c_str()); m_curve = getContext().getAnimationCurveManager()->getAnimationCurve(m_curve_name.c_str());
} }
return m_curve; return m_curve;
} }
void KRAnimationAttribute::deleteCurve() void KRAnimationAttribute::deleteCurve()
{ {
KRAnimationCurve *curve = getCurve(); KRAnimationCurve* curve = getCurve();
if(curve) { if (curve) {
getContext().getAnimationCurveManager()->deleteAnimationCurve(curve); getContext().getAnimationCurveManager()->deleteAnimationCurve(curve);
m_curve = NULL; m_curve = NULL;
} }
} }

View File

@@ -36,33 +36,34 @@
#include "KRNode.h" #include "KRNode.h"
#include "KRAnimationCurve.h" #include "KRAnimationCurve.h"
class KRAnimationAttribute : public KRContextObject { class KRAnimationAttribute : public KRContextObject
{
public: public:
KRAnimationAttribute(KRContext &context); KRAnimationAttribute(KRContext& context);
~KRAnimationAttribute(); ~KRAnimationAttribute();
tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
void loadXML(tinyxml2::XMLElement *e); void loadXML(tinyxml2::XMLElement* e);
std::string getCurveName() const; std::string getCurveName() const;
void setCurveName(const std::string &curve_name); void setCurveName(const std::string& curve_name);
std::string getTargetName() const; std::string getTargetName() const;
void setTargetName(const std::string &target_name); void setTargetName(const std::string& target_name);
KRNode::node_attribute_type getTargetAttribute() const; KRNode::node_attribute_type getTargetAttribute() const;
void setTargetAttribute(KRNode::node_attribute_type target_attribute); void setTargetAttribute(KRNode::node_attribute_type target_attribute);
KRNode *getTarget(); KRNode* getTarget();
KRAnimationCurve *getCurve(); KRAnimationCurve* getCurve();
void deleteCurve(); void deleteCurve();
private: private:
std::string m_target_name; std::string m_target_name;
std::string m_curve_name; std::string m_curve_name;
KRNode::node_attribute_type m_node_attribute; KRNode::node_attribute_type m_node_attribute;
KRNode *m_target; KRNode* m_target;
KRAnimationCurve *m_curve; KRAnimationCurve* m_curve;
}; };

View File

@@ -33,208 +33,211 @@
#include "KRAnimationCurve.h" #include "KRAnimationCurve.h"
#include "KRDataBlock.h" #include "KRDataBlock.h"
KRAnimationCurve::KRAnimationCurve(KRContext &context, const std::string &name) : KRResource(context, name) KRAnimationCurve::KRAnimationCurve(KRContext& context, const std::string& name) : KRResource(context, name)
{ {
m_pData = new KRDataBlock(); m_pData = new KRDataBlock();
m_pData->expand(sizeof(animation_curve_header)); m_pData->expand(sizeof(animation_curve_header));
m_pData->lock(); m_pData->lock();
animation_curve_header *header = (animation_curve_header *)m_pData->getStart(); animation_curve_header* header = (animation_curve_header*)m_pData->getStart();
strcpy(header->szTag, "KRCURVE1.0 "); strcpy(header->szTag, "KRCURVE1.0 ");
header->frame_rate = 30.0f; header->frame_rate = 30.0f;
header->frame_start = 0; header->frame_start = 0;
header->frame_count = 0; header->frame_count = 0;
m_pData->unlock(); m_pData->unlock();
} }
KRAnimationCurve::~KRAnimationCurve() KRAnimationCurve::~KRAnimationCurve()
{ {
m_pData->unload(); m_pData->unload();
delete m_pData; delete m_pData;
} }
bool KRAnimationCurve::load(KRDataBlock *data) bool KRAnimationCurve::load(KRDataBlock* data)
{ {
m_pData->unload(); m_pData->unload();
delete m_pData; delete m_pData;
m_pData = data; m_pData = data;
return true; return true;
} }
std::string KRAnimationCurve::getExtension() { std::string KRAnimationCurve::getExtension()
return "kranimationcurve";
}
bool KRAnimationCurve::save(const std::string& path) {
return m_pData->save(path);
}
bool KRAnimationCurve::save(KRDataBlock &data) {
data.append(*m_pData);
return true;
}
KRAnimationCurve *KRAnimationCurve::Load(KRContext &context, const std::string &name, KRDataBlock *data)
{ {
KRAnimationCurve *new_animation_curve = new KRAnimationCurve(context, name); return "kranimationcurve";
if(new_animation_curve->load(data)) { }
return new_animation_curve;
} else { bool KRAnimationCurve::save(const std::string& path)
delete new_animation_curve; {
delete data; return m_pData->save(path);
return NULL; }
}
bool KRAnimationCurve::save(KRDataBlock& data)
{
data.append(*m_pData);
return true;
}
KRAnimationCurve* KRAnimationCurve::Load(KRContext& context, const std::string& name, KRDataBlock* data)
{
KRAnimationCurve* new_animation_curve = new KRAnimationCurve(context, name);
if (new_animation_curve->load(data)) {
return new_animation_curve;
} else {
delete new_animation_curve;
delete data;
return NULL;
}
} }
int KRAnimationCurve::getFrameCount() int KRAnimationCurve::getFrameCount()
{ {
m_pData->lock(); m_pData->lock();
int frame_count = ((animation_curve_header *)m_pData->getStart())->frame_count; int frame_count = ((animation_curve_header*)m_pData->getStart())->frame_count;
m_pData->unlock(); m_pData->unlock();
return frame_count; return frame_count;
} }
void KRAnimationCurve::setFrameCount(int frame_count) void KRAnimationCurve::setFrameCount(int frame_count)
{ {
m_pData->lock(); m_pData->lock();
int prev_frame_count = getFrameCount(); int prev_frame_count = getFrameCount();
if(frame_count != prev_frame_count) { if (frame_count != prev_frame_count) {
float fill_value = 0.0f; float fill_value = 0.0f;
if(prev_frame_count > 0) { if (prev_frame_count > 0) {
fill_value = getValue(prev_frame_count - 1); fill_value = getValue(prev_frame_count - 1);
}
m_pData->expand(sizeof(animation_curve_header) + sizeof(float) * frame_count - m_pData->getSize());
float *frame_data = (float *)((char *)m_pData->getStart() + sizeof(animation_curve_header));
for(int frame_number=prev_frame_count; frame_number < frame_count; frame_number++) {
frame_data[frame_number] = fill_value;
}
((animation_curve_header *)m_pData->getStart())->frame_count = frame_count;
} }
m_pData->unlock(); m_pData->expand(sizeof(animation_curve_header) + sizeof(float) * frame_count - m_pData->getSize());
float* frame_data = (float*)((char*)m_pData->getStart() + sizeof(animation_curve_header));
for (int frame_number = prev_frame_count; frame_number < frame_count; frame_number++) {
frame_data[frame_number] = fill_value;
}
((animation_curve_header*)m_pData->getStart())->frame_count = frame_count;
}
m_pData->unlock();
} }
float KRAnimationCurve::getFrameRate() float KRAnimationCurve::getFrameRate()
{ {
m_pData->lock(); m_pData->lock();
float frame_rate =((animation_curve_header *)m_pData->getStart())->frame_rate; float frame_rate = ((animation_curve_header*)m_pData->getStart())->frame_rate;
m_pData->unlock(); m_pData->unlock();
return frame_rate; return frame_rate;
} }
void KRAnimationCurve::setFrameRate(float frame_rate) void KRAnimationCurve::setFrameRate(float frame_rate)
{ {
m_pData->lock(); m_pData->lock();
((animation_curve_header *)m_pData->getStart())->frame_rate = frame_rate; ((animation_curve_header*)m_pData->getStart())->frame_rate = frame_rate;
m_pData->unlock(); m_pData->unlock();
} }
int KRAnimationCurve::getFrameStart() int KRAnimationCurve::getFrameStart()
{ {
m_pData->lock(); m_pData->lock();
int frame_start = ((animation_curve_header *)m_pData->getStart())->frame_start; int frame_start = ((animation_curve_header*)m_pData->getStart())->frame_start;
m_pData->unlock(); m_pData->unlock();
return frame_start; return frame_start;
} }
void KRAnimationCurve::setFrameStart(int frame_number) void KRAnimationCurve::setFrameStart(int frame_number)
{ {
m_pData->lock(); m_pData->lock();
((animation_curve_header *)m_pData->getStart())->frame_start = frame_number; ((animation_curve_header*)m_pData->getStart())->frame_start = frame_number;
m_pData->unlock(); m_pData->unlock();
} }
float KRAnimationCurve::getValue(int frame_number) float KRAnimationCurve::getValue(int frame_number)
{ {
m_pData->lock(); m_pData->lock();
//printf("frame_number: %i\n", frame_number); //printf("frame_number: %i\n", frame_number);
int clamped_frame = frame_number - getFrameStart(); int clamped_frame = frame_number - getFrameStart();
if(clamped_frame < 0) { if (clamped_frame < 0) {
clamped_frame = 0; clamped_frame = 0;
} else if(clamped_frame >= getFrameCount()) { } else if (clamped_frame >= getFrameCount()) {
clamped_frame = getFrameCount()-1; clamped_frame = getFrameCount() - 1;
} }
float *frame_data = (float *)((char *)m_pData->getStart() + sizeof(animation_curve_header)); float* frame_data = (float*)((char*)m_pData->getStart() + sizeof(animation_curve_header));
float v = frame_data[clamped_frame]; float v = frame_data[clamped_frame];
m_pData->unlock(); m_pData->unlock();
return v; return v;
} }
void KRAnimationCurve::setValue(int frame_number, float value) void KRAnimationCurve::setValue(int frame_number, float value)
{ {
m_pData->lock(); m_pData->lock();
int clamped_frame = frame_number - getFrameStart(); int clamped_frame = frame_number - getFrameStart();
if(clamped_frame >= 0 && clamped_frame < getFrameCount()) { if (clamped_frame >= 0 && clamped_frame < getFrameCount()) {
float *frame_data = (float *)((char *)m_pData->getStart() + sizeof(animation_curve_header)); float* frame_data = (float*)((char*)m_pData->getStart() + sizeof(animation_curve_header));
frame_data[clamped_frame] = value; frame_data[clamped_frame] = value;
} }
m_pData->unlock(); m_pData->unlock();
} }
float KRAnimationCurve::getValue(float local_time) float KRAnimationCurve::getValue(float local_time)
{ {
// TODO - Need to add interpolation for time values between frames. // TODO - Need to add interpolation for time values between frames.
// Must consider looping animations when determining which two frames to interpolate between. // Must consider looping animations when determining which two frames to interpolate between.
m_pData->lock(); m_pData->lock();
float v = getValue((int)(local_time * getFrameRate())); float v = getValue((int)(local_time * getFrameRate()));
m_pData->unlock(); m_pData->unlock();
return v; return v;
} }
bool KRAnimationCurve::valueChanges(float start_time, float duration) bool KRAnimationCurve::valueChanges(float start_time, float duration)
{ {
m_pData->lock(); m_pData->lock();
bool c = valueChanges((int)(start_time * getFrameRate()), (int)(duration * getFrameRate())); bool c = valueChanges((int)(start_time * getFrameRate()), (int)(duration * getFrameRate()));
m_pData->unlock(); m_pData->unlock();
return c; return c;
} }
bool KRAnimationCurve::valueChanges(int start_frame, int frame_count) bool KRAnimationCurve::valueChanges(int start_frame, int frame_count)
{ {
m_pData->lock(); m_pData->lock();
float first_value = getValue(start_frame); float first_value = getValue(start_frame);
bool change_found = false; bool change_found = false;
// Range of frames is not inclusive of last frame // Range of frames is not inclusive of last frame
for(int frame_number = start_frame + 1; frame_number < start_frame + frame_count && !change_found; frame_number++) { for (int frame_number = start_frame + 1; frame_number < start_frame + frame_count && !change_found; frame_number++) {
if(getValue(frame_number) != first_value) { if (getValue(frame_number) != first_value) {
change_found = true; change_found = true;
}
} }
}
m_pData->unlock();
return change_found; m_pData->unlock();
return change_found;
} }
KRAnimationCurve *KRAnimationCurve::split(const std::string &name, float start_time, float duration) KRAnimationCurve* KRAnimationCurve::split(const std::string& name, float start_time, float duration)
{ {
return split(name, (int)(start_time * getFrameRate()), (int)(duration * getFrameRate())); return split(name, (int)(start_time * getFrameRate()), (int)(duration * getFrameRate()));
} }
KRAnimationCurve *KRAnimationCurve::split(const std::string &name, int start_frame, int frame_count) KRAnimationCurve* KRAnimationCurve::split(const std::string& name, int start_frame, int frame_count)
{ {
KRAnimationCurve *new_curve = new KRAnimationCurve(getContext(), name); KRAnimationCurve* new_curve = new KRAnimationCurve(getContext(), name);
new_curve->setFrameRate(getFrameRate()); new_curve->setFrameRate(getFrameRate());
new_curve->setFrameStart(start_frame); new_curve->setFrameStart(start_frame);
new_curve->setFrameCount(frame_count); new_curve->setFrameCount(frame_count);
new_curve->m_pData->lock(); new_curve->m_pData->lock();
// Range of frames is not inclusive of last frame // Range of frames is not inclusive of last frame
for(int frame_number = start_frame; frame_number < start_frame + frame_count; frame_number++) { for (int frame_number = start_frame; frame_number < start_frame + frame_count; frame_number++) {
new_curve->setValue(frame_number, getValue(frame_number)); // TODO - MEMCPY here? new_curve->setValue(frame_number, getValue(frame_number)); // TODO - MEMCPY here?
} }
new_curve->m_pData->unlock(); new_curve->m_pData->unlock();
getContext().getAnimationCurveManager()->addAnimationCurve(new_curve); getContext().getAnimationCurveManager()->addAnimationCurve(new_curve);
return new_curve; return new_curve;
} }
void KRAnimationCurve::_lockData() void KRAnimationCurve::_lockData()
{ {
m_pData->lock(); m_pData->lock();
} }
void KRAnimationCurve::_unlockData() void KRAnimationCurve::_unlockData()
{ {
m_pData->unlock(); m_pData->unlock();
} }

View File

@@ -36,48 +36,50 @@
#include "KRDataBlock.h" #include "KRDataBlock.h"
#include "KRResource.h" #include "KRResource.h"
class KRAnimationCurve : public KRResource { class KRAnimationCurve : public KRResource
{
public: public:
KRAnimationCurve(KRContext &context, const std::string &name); KRAnimationCurve(KRContext& context, const std::string& name);
virtual ~KRAnimationCurve(); virtual ~KRAnimationCurve();
virtual std::string getExtension(); virtual std::string getExtension();
virtual bool save(const std::string& path); virtual bool save(const std::string& path);
virtual bool save(KRDataBlock &data); virtual bool save(KRDataBlock& data);
virtual bool load(KRDataBlock *data); virtual bool load(KRDataBlock* data);
float getFrameRate(); float getFrameRate();
void setFrameRate(float frame_rate); void setFrameRate(float frame_rate);
int getFrameStart(); int getFrameStart();
void setFrameStart(int frame_number); void setFrameStart(int frame_number);
int getFrameCount(); int getFrameCount();
void setFrameCount(int frame_count); void setFrameCount(int frame_count);
float getValue(float local_time); float getValue(float local_time);
float getValue(int frame_number); float getValue(int frame_number);
void setValue(int frame_number, float value); void setValue(int frame_number, float value);
static KRAnimationCurve *Load(KRContext &context, const std::string &name, KRDataBlock *data); static KRAnimationCurve* Load(KRContext& context, const std::string& name, KRDataBlock* data);
bool valueChanges(float start_time, float duration); bool valueChanges(float start_time, float duration);
bool valueChanges(int start_frame, int frame_count); bool valueChanges(int start_frame, int frame_count);
KRAnimationCurve *split(const std::string &name, float start_time, float duration); KRAnimationCurve* split(const std::string& name, float start_time, float duration);
KRAnimationCurve *split(const std::string &name, int start_frame, int frame_count); KRAnimationCurve* split(const std::string& name, int start_frame, int frame_count);
void _lockData(); void _lockData();
void _unlockData(); void _unlockData();
private: private:
KRDataBlock *m_pData; KRDataBlock* m_pData;
typedef struct { typedef struct
char szTag[16]; {
float frame_rate; char szTag[16];
int32_t frame_start; float frame_rate;
int32_t frame_count; int32_t frame_start;
} animation_curve_header; int32_t frame_count;
} animation_curve_header;
}; };

View File

@@ -32,61 +32,66 @@
#include "KRAnimationCurveManager.h" #include "KRAnimationCurveManager.h"
#include "KRAnimationCurve.h" #include "KRAnimationCurve.h"
KRAnimationCurveManager::KRAnimationCurveManager(KRContext &context) : KRResourceManager(context) KRAnimationCurveManager::KRAnimationCurveManager(KRContext& context) : KRResourceManager(context)
{ {
} }
KRAnimationCurveManager::~KRAnimationCurveManager() { KRAnimationCurveManager::~KRAnimationCurveManager()
for(unordered_map<std::string, KRAnimationCurve *>::iterator itr = m_animationCurves.begin(); itr != m_animationCurves.end(); ++itr){ {
delete (*itr).second; for (unordered_map<std::string, KRAnimationCurve*>::iterator itr = m_animationCurves.begin(); itr != m_animationCurves.end(); ++itr) {
} delete (*itr).second;
}
} }
void KRAnimationCurveManager::deleteAnimationCurve(KRAnimationCurve *curve) { void KRAnimationCurveManager::deleteAnimationCurve(KRAnimationCurve* curve)
m_animationCurves.erase(curve->getName()); {
delete curve; m_animationCurves.erase(curve->getName());
delete curve;
} }
KRResource* KRAnimationCurveManager::loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) KRResource* KRAnimationCurveManager::loadResource(const std::string& name, const std::string& extension, KRDataBlock* data)
{ {
if (extension.compare("kranimationcurve") == 0) { if (extension.compare("kranimationcurve") == 0) {
return loadAnimationCurve(name, data); return loadAnimationCurve(name, data);
} }
return nullptr; return nullptr;
} }
KRResource* KRAnimationCurveManager::getResource(const std::string& name, const std::string& extension) KRResource* KRAnimationCurveManager::getResource(const std::string& name, const std::string& extension)
{ {
if (extension.compare("kranimationcurve") == 0) { if (extension.compare("kranimationcurve") == 0) {
return getAnimationCurve(name); return getAnimationCurve(name);
} }
return nullptr; return nullptr;
} }
KRAnimationCurve *KRAnimationCurveManager::loadAnimationCurve(const std::string &name, KRDataBlock *data) { KRAnimationCurve* KRAnimationCurveManager::loadAnimationCurve(const std::string& name, KRDataBlock* data)
KRAnimationCurve *pAnimationCurve = KRAnimationCurve::Load(*m_pContext, name, data);
if(pAnimationCurve) {
m_animationCurves[name] = pAnimationCurve;
}
return pAnimationCurve;
}
KRAnimationCurve *KRAnimationCurveManager::getAnimationCurve(const std::string &name) {
unordered_map<std::string, KRAnimationCurve *>::iterator itr = m_animationCurves.find(name);
if(itr == m_animationCurves.end()) {
return NULL; // Not found
} else {
return (*itr).second;
}
}
unordered_map<std::string, KRAnimationCurve *> &KRAnimationCurveManager::getAnimationCurves() {
return m_animationCurves;
}
void KRAnimationCurveManager::addAnimationCurve(KRAnimationCurve *new_animation_curve)
{ {
assert(new_animation_curve != NULL); KRAnimationCurve* pAnimationCurve = KRAnimationCurve::Load(*m_pContext, name, data);
m_animationCurves[new_animation_curve->getName()] = new_animation_curve; if (pAnimationCurve) {
m_animationCurves[name] = pAnimationCurve;
}
return pAnimationCurve;
}
KRAnimationCurve* KRAnimationCurveManager::getAnimationCurve(const std::string& name)
{
unordered_map<std::string, KRAnimationCurve*>::iterator itr = m_animationCurves.find(name);
if (itr == m_animationCurves.end()) {
return NULL; // Not found
} else {
return (*itr).second;
}
}
unordered_map<std::string, KRAnimationCurve*>& KRAnimationCurveManager::getAnimationCurves()
{
return m_animationCurves;
}
void KRAnimationCurveManager::addAnimationCurve(KRAnimationCurve* new_animation_curve)
{
assert(new_animation_curve != NULL);
m_animationCurves[new_animation_curve->getName()] = new_animation_curve;
} }

View File

@@ -41,22 +41,23 @@
using std::map; using std::map;
class KRAnimationCurveManager : public KRResourceManager { class KRAnimationCurveManager : public KRResourceManager
{
public: public:
KRAnimationCurveManager(KRContext &context); KRAnimationCurveManager(KRContext& context);
virtual ~KRAnimationCurveManager(); virtual ~KRAnimationCurveManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override; virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override; virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
KRAnimationCurve* loadAnimationCurve(const std::string& name, KRDataBlock* data);
KRAnimationCurve* getAnimationCurve(const std::string& name);
void addAnimationCurve(KRAnimationCurve* new_animation_curve);
unordered_map<std::string, KRAnimationCurve*>& getAnimationCurves();
void deleteAnimationCurve(KRAnimationCurve* curve);
KRAnimationCurve *loadAnimationCurve(const std::string &name, KRDataBlock *data);
KRAnimationCurve *getAnimationCurve(const std::string &name);
void addAnimationCurve(KRAnimationCurve *new_animation_curve);
unordered_map<std::string, KRAnimationCurve *> &getAnimationCurves();
void deleteAnimationCurve(KRAnimationCurve *curve);
private: private:
unordered_map<std::string, KRAnimationCurve *> m_animationCurves; unordered_map<std::string, KRAnimationCurve*> m_animationCurves;
}; };

View File

@@ -31,168 +31,168 @@
#include "KRAnimationLayer.h" #include "KRAnimationLayer.h"
KRAnimationLayer::KRAnimationLayer(KRContext &context) : KRContextObject(context) KRAnimationLayer::KRAnimationLayer(KRContext& context) : KRContextObject(context)
{ {
m_name = ""; m_name = "";
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE; m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE;
m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER; m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER;
m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY; m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY;
} }
KRAnimationLayer::~KRAnimationLayer() KRAnimationLayer::~KRAnimationLayer()
{ {
for(std::vector<KRAnimationAttribute *>::iterator itr = m_attributes.begin(); itr != m_attributes.end(); ++itr){ for (std::vector<KRAnimationAttribute*>::iterator itr = m_attributes.begin(); itr != m_attributes.end(); ++itr) {
delete (*itr); delete (*itr);
} }
} }
std::string KRAnimationLayer::getName() const std::string KRAnimationLayer::getName() const
{ {
return m_name; return m_name;
} }
void KRAnimationLayer::setName(const std::string &name) void KRAnimationLayer::setName(const std::string& name)
{ {
m_name = name; m_name = name;
} }
tinyxml2::XMLElement *KRAnimationLayer::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement* KRAnimationLayer::saveXML(tinyxml2::XMLNode* parent)
{ {
tinyxml2::XMLDocument *doc = parent->GetDocument(); tinyxml2::XMLDocument* doc = parent->GetDocument();
tinyxml2::XMLElement *e = doc->NewElement("layer"); tinyxml2::XMLElement* e = doc->NewElement("layer");
tinyxml2::XMLNode *n = parent->InsertEndChild(e); tinyxml2::XMLNode* n = parent->InsertEndChild(e);
e->SetAttribute("name", m_name.c_str()); e->SetAttribute("name", m_name.c_str());
e->SetAttribute("weight", m_weight); e->SetAttribute("weight", m_weight);
switch(m_blend_mode) { switch (m_blend_mode) {
case KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE: case KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE:
e->SetAttribute("blend_mode", "additive"); e->SetAttribute("blend_mode", "additive");
break; break;
case KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE: case KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE:
e->SetAttribute("blend_mode", "override"); e->SetAttribute("blend_mode", "override");
break; break;
case KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE_PASSTHROUGH: case KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE_PASSTHROUGH:
e->SetAttribute("blend_mode", "override_passthrough"); e->SetAttribute("blend_mode", "override_passthrough");
break; break;
} }
switch(m_rotation_accumulation_mode) { switch (m_rotation_accumulation_mode) {
case KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_CHANNEL: case KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_CHANNEL:
e->SetAttribute("rotation_accumulation_mode", "by_channel"); e->SetAttribute("rotation_accumulation_mode", "by_channel");
break; break;
case KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER: case KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER:
e->SetAttribute("rotation_accumulation_mode", "by_layer"); e->SetAttribute("rotation_accumulation_mode", "by_layer");
break; break;
} }
switch(m_scale_accumulation_mode) { switch (m_scale_accumulation_mode) {
case KRENGINE_ANIMATION_SCALE_ACCUMULATION_ADDITIVE: case KRENGINE_ANIMATION_SCALE_ACCUMULATION_ADDITIVE:
e->SetAttribute("scale_accumulation_mode", "additive"); e->SetAttribute("scale_accumulation_mode", "additive");
break; break;
case KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY: case KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY:
e->SetAttribute("scale_accumulation_mode", "multiply"); e->SetAttribute("scale_accumulation_mode", "multiply");
break; break;
} }
for(std::vector<KRAnimationAttribute *>::iterator itr = m_attributes.begin(); itr != m_attributes.end(); ++itr){ for (std::vector<KRAnimationAttribute*>::iterator itr = m_attributes.begin(); itr != m_attributes.end(); ++itr) {
(*itr)->saveXML(n); (*itr)->saveXML(n);
} }
return e; return e;
} }
void KRAnimationLayer::loadXML(tinyxml2::XMLElement *e) void KRAnimationLayer::loadXML(tinyxml2::XMLElement* e)
{ {
m_name = e->Attribute("name"); m_name = e->Attribute("name");
if(e->QueryFloatAttribute("weight", &m_weight) != tinyxml2::XML_SUCCESS) { if (e->QueryFloatAttribute("weight", &m_weight) != tinyxml2::XML_SUCCESS) {
m_weight = 1.0f; // default m_weight = 1.0f; // default
} }
const char *szBlendMode = e->Attribute("blend_mode"); const char* szBlendMode = e->Attribute("blend_mode");
if(strcmp(szBlendMode, "additive") == 0) { if (strcmp(szBlendMode, "additive") == 0) {
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE; m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE;
} else if(strcmp(szBlendMode, "override") == 0) { } else if (strcmp(szBlendMode, "override") == 0) {
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE; m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE;
} else if(strcmp(szBlendMode, "override_passthrough") == 0) { } else if (strcmp(szBlendMode, "override_passthrough") == 0) {
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE_PASSTHROUGH; m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE_PASSTHROUGH;
} else { } else {
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE; // default m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE; // default
} }
const char *szRotationAccumulationMode = e->Attribute("rotation_accumulation_mode"); const char* szRotationAccumulationMode = e->Attribute("rotation_accumulation_mode");
if(strcmp(szRotationAccumulationMode, "by_channel") == 0) { if (strcmp(szRotationAccumulationMode, "by_channel") == 0) {
m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_CHANNEL; m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_CHANNEL;
} else if(strcmp(szRotationAccumulationMode, "by_layer") == 0) { } else if (strcmp(szRotationAccumulationMode, "by_layer") == 0) {
m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER; m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER;
} else { } else {
m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER; // default m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER; // default
} }
const char *szScaleAccumulationMode = e->Attribute("scale_accumulation_mode"); const char* szScaleAccumulationMode = e->Attribute("scale_accumulation_mode");
if(strcmp(szScaleAccumulationMode, "additive") == 0) { if (strcmp(szScaleAccumulationMode, "additive") == 0) {
m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_ADDITIVE; m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_ADDITIVE;
} else if(strcmp(szScaleAccumulationMode, "multiply") == 0) { } else if (strcmp(szScaleAccumulationMode, "multiply") == 0) {
m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY; m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY;
} else { } else {
m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY; // default m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY; // default
} }
for(tinyxml2::XMLElement *child_element=e->FirstChildElement(); child_element != NULL; child_element = child_element->NextSiblingElement()) { for (tinyxml2::XMLElement* child_element = e->FirstChildElement(); child_element != NULL; child_element = child_element->NextSiblingElement()) {
if(strcmp(child_element->Name(), "attribute") == 0) { if (strcmp(child_element->Name(), "attribute") == 0) {
KRAnimationAttribute *new_attribute = new KRAnimationAttribute(getContext()); KRAnimationAttribute* new_attribute = new KRAnimationAttribute(getContext());
new_attribute->loadXML(child_element); new_attribute->loadXML(child_element);
m_attributes.push_back(new_attribute); m_attributes.push_back(new_attribute);
}
} }
}
} }
float KRAnimationLayer::getWeight() const float KRAnimationLayer::getWeight() const
{ {
return m_weight; return m_weight;
} }
void KRAnimationLayer::setWeight(float weight) void KRAnimationLayer::setWeight(float weight)
{ {
m_weight = weight; m_weight = weight;
} }
KRAnimationLayer::blend_mode_t KRAnimationLayer::getBlendMode() const KRAnimationLayer::blend_mode_t KRAnimationLayer::getBlendMode() const
{ {
return m_blend_mode; return m_blend_mode;
} }
void KRAnimationLayer::setBlendMode(const KRAnimationLayer::blend_mode_t &blend_mode) void KRAnimationLayer::setBlendMode(const KRAnimationLayer::blend_mode_t& blend_mode)
{ {
m_blend_mode = blend_mode; m_blend_mode = blend_mode;
} }
KRAnimationLayer::rotation_accumulation_mode_t KRAnimationLayer::getRotationAccumulationMode() const KRAnimationLayer::rotation_accumulation_mode_t KRAnimationLayer::getRotationAccumulationMode() const
{ {
return m_rotation_accumulation_mode; return m_rotation_accumulation_mode;
} }
void KRAnimationLayer::setRotationAccumulationMode(const KRAnimationLayer::rotation_accumulation_mode_t &rotation_accumulation_mode) void KRAnimationLayer::setRotationAccumulationMode(const KRAnimationLayer::rotation_accumulation_mode_t& rotation_accumulation_mode)
{ {
m_rotation_accumulation_mode = rotation_accumulation_mode; m_rotation_accumulation_mode = rotation_accumulation_mode;
} }
KRAnimationLayer::scale_accumulation_mode_t KRAnimationLayer::getScaleAccumulationMode() const KRAnimationLayer::scale_accumulation_mode_t KRAnimationLayer::getScaleAccumulationMode() const
{ {
return m_scale_accumulation_mode; return m_scale_accumulation_mode;
} }
void KRAnimationLayer::setScaleAccumulationMode(const KRAnimationLayer::scale_accumulation_mode_t &scale_accumulation_mode) void KRAnimationLayer::setScaleAccumulationMode(const KRAnimationLayer::scale_accumulation_mode_t& scale_accumulation_mode)
{ {
m_scale_accumulation_mode = scale_accumulation_mode; m_scale_accumulation_mode = scale_accumulation_mode;
} }
void KRAnimationLayer::addAttribute(KRAnimationAttribute *attribute) void KRAnimationLayer::addAttribute(KRAnimationAttribute* attribute)
{ {
m_attributes.push_back(attribute); m_attributes.push_back(attribute);
} }
std::vector<KRAnimationAttribute *> &KRAnimationLayer::getAttributes() std::vector<KRAnimationAttribute*>& KRAnimationLayer::getAttributes()
{ {
return m_attributes; return m_attributes;
} }

View File

@@ -36,58 +36,62 @@
#include "KRAnimationAttribute.h" #include "KRAnimationAttribute.h"
namespace tinyxml2 { namespace tinyxml2 {
class XMLNode; class XMLNode;
class XMLAttribute; class XMLAttribute;
} }
class KRAnimationLayer : public KRContextObject { class KRAnimationLayer : public KRContextObject
{
public: public:
KRAnimationLayer(KRContext &context); KRAnimationLayer(KRContext& context);
~KRAnimationLayer(); ~KRAnimationLayer();
tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
void loadXML(tinyxml2::XMLElement *e); void loadXML(tinyxml2::XMLElement* e);
std::string getName() const; std::string getName() const;
void setName(const std::string &name); void setName(const std::string& name);
float getWeight() const; float getWeight() const;
void setWeight(float weight); void setWeight(float weight);
typedef enum { typedef enum
KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE, {
KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE, KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE,
KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE_PASSTHROUGH KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE,
} blend_mode_t; KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE_PASSTHROUGH
} blend_mode_t;
blend_mode_t getBlendMode() const;
void setBlendMode(const blend_mode_t &blend_mode); blend_mode_t getBlendMode() const;
void setBlendMode(const blend_mode_t& blend_mode);
typedef enum {
KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER, typedef enum
KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_CHANNEL {
} rotation_accumulation_mode_t; KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER,
KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_CHANNEL
rotation_accumulation_mode_t getRotationAccumulationMode() const; } rotation_accumulation_mode_t;
void setRotationAccumulationMode(const rotation_accumulation_mode_t &rotation_accumulation_mode);
rotation_accumulation_mode_t getRotationAccumulationMode() const;
typedef enum { void setRotationAccumulationMode(const rotation_accumulation_mode_t& rotation_accumulation_mode);
KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY,
KRENGINE_ANIMATION_SCALE_ACCUMULATION_ADDITIVE typedef enum
} scale_accumulation_mode_t; {
KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY,
scale_accumulation_mode_t getScaleAccumulationMode() const; KRENGINE_ANIMATION_SCALE_ACCUMULATION_ADDITIVE
void setScaleAccumulationMode(const scale_accumulation_mode_t &scale_accumulation_mode); } scale_accumulation_mode_t;
scale_accumulation_mode_t getScaleAccumulationMode() const;
void setScaleAccumulationMode(const scale_accumulation_mode_t& scale_accumulation_mode);
void addAttribute(KRAnimationAttribute* attribute);
std::vector<KRAnimationAttribute*>& getAttributes();
void addAttribute(KRAnimationAttribute *attribute);
std::vector<KRAnimationAttribute *> &getAttributes();
private: private:
std::string m_name; std::string m_name;
float m_weight; float m_weight;
blend_mode_t m_blend_mode; blend_mode_t m_blend_mode;
rotation_accumulation_mode_t m_rotation_accumulation_mode; rotation_accumulation_mode_t m_rotation_accumulation_mode;
scale_accumulation_mode_t m_scale_accumulation_mode; scale_accumulation_mode_t m_scale_accumulation_mode;
std::vector<KRAnimationAttribute *> m_attributes; std::vector<KRAnimationAttribute*> m_attributes;
}; };

View File

@@ -32,53 +32,54 @@
#include "KRAnimationManager.h" #include "KRAnimationManager.h"
#include "KRAnimation.h" #include "KRAnimation.h"
KRAnimationManager::KRAnimationManager(KRContext &context) : KRResourceManager(context) KRAnimationManager::KRAnimationManager(KRContext& context) : KRResourceManager(context)
{ {
} }
KRAnimationManager::~KRAnimationManager() { KRAnimationManager::~KRAnimationManager()
for(std::set<KRAnimation *>::iterator itr = m_activeAnimations.begin(); itr != m_activeAnimations.end(); itr++) { {
KRAnimation *animation = *itr; for (std::set<KRAnimation*>::iterator itr = m_activeAnimations.begin(); itr != m_activeAnimations.end(); itr++) {
animation->_unlockData(); KRAnimation* animation = *itr;
} animation->_unlockData();
}
for(unordered_map<std::string, KRAnimation *>::iterator itr = m_animations.begin(); itr != m_animations.end(); ++itr){
delete (*itr).second; for (unordered_map<std::string, KRAnimation*>::iterator itr = m_animations.begin(); itr != m_animations.end(); ++itr) {
} delete (*itr).second;
}
} }
void KRAnimationManager::startFrame(float deltaTime) void KRAnimationManager::startFrame(float deltaTime)
{ {
for(std::set<KRAnimation *>::iterator itr = m_animationsToUpdate.begin(); itr != m_animationsToUpdate.end(); itr++) { for (std::set<KRAnimation*>::iterator itr = m_animationsToUpdate.begin(); itr != m_animationsToUpdate.end(); itr++) {
KRAnimation *animation = *itr; KRAnimation* animation = *itr;
std::set<KRAnimation *>::iterator active_animations_itr = m_activeAnimations.find(animation); std::set<KRAnimation*>::iterator active_animations_itr = m_activeAnimations.find(animation);
if(animation->isPlaying()) { if (animation->isPlaying()) {
// Add playing animations to the active animations list // Add playing animations to the active animations list
if(active_animations_itr == m_activeAnimations.end()) { if (active_animations_itr == m_activeAnimations.end()) {
m_activeAnimations.insert(animation); m_activeAnimations.insert(animation);
animation->_lockData(); animation->_lockData();
} }
} else { } else {
// Remove stopped animations from the active animations list // Remove stopped animations from the active animations list
if(active_animations_itr != m_activeAnimations.end()) { if (active_animations_itr != m_activeAnimations.end()) {
m_activeAnimations.erase(active_animations_itr); m_activeAnimations.erase(active_animations_itr);
animation->_unlockData(); animation->_unlockData();
} }
}
}
m_animationsToUpdate.clear();
for(std::set<KRAnimation *>::iterator active_animations_itr = m_activeAnimations.begin(); active_animations_itr != m_activeAnimations.end(); active_animations_itr++) {
KRAnimation *animation = *active_animations_itr;
animation->update(deltaTime);
} }
}
m_animationsToUpdate.clear();
for (std::set<KRAnimation*>::iterator active_animations_itr = m_activeAnimations.begin(); active_animations_itr != m_activeAnimations.end(); active_animations_itr++) {
KRAnimation* animation = *active_animations_itr;
animation->update(deltaTime);
}
} }
void KRAnimationManager::endFrame(float deltaTime) void KRAnimationManager::endFrame(float deltaTime)
{ {
} }
KRResource* KRAnimationManager::loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) KRResource* KRAnimationManager::loadResource(const std::string& name, const std::string& extension, KRDataBlock* data)
@@ -96,37 +97,39 @@ KRResource* KRAnimationManager::getResource(const std::string& name, const std::
return nullptr; return nullptr;
} }
KRAnimation *KRAnimationManager::loadAnimation(const char *szName, KRDataBlock *data) { KRAnimation* KRAnimationManager::loadAnimation(const char* szName, KRDataBlock* data)
KRAnimation *pAnimation = KRAnimation::Load(*m_pContext, szName, data);
addAnimation(pAnimation);
return pAnimation;
}
KRAnimation *KRAnimationManager::getAnimation(const char *szName) {
return m_animations[szName];
}
unordered_map<std::string, KRAnimation *> &KRAnimationManager::getAnimations() {
return m_animations;
}
void KRAnimationManager::addAnimation(KRAnimation *new_animation)
{ {
m_animations[new_animation->getName()] = new_animation; KRAnimation* pAnimation = KRAnimation::Load(*m_pContext, szName, data);
updateActiveAnimations(new_animation); addAnimation(pAnimation);
return pAnimation;
} }
void KRAnimationManager::updateActiveAnimations(KRAnimation *animation) KRAnimation* KRAnimationManager::getAnimation(const char* szName)
{ {
m_animationsToUpdate.insert(animation); return m_animations[szName];
} }
void KRAnimationManager::deleteAnimation(KRAnimation *animation, bool delete_curves) unordered_map<std::string, KRAnimation*>& KRAnimationManager::getAnimations()
{ {
if(delete_curves) return m_animations;
{ }
animation->deleteCurves();
} void KRAnimationManager::addAnimation(KRAnimation* new_animation)
m_animations.erase(animation->getName()); {
delete animation; m_animations[new_animation->getName()] = new_animation;
updateActiveAnimations(new_animation);
}
void KRAnimationManager::updateActiveAnimations(KRAnimation* animation)
{
m_animationsToUpdate.insert(animation);
}
void KRAnimationManager::deleteAnimation(KRAnimation* animation, bool delete_curves)
{
if (delete_curves) {
animation->deleteCurves();
}
m_animations.erase(animation->getName());
delete animation;
} }

View File

@@ -41,28 +41,29 @@
class KRAnimationManager : public KRResourceManager { class KRAnimationManager : public KRResourceManager
{
public: public:
KRAnimationManager(KRContext &context); KRAnimationManager(KRContext& context);
virtual ~KRAnimationManager(); virtual ~KRAnimationManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
KRAnimation* loadAnimation(const char* szName, KRDataBlock* data);
KRAnimation* getAnimation(const char* szName);
void addAnimation(KRAnimation* new_animation);
unordered_map<std::string, KRAnimation*>& getAnimations();
void deleteAnimation(KRAnimation* animation, bool delete_curves);
void startFrame(float deltaTime);
void endFrame(float deltaTime);
void updateActiveAnimations(KRAnimation* animation);
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
KRAnimation *loadAnimation(const char *szName, KRDataBlock *data);
KRAnimation *getAnimation(const char *szName);
void addAnimation(KRAnimation *new_animation);
unordered_map<std::string, KRAnimation *> &getAnimations();
void deleteAnimation(KRAnimation *animation, bool delete_curves);
void startFrame(float deltaTime);
void endFrame(float deltaTime);
void updateActiveAnimations(KRAnimation *animation);
private: private:
unordered_map<std::string, KRAnimation *> m_animations; unordered_map<std::string, KRAnimation*> m_animations;
set<KRAnimation *> m_activeAnimations; set<KRAnimation*> m_activeAnimations;
set<KRAnimation *> m_animationsToUpdate; set<KRAnimation*> m_animationsToUpdate;
}; };

View File

@@ -33,47 +33,47 @@
#include "KRAudioManager.h" #include "KRAudioManager.h"
KRAudioBuffer::KRAudioBuffer(KRAudioManager *manager, KRAudioSample *sound, int index, int frameCount, int frameRate, int bytesPerFrame, void (*fn_populate)(KRAudioSample *, int, void *)) KRAudioBuffer::KRAudioBuffer(KRAudioManager* manager, KRAudioSample* sound, int index, int frameCount, int frameRate, int bytesPerFrame, void (*fn_populate)(KRAudioSample*, int, void*))
{ {
m_pSoundManager = manager; m_pSoundManager = manager;
m_frameCount = frameCount; m_frameCount = frameCount;
m_frameRate = frameRate; m_frameRate = frameRate;
m_bytesPerFrame = bytesPerFrame; m_bytesPerFrame = bytesPerFrame;
m_pData = NULL; m_pData = NULL;
m_audioSample = sound; m_audioSample = sound;
m_index = index; m_index = index;
m_pSoundManager->makeCurrentContext(); m_pSoundManager->makeCurrentContext();
m_pData = m_pSoundManager->getBufferData(m_frameCount * m_bytesPerFrame); m_pData = m_pSoundManager->getBufferData(m_frameCount * m_bytesPerFrame);
fn_populate(sound, index, m_pData->getStart()); fn_populate(sound, index, m_pData->getStart());
} }
KRAudioBuffer::~KRAudioBuffer() KRAudioBuffer::~KRAudioBuffer()
{ {
m_pSoundManager->recycleBufferData(m_pData); m_pSoundManager->recycleBufferData(m_pData);
} }
KRAudioSample *KRAudioBuffer::getAudioSample() KRAudioSample* KRAudioBuffer::getAudioSample()
{ {
return m_audioSample; return m_audioSample;
} }
int KRAudioBuffer::getFrameCount() int KRAudioBuffer::getFrameCount()
{ {
return m_frameCount; return m_frameCount;
} }
int KRAudioBuffer::getFrameRate() int KRAudioBuffer::getFrameRate()
{ {
return m_frameRate; return m_frameRate;
} }
signed short *KRAudioBuffer::getFrameData() signed short* KRAudioBuffer::getFrameData()
{ {
return (signed short *)m_pData->getStart(); return (signed short*)m_pData->getStart();
} }
int KRAudioBuffer::getIndex() int KRAudioBuffer::getIndex()
{ {
return m_index; return m_index;
} }

View File

@@ -40,23 +40,23 @@ class KRAudioSample;
class KRAudioBuffer class KRAudioBuffer
{ {
public: public:
KRAudioBuffer(KRAudioManager *manager, KRAudioSample *sound, int index, int frameCount, int frameRate, int bytesPerFrame, void (*fn_populate)(KRAudioSample *, int, void *)); KRAudioBuffer(KRAudioManager* manager, KRAudioSample* sound, int index, int frameCount, int frameRate, int bytesPerFrame, void (*fn_populate)(KRAudioSample*, int, void*));
~KRAudioBuffer(); ~KRAudioBuffer();
int getFrameCount(); int getFrameCount();
int getFrameRate(); int getFrameRate();
signed short *getFrameData(); signed short* getFrameData();
KRAudioSample *getAudioSample(); KRAudioSample* getAudioSample();
int getIndex(); int getIndex();
private: private:
KRAudioManager *m_pSoundManager; KRAudioManager* m_pSoundManager;
int m_index; int m_index;
int m_frameCount; int m_frameCount;
int m_frameRate; int m_frameRate;
int m_bytesPerFrame; int m_bytesPerFrame;
KRDataBlock *m_pData; KRDataBlock* m_pData;
KRAudioSample *m_audioSample; KRAudioSample* m_audioSample;
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -59,9 +59,9 @@ const int KRENGINE_AUDIO_BLOCK_LOG2N = 7; // 2 ^ KRENGINE_AUDIO_BLOCK_LOG2N =
// 7 is 128 .. NOTE: the hrtf code uses magic numbers everywhere and is hardcoded to 128 samples per frame // 7 is 128 .. NOTE: the hrtf code uses magic numbers everywhere and is hardcoded to 128 samples per frame
const int KRENGINE_AUDIO_BLOCK_LENGTH = 1 << KRENGINE_AUDIO_BLOCK_LOG2N; const int KRENGINE_AUDIO_BLOCK_LENGTH = 1 << KRENGINE_AUDIO_BLOCK_LOG2N;
// Length of one block to process. Determines the latency of the audio system and sets size for FFT's used in HRTF convolution // Length of one block to process. Determines the latency of the audio system and sets size for FFT's used in HRTF convolution
// the AUGraph works in 1024 sample chunks. At 128 we are making 8 consecutive calls to the renderBlock method for each // the AUGraph works in 1024 sample chunks. At 128 we are making 8 consecutive calls to the renderBlock method for each
// render initiated by the AUGraph. // render initiated by the AUGraph.
const int KRENGINE_REVERB_MAX_FFT_LOG2 = 15; const int KRENGINE_REVERB_MAX_FFT_LOG2 = 15;
const int KRENGINE_REVERB_WORKSPACE_SIZE = 1 << KRENGINE_REVERB_MAX_FFT_LOG2; const int KRENGINE_REVERB_WORKSPACE_SIZE = 1 << KRENGINE_REVERB_MAX_FFT_LOG2;
@@ -79,177 +79,180 @@ const int KRENGINE_AUDIO_ANTICLICK_SAMPLES = 64;
class KRAmbientZone; class KRAmbientZone;
class KRReverbZone; class KRReverbZone;
typedef struct { typedef struct
float weight; {
KRAmbientZone *ambient_zone; float weight;
KRAudioSample *ambient_sample; KRAmbientZone* ambient_zone;
KRAudioSample* ambient_sample;
} siren_ambient_zone_weight_info; } siren_ambient_zone_weight_info;
typedef struct { typedef struct
float weight; {
KRReverbZone *reverb_zone; float weight;
KRAudioSample *reverb_sample; KRReverbZone* reverb_zone;
KRAudioSample* reverb_sample;
} siren_reverb_zone_weight_info; } siren_reverb_zone_weight_info;
class KRAudioManager : public KRResourceManager { class KRAudioManager : public KRResourceManager
{
public: public:
KRAudioManager(KRContext &context); KRAudioManager(KRContext& context);
virtual ~KRAudioManager(); virtual ~KRAudioManager();
void destroy(); void destroy();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override; virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override; virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
unordered_map<std::string, KRAudioSample *> &getSounds();
void add(KRAudioSample *Sound);
KRAudioSample *load(const std::string &name, const std::string &extension, KRDataBlock *data);
KRAudioSample *get(const std::string &name);
// Listener position and orientation
KRScene *getListenerScene();
void setListenerScene(KRScene *scene);
void setListenerOrientation(const Vector3 &position, const Vector3 &forward, const Vector3 &up);
void setListenerOrientationFromModelMatrix(const Matrix4 &modelMatrix);
Vector3 &getListenerForward();
Vector3 &getListenerPosition();
Vector3 &getListenerUp();
// Global audio gain / attenuation
float getGlobalGain();
void setGlobalGain(float gain);
float getGlobalReverbSendLevel();
void setGlobalReverbSendLevel(float send_level);
float getGlobalAmbientGain();
void setGlobalAmbientGain(float gain);
unordered_map<std::string, KRAudioSample*>& getSounds();
void makeCurrentContext(); void add(KRAudioSample* Sound);
KRDataBlock *getBufferData(int size); KRAudioSample* load(const std::string& name, const std::string& extension, KRDataBlock* data);
void recycleBufferData(KRDataBlock *data); KRAudioSample* get(const std::string& name);
void activateAudioSource(KRAudioSource *audioSource); // Listener position and orientation
void deactivateAudioSource(KRAudioSource *audioSource); KRScene* getListenerScene();
void setListenerScene(KRScene* scene);
__int64_t getAudioFrame(); void setListenerOrientation(const Vector3& position, const Vector3& forward, const Vector3& up);
void setListenerOrientationFromModelMatrix(const Matrix4& modelMatrix);
KRAudioBuffer *getBuffer(KRAudioSample &audio_sample, int buffer_index); Vector3& getListenerForward();
Vector3& getListenerPosition();
static void mute(bool onNotOff); Vector3& getListenerUp();
void goToSleep();
// Global audio gain / attenuation
float getGlobalGain();
void setGlobalGain(float gain);
float getGlobalReverbSendLevel();
void setGlobalReverbSendLevel(float send_level);
float getGlobalAmbientGain();
void setGlobalAmbientGain(float gain);
void makeCurrentContext();
KRDataBlock* getBufferData(int size);
void recycleBufferData(KRDataBlock* data);
void activateAudioSource(KRAudioSource* audioSource);
void deactivateAudioSource(KRAudioSource* audioSource);
__int64_t getAudioFrame();
KRAudioBuffer* getBuffer(KRAudioSample& audio_sample, int buffer_index);
static void mute(bool onNotOff);
void goToSleep();
void startFrame(float deltaTime);
bool getEnableAudio();
void setEnableAudio(bool enable);
bool getEnableHRTF();
void setEnableHRTF(bool enable);
bool getEnableReverb();
void setEnableReverb(bool enable);
float getReverbMaxLength();
void setReverbMaxLength(float max_length);
void _registerOpenAudioSample(KRAudioSample* audioSample);
void _registerCloseAudioSample(KRAudioSample* audioSample);
void startFrame(float deltaTime);
bool getEnableAudio();
void setEnableAudio(bool enable);
bool getEnableHRTF();
void setEnableHRTF(bool enable);
bool getEnableReverb();
void setEnableReverb(bool enable);
float getReverbMaxLength();
void setReverbMaxLength(float max_length);
void _registerOpenAudioSample(KRAudioSample *audioSample);
void _registerCloseAudioSample(KRAudioSample *audioSample);
private: private:
bool m_enable_audio; bool m_enable_audio;
bool m_enable_hrtf; bool m_enable_hrtf;
bool m_enable_reverb; bool m_enable_reverb;
float m_reverb_max_length; float m_reverb_max_length;
KRScene *m_listener_scene; // For now, only one scene is allowed to have active audio at once KRScene* m_listener_scene; // For now, only one scene is allowed to have active audio at once
float m_global_reverb_send_level; float m_global_reverb_send_level;
float m_global_ambient_gain; float m_global_ambient_gain;
float m_global_gain; float m_global_gain;
Vector3 m_listener_position; Vector3 m_listener_position;
Vector3 m_listener_forward; Vector3 m_listener_forward;
Vector3 m_listener_up; Vector3 m_listener_up;
unordered_map<std::string, KRAudioSample *> m_sounds; unordered_map<std::string, KRAudioSample*> m_sounds;
std::vector<KRDataBlock *> m_bufferPoolIdle; std::vector<KRDataBlock*> m_bufferPoolIdle;
std::vector<KRAudioBuffer *> m_bufferCache; std::vector<KRAudioBuffer*> m_bufferCache;
std::set<KRAudioSource *> m_activeAudioSources; std::set<KRAudioSource*> m_activeAudioSources;
std::set<KRAudioSample *> m_openAudioSamples; std::set<KRAudioSample*> m_openAudioSamples;
void initAudio(); void initAudio();
void initHRTF(); void initHRTF();
void cleanupAudio(); void cleanupAudio();
bool m_initialized; bool m_initialized;
#ifdef __APPLE__ #ifdef __APPLE__
// Apple Core Audio // Apple Core Audio
AUGraph m_auGraph; AUGraph m_auGraph;
AudioUnit m_auMixer; AudioUnit m_auMixer;
static OSStatus renderInput(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); static OSStatus renderInput(void* inRefCon, AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData);
void renderAudio(UInt32 inNumberFrames, AudioBufferList *ioData); void renderAudio(UInt32 inNumberFrames, AudioBufferList* ioData);
#endif #endif
KRDSP::FFTWorkspace m_fft_setup[KRENGINE_REVERB_MAX_FFT_LOG2 - KRENGINE_AUDIO_BLOCK_LOG2N + 1]; KRDSP::FFTWorkspace m_fft_setup[KRENGINE_REVERB_MAX_FFT_LOG2 - KRENGINE_AUDIO_BLOCK_LOG2N + 1];
__int64_t m_audio_frame; // Number of audio frames processed since the start of the application __int64_t m_audio_frame; // Number of audio frames processed since the start of the application
float *m_reverb_input_samples; // Circular-buffered reverb input, single channel float* m_reverb_input_samples; // Circular-buffered reverb input, single channel
int m_reverb_input_next_sample; // Pointer to next sample in reverb buffer int m_reverb_input_next_sample; // Pointer to next sample in reverb buffer
int m_reverb_sequence; int m_reverb_sequence;
KRAudioSample *m_reverb_impulse_responses[KRENGINE_MAX_REVERB_IMPULSE_MIX]; KRAudioSample* m_reverb_impulse_responses[KRENGINE_MAX_REVERB_IMPULSE_MIX];
float m_reverb_impulse_responses_weight[KRENGINE_MAX_REVERB_IMPULSE_MIX]; float m_reverb_impulse_responses_weight[KRENGINE_MAX_REVERB_IMPULSE_MIX];
float *m_output_accumulation; // Interleaved output accumulation buffer float* m_output_accumulation; // Interleaved output accumulation buffer
int m_output_accumulation_block_start; int m_output_accumulation_block_start;
int m_output_sample; int m_output_sample;
float *m_workspace_data; float* m_workspace_data;
KRDSP::SplitComplex m_workspace[3]; KRDSP::SplitComplex m_workspace[3];
float *getBlockAddress(int block_offset); float* getBlockAddress(int block_offset);
void renderBlock(); void renderBlock();
void renderReverb(); void renderReverb();
void renderAmbient(); void renderAmbient();
void renderHRTF(); void renderHRTF();
void renderITD(); void renderITD();
void renderReverbImpulseResponse(int impulse_response_offset, int frame_count_log2); void renderReverbImpulseResponse(int impulse_response_offset, int frame_count_log2);
void renderLimiter(); void renderLimiter();
std::vector<Vector2> m_hrtf_sample_locations; std::vector<Vector2> m_hrtf_sample_locations;
float *m_hrtf_data; float* m_hrtf_data;
unordered_map<Vector2, KRDSP::SplitComplex> m_hrtf_spectral[2]; unordered_map<Vector2, KRDSP::SplitComplex> m_hrtf_spectral[2];
Vector2 getNearestHRTFSample(const Vector2 &dir); Vector2 getNearestHRTFSample(const Vector2& dir);
void getHRTFMix(const Vector2 &dir, Vector2 &hrtf1, Vector2 &hrtf2, Vector2 &hrtf3, Vector2 &hrtf4, float &mix1, float &mix2, float &mix3, float &mix4); void getHRTFMix(const Vector2& dir, Vector2& hrtf1, Vector2& hrtf2, Vector2& hrtf3, Vector2& hrtf4, float& mix1, float& mix2, float& mix3, float& mix4);
KRAudioSample *getHRTFSample(const Vector2 &hrtf_dir); KRAudioSample* getHRTFSample(const Vector2& hrtf_dir);
KRDSP::SplitComplex getHRTFSpectral(const Vector2 &hrtf_dir, const int channel); KRDSP::SplitComplex getHRTFSpectral(const Vector2& hrtf_dir, const int channel);
unordered_map<std::string, siren_ambient_zone_weight_info> m_ambient_zone_weights; unordered_map<std::string, siren_ambient_zone_weight_info> m_ambient_zone_weights;
float m_ambient_zone_total_weight = 0.0f; // For normalizing zone weights float m_ambient_zone_total_weight = 0.0f; // For normalizing zone weights
unordered_map<std::string, siren_reverb_zone_weight_info> m_reverb_zone_weights; unordered_map<std::string, siren_reverb_zone_weight_info> m_reverb_zone_weights;
float m_reverb_zone_total_weight = 0.0f; // For normalizing zone weights float m_reverb_zone_total_weight = 0.0f; // For normalizing zone weights
std::mutex m_mutex; std::mutex m_mutex;
#ifdef __APPLE__ #ifdef __APPLE__
mach_timebase_info_data_t m_timebase_info; mach_timebase_info_data_t m_timebase_info;
#endif #endif
unordered_multimap<Vector2, std::pair<KRAudioSource *, std::pair<float, float> > > m_mapped_sources, m_prev_mapped_sources; unordered_multimap<Vector2, std::pair<KRAudioSource*, std::pair<float, float> > > m_mapped_sources, m_prev_mapped_sources;
bool m_anticlick_block; bool m_anticlick_block;
bool m_high_quality_hrtf; // If true, 4 HRTF samples will be interpolated; if false, the nearest HRTF sample will be used without interpolation bool m_high_quality_hrtf; // If true, 4 HRTF samples will be interpolated; if false, the nearest HRTF sample will be used without interpolation
}; };

View File

@@ -36,263 +36,263 @@
#include "KRContext.h" #include "KRContext.h"
#include "KRDSP.h" #include "KRDSP.h"
KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string extension) : KRResource(context, name) KRAudioSample::KRAudioSample(KRContext& context, std::string name, std::string extension) : KRResource(context, name)
{ {
m_pData = new KRDataBlock(); m_pData = new KRDataBlock();
m_extension = extension; m_extension = extension;
#ifdef __APPLE__ #ifdef __APPLE__
// Apple Audio Toolbox // Apple Audio Toolbox
m_audio_file_id = 0; m_audio_file_id = 0;
m_fileRef = NULL; m_fileRef = NULL;
#endif #endif
m_totalFrames = 0; m_totalFrames = 0;
m_bytesPerFrame = 0; m_bytesPerFrame = 0;
m_frameRate = 0; m_frameRate = 0;
m_bufferCount = 0; m_bufferCount = 0;
m_last_frame_used = 0; m_last_frame_used = 0;
} }
KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string extension, KRDataBlock *data) : KRResource(context, name) KRAudioSample::KRAudioSample(KRContext& context, std::string name, std::string extension, KRDataBlock* data) : KRResource(context, name)
{ {
m_pData = data; m_pData = data;
m_extension = extension; m_extension = extension;
#ifdef __APPLE__ #ifdef __APPLE__
// Apple Audio Toolbox // Apple Audio Toolbox
m_audio_file_id = 0; m_audio_file_id = 0;
m_fileRef = NULL; m_fileRef = NULL;
#endif #endif
m_totalFrames = 0; m_totalFrames = 0;
m_bytesPerFrame = 0; m_bytesPerFrame = 0;
m_frameRate = 0; m_frameRate = 0;
m_bufferCount = 0; m_bufferCount = 0;
m_last_frame_used = 0; m_last_frame_used = 0;
} }
KRAudioSample::~KRAudioSample() KRAudioSample::~KRAudioSample()
{ {
closeFile(); closeFile();
delete m_pData; delete m_pData;
} }
int KRAudioSample::getChannelCount() int KRAudioSample::getChannelCount()
{ {
loadInfo(); loadInfo();
return m_channelsPerFrame; return m_channelsPerFrame;
} }
__int64_t KRAudioSample::getFrameCount() __int64_t KRAudioSample::getFrameCount()
{ {
loadInfo(); loadInfo();
//return (int)((__int64_t)m_totalFrames * (__int64_t)frame_rate / (__int64_t)m_frameRate); //return (int)((__int64_t)m_totalFrames * (__int64_t)frame_rate / (__int64_t)m_frameRate);
return m_totalFrames; return m_totalFrames;
} }
float KRAudioSample::sample(int frame_offset, int frame_rate, int channel) float KRAudioSample::sample(int frame_offset, int frame_rate, int channel)
{ {
loadInfo(); loadInfo();
int c = KRMIN(channel, m_channelsPerFrame - 1);
if(frame_offset < 0) { int c = KRMIN(channel, m_channelsPerFrame - 1);
return 0.0f; // Past the beginning of the recording
if (frame_offset < 0) {
return 0.0f; // Past the beginning of the recording
} else {
int sample_frame;
if (m_frameRate == frame_rate) {
// No resampling required
sample_frame = frame_offset;
} else { } else {
int sample_frame; // Need to resample from m_frameRate to frame_rate
if(m_frameRate == frame_rate) { sample_frame = (int)((__int64_t)frame_offset * (__int64_t)m_frameRate / (__int64_t)frame_rate);
// No resampling required
sample_frame = frame_offset;
} else {
// Need to resample from m_frameRate to frame_rate
sample_frame = (int)((__int64_t)frame_offset * (__int64_t)m_frameRate / (__int64_t)frame_rate);
}
int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame;
int buffer_index = sample_frame / maxFramesPerBuffer;
if(buffer_index >= m_bufferCount) {
return 0.0f; // Past the end of the recording
} else {
__int64_t buffer_offset = frame_offset - buffer_index * maxFramesPerBuffer;
KRAudioBuffer *buffer = getContext().getAudioManager()->getBuffer(*this, buffer_index);
if(buffer == NULL) {
return 0.0f;
} else if(buffer_offset >= buffer->getFrameCount()) {
return 0.0f; // past the end of the recording
} else {
short *frame = buffer->getFrameData() + (buffer_offset * m_channelsPerFrame);
return frame[c] / 32767.0f;
}
}
} }
int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame;
int buffer_index = sample_frame / maxFramesPerBuffer;
if (buffer_index >= m_bufferCount) {
return 0.0f; // Past the end of the recording
} else {
__int64_t buffer_offset = frame_offset - buffer_index * maxFramesPerBuffer;
KRAudioBuffer* buffer = getContext().getAudioManager()->getBuffer(*this, buffer_index);
if (buffer == NULL) {
return 0.0f;
} else if (buffer_offset >= buffer->getFrameCount()) {
return 0.0f; // past the end of the recording
} else {
short* frame = buffer->getFrameData() + (buffer_offset * m_channelsPerFrame);
return frame[c] / 32767.0f;
}
}
}
} }
void KRAudioSample::sample(__int64_t frame_offset, int frame_count, int channel, float *buffer, float amplitude, bool loop) void KRAudioSample::sample(__int64_t frame_offset, int frame_count, int channel, float* buffer, float amplitude, bool loop)
{ {
loadInfo(); loadInfo();
m_last_frame_used = (int)getContext().getAudioManager()->getAudioFrame(); m_last_frame_used = (int)getContext().getAudioManager()->getAudioFrame();
if(loop) { if (loop) {
int buffer_offset = 0; int buffer_offset = 0;
int frames_left = frame_count; int frames_left = frame_count;
int sample_length = (int)getFrameCount(); int sample_length = (int)getFrameCount();
while(frames_left) { while (frames_left) {
int next_frame = (int)(((__int64_t)frame_offset + (__int64_t)buffer_offset) % sample_length); int next_frame = (int)(((__int64_t)frame_offset + (__int64_t)buffer_offset) % sample_length);
if(next_frame + frames_left >= sample_length) { if (next_frame + frames_left >= sample_length) {
int frames_processed = sample_length - next_frame; int frames_processed = sample_length - next_frame;
sample(next_frame, frames_processed, channel, buffer + buffer_offset, amplitude, false); sample(next_frame, frames_processed, channel, buffer + buffer_offset, amplitude, false);
frames_left -= frames_processed; frames_left -= frames_processed;
buffer_offset += frames_processed; buffer_offset += frames_processed;
} else { } else {
sample(next_frame, frames_left, channel, buffer + buffer_offset, amplitude, false); sample(next_frame, frames_left, channel, buffer + buffer_offset, amplitude, false);
frames_left = 0; frames_left = 0;
} }
}
} else {
int c = KRMIN(channel, m_channelsPerFrame - 1);
if(frame_offset + frame_count <= 0) {
// Range is entirely before the sample
memset(buffer, 0, frame_count * sizeof(float));
} else if(frame_offset >= m_totalFrames) {
// Range is entirely after the sample
memset(buffer, 0, frame_count * sizeof(float));
} else {
int start_frame = (int)(frame_offset < 0 ? 0 : frame_offset);
int prefix_frames = (int)(frame_offset < 0 ? -frame_offset : 0);
if(prefix_frames > 0) {
// Prefix with padding of 0's
memset(buffer, 0, prefix_frames * sizeof(float));
}
int frames_per_buffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame;
int buffer_index = start_frame / frames_per_buffer;
int buffer_offset = start_frame % frames_per_buffer;
int processed_frames = prefix_frames;
while(processed_frames < frame_count) {
int frames_left = frame_count - processed_frames;
if(buffer_index >= m_bufferCount) {
// Suffix with padding of 0's
memset(buffer + processed_frames, 0, frames_left * sizeof(float));
processed_frames += frames_left;
} else {
KRAudioBuffer *source_buffer = getContext().getAudioManager()->getBuffer(*this, buffer_index);
int frames_to_copy = source_buffer->getFrameCount() - buffer_offset;
if(frames_to_copy > frames_left) frames_to_copy = frames_left;
if(frames_to_copy > 0) {
signed short *source_data = source_buffer->getFrameData() + buffer_offset * m_channelsPerFrame + c;
KRDSP::Int16ToFloat(source_data, m_channelsPerFrame, buffer + processed_frames, 1, frames_to_copy);
//memcpy(buffer + processed_frames, source_buffer->getFrameData() + buffer_offset, frames_to_copy * m_channelsPerFrame * sizeof(float));
processed_frames += frames_to_copy;
}
buffer_index++;
buffer_offset = 0;
}
}
}
float scale = amplitude / 32768.0f;
KRDSP::Scale(buffer, scale, frame_count);
} }
} else {
int c = KRMIN(channel, m_channelsPerFrame - 1);
if (frame_offset + frame_count <= 0) {
// Range is entirely before the sample
memset(buffer, 0, frame_count * sizeof(float));
} else if (frame_offset >= m_totalFrames) {
// Range is entirely after the sample
memset(buffer, 0, frame_count * sizeof(float));
} else {
int start_frame = (int)(frame_offset < 0 ? 0 : frame_offset);
int prefix_frames = (int)(frame_offset < 0 ? -frame_offset : 0);
if (prefix_frames > 0) {
// Prefix with padding of 0's
memset(buffer, 0, prefix_frames * sizeof(float));
}
int frames_per_buffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame;
int buffer_index = start_frame / frames_per_buffer;
int buffer_offset = start_frame % frames_per_buffer;
int processed_frames = prefix_frames;
while (processed_frames < frame_count) {
int frames_left = frame_count - processed_frames;
if (buffer_index >= m_bufferCount) {
// Suffix with padding of 0's
memset(buffer + processed_frames, 0, frames_left * sizeof(float));
processed_frames += frames_left;
} else {
KRAudioBuffer* source_buffer = getContext().getAudioManager()->getBuffer(*this, buffer_index);
int frames_to_copy = source_buffer->getFrameCount() - buffer_offset;
if (frames_to_copy > frames_left) frames_to_copy = frames_left;
if (frames_to_copy > 0) {
signed short* source_data = source_buffer->getFrameData() + buffer_offset * m_channelsPerFrame + c;
KRDSP::Int16ToFloat(source_data, m_channelsPerFrame, buffer + processed_frames, 1, frames_to_copy);
//memcpy(buffer + processed_frames, source_buffer->getFrameData() + buffer_offset, frames_to_copy * m_channelsPerFrame * sizeof(float));
processed_frames += frames_to_copy;
}
buffer_index++;
buffer_offset = 0;
}
}
}
float scale = amplitude / 32768.0f;
KRDSP::Scale(buffer, scale, frame_count);
}
} }
#ifdef __APPLE__ #ifdef __APPLE__
// Apple Audio Toolbox // Apple Audio Toolbox
OSStatus KRAudioSample::ReadProc( // AudioFile_ReadProc OSStatus KRAudioSample::ReadProc( // AudioFile_ReadProc
void * inClientData, void* inClientData,
SInt64 inPosition, SInt64 inPosition,
UInt32 requestCount, UInt32 requestCount,
void * buffer, void* buffer,
UInt32 * actualCount) UInt32* actualCount)
{ {
KRAudioSample *sound = (KRAudioSample *)inClientData; KRAudioSample* sound = (KRAudioSample*)inClientData;
UInt32 max_count = sound->m_pData->getSize() - inPosition; UInt32 max_count = sound->m_pData->getSize() - inPosition;
*actualCount = requestCount < max_count ? requestCount : max_count; *actualCount = requestCount < max_count ? requestCount : max_count;
sound->m_pData->copy(buffer, inPosition, *actualCount); sound->m_pData->copy(buffer, inPosition, *actualCount);
return noErr; return noErr;
} }
SInt64 KRAudioSample::GetSizeProc( // AudioFile_GetSizeProc SInt64 KRAudioSample::GetSizeProc( // AudioFile_GetSizeProc
void * inClientData) void* inClientData)
{ {
KRAudioSample *sound = (KRAudioSample *)inClientData; KRAudioSample* sound = (KRAudioSample*)inClientData;
return sound->m_pData->getSize(); return sound->m_pData->getSize();
} }
OSStatus KRAudioSample::SetSizeProc( // AudioFile_SetSizeProc OSStatus KRAudioSample::SetSizeProc( // AudioFile_SetSizeProc
void * inClientData, void* inClientData,
SInt64 inSize) SInt64 inSize)
{ {
return -1; // Writing not supported return -1; // Writing not supported
} }
OSStatus KRAudioSample::WriteProc( // AudioFile_WriteProc OSStatus KRAudioSample::WriteProc( // AudioFile_WriteProc
void * inClientData, void* inClientData,
SInt64 inPosition, SInt64 inPosition,
UInt32 requestCount, UInt32 requestCount,
const void *buffer, const void* buffer,
UInt32 * actualCount) UInt32* actualCount)
{ {
return -1; // Writing not supported return -1; // Writing not supported
} }
#endif // Apple Audio Toolbox #endif // Apple Audio Toolbox
void KRAudioSample::openFile() void KRAudioSample::openFile()
{ {
#ifdef __APPLE__ #ifdef __APPLE__
// Apple Audio Toolbox // Apple Audio Toolbox
// AudioFileInitializeWithCallbacks // AudioFileInitializeWithCallbacks
if(m_fileRef == NULL) { if (m_fileRef == NULL) {
// printf("Call to KRAudioSample::openFile() with extension: %s\n", m_extension.c_str());
// The m_extension is valid (it's either wav or mp3 for the files in Circa project)
// so we can key off the extension and use a different data handler for mp3 files if we want to
//
// Temp variables // printf("Call to KRAudioSample::openFile() with extension: %s\n", m_extension.c_str());
UInt32 propertySize; // The m_extension is valid (it's either wav or mp3 for the files in Circa project)
// so we can key off the extension and use a different data handler for mp3 files if we want to
// ---- Open audio file ---- //
assert(AudioFileOpenWithCallbacks((void *)this, ReadProc, WriteProc, GetSizeProc, SetSizeProc, 0, &m_audio_file_id) == noErr);
assert(ExtAudioFileWrapAudioFileID(m_audio_file_id, false, &m_fileRef) == noErr); // Temp variables
UInt32 propertySize;
// ---- Get file format information ----
AudioStreamBasicDescription inputFormat; // ---- Open audio file ----
propertySize = sizeof(inputFormat); assert(AudioFileOpenWithCallbacks((void*)this, ReadProc, WriteProc, GetSizeProc, SetSizeProc, 0, &m_audio_file_id) == noErr);
ExtAudioFileGetProperty(m_fileRef, kExtAudioFileProperty_FileDataFormat, &propertySize, &inputFormat); assert(ExtAudioFileWrapAudioFileID(m_audio_file_id, false, &m_fileRef) == noErr);
// ---- Set up output format ---- // ---- Get file format information ----
AudioStreamBasicDescription outputFormat; AudioStreamBasicDescription inputFormat;
// Set the client format to 16 bit signed integer (native-endian) data propertySize = sizeof(inputFormat);
// Maintain the channel count and sample rate of the original source format ExtAudioFileGetProperty(m_fileRef, kExtAudioFileProperty_FileDataFormat, &propertySize, &inputFormat);
outputFormat.mSampleRate = inputFormat.mSampleRate;
outputFormat.mChannelsPerFrame = inputFormat.mChannelsPerFrame; // ---- Set up output format ----
outputFormat.mFormatID = kAudioFormatLinearPCM; AudioStreamBasicDescription outputFormat;
outputFormat.mBytesPerPacket = 2 * outputFormat.mChannelsPerFrame; // Set the client format to 16 bit signed integer (native-endian) data
outputFormat.mFramesPerPacket = 1; // Maintain the channel count and sample rate of the original source format
outputFormat.mBytesPerFrame = 2 * outputFormat.mChannelsPerFrame; outputFormat.mSampleRate = inputFormat.mSampleRate;
outputFormat.mBitsPerChannel = 16; outputFormat.mChannelsPerFrame = inputFormat.mChannelsPerFrame;
outputFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger; outputFormat.mFormatID = kAudioFormatLinearPCM;
ExtAudioFileSetProperty(m_fileRef, kExtAudioFileProperty_ClientDataFormat, sizeof(outputFormat), &outputFormat); outputFormat.mBytesPerPacket = 2 * outputFormat.mChannelsPerFrame;
outputFormat.mFramesPerPacket = 1;
// ---- Get the buffer size and format parameters ---- outputFormat.mBytesPerFrame = 2 * outputFormat.mChannelsPerFrame;
propertySize = sizeof(m_totalFrames); outputFormat.mBitsPerChannel = 16;
ExtAudioFileGetProperty(m_fileRef, kExtAudioFileProperty_FileLengthFrames, &propertySize, &m_totalFrames); outputFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
ExtAudioFileSetProperty(m_fileRef, kExtAudioFileProperty_ClientDataFormat, sizeof(outputFormat), &outputFormat);
m_bytesPerFrame = outputFormat.mBytesPerFrame;
m_frameRate = outputFormat.mSampleRate; // ---- Get the buffer size and format parameters ----
propertySize = sizeof(m_totalFrames);
int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame; ExtAudioFileGetProperty(m_fileRef, kExtAudioFileProperty_FileLengthFrames, &propertySize, &m_totalFrames);
m_bufferCount = (m_totalFrames+maxFramesPerBuffer-1)/maxFramesPerBuffer; // CEIL(_totalFrames / maxFramesPerBuffer)
m_bytesPerFrame = outputFormat.mBytesPerFrame;
m_channelsPerFrame = outputFormat.mChannelsPerFrame; m_frameRate = outputFormat.mSampleRate;
getContext().getAudioManager()->_registerOpenAudioSample(this); int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame;
} m_bufferCount = (m_totalFrames + maxFramesPerBuffer - 1) / maxFramesPerBuffer; // CEIL(_totalFrames / maxFramesPerBuffer)
m_channelsPerFrame = outputFormat.mChannelsPerFrame;
getContext().getAudioManager()->_registerOpenAudioSample(this);
}
#else #else
#pragma message ( "TODO - implement for Windows" ) #pragma message ( "TODO - implement for Windows" )
#endif #endif
@@ -302,92 +302,92 @@ void KRAudioSample::closeFile()
{ {
#ifdef __APPLE__ #ifdef __APPLE__
// Apple Audio Toolbox // Apple Audio Toolbox
if(m_fileRef) { if (m_fileRef) {
ExtAudioFileDispose(m_fileRef); ExtAudioFileDispose(m_fileRef);
m_fileRef = NULL; m_fileRef = NULL;
} }
if(m_audio_file_id) { if (m_audio_file_id) {
AudioFileClose(m_audio_file_id); AudioFileClose(m_audio_file_id);
m_audio_file_id = 0; m_audio_file_id = 0;
} }
#endif #endif
getContext().getAudioManager()->_registerCloseAudioSample(this); getContext().getAudioManager()->_registerCloseAudioSample(this);
} }
void KRAudioSample::loadInfo() void KRAudioSample::loadInfo()
{ {
if(m_frameRate == 0) { if (m_frameRate == 0) {
openFile(); openFile();
closeFile(); closeFile();
} }
} }
std::string KRAudioSample::getExtension() std::string KRAudioSample::getExtension()
{ {
return m_extension; return m_extension;
} }
bool KRAudioSample::save(KRDataBlock &data) bool KRAudioSample::save(KRDataBlock& data)
{ {
data.append(*m_pData); data.append(*m_pData);
return true; return true;
} }
float KRAudioSample::getDuration() float KRAudioSample::getDuration()
{ {
loadInfo(); loadInfo();
return (float)m_totalFrames / (float)m_frameRate; return (float)m_totalFrames / (float)m_frameRate;
} }
int KRAudioSample::getBufferCount() int KRAudioSample::getBufferCount()
{ {
loadInfo(); loadInfo();
return m_bufferCount; return m_bufferCount;
} }
void KRAudioSample::PopulateBuffer(KRAudioSample *sound, int index, void *data) void KRAudioSample::PopulateBuffer(KRAudioSample* sound, int index, void* data)
{ {
int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / sound->m_bytesPerFrame; int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / sound->m_bytesPerFrame;
int startFrame = index * maxFramesPerBuffer; int startFrame = index * maxFramesPerBuffer;
__uint32_t frameCount = (__uint32_t)KRMIN(sound->m_totalFrames - startFrame, maxFramesPerBuffer); __uint32_t frameCount = (__uint32_t)KRMIN(sound->m_totalFrames - startFrame, maxFramesPerBuffer);
#ifdef __APPLE__ #ifdef __APPLE__
// Apple Audio Toolbox // Apple Audio Toolbox
AudioBufferList outputBufferInfo; AudioBufferList outputBufferInfo;
outputBufferInfo.mNumberBuffers = 1; outputBufferInfo.mNumberBuffers = 1;
outputBufferInfo.mBuffers[0].mDataByteSize = frameCount * sound->m_bytesPerFrame; outputBufferInfo.mBuffers[0].mDataByteSize = frameCount * sound->m_bytesPerFrame;
outputBufferInfo.mBuffers[0].mNumberChannels = sound->m_channelsPerFrame; outputBufferInfo.mBuffers[0].mNumberChannels = sound->m_channelsPerFrame;
outputBufferInfo.mBuffers[0].mData = data; outputBufferInfo.mBuffers[0].mData = data;
// Read the data into an AudioBufferList // Read the data into an AudioBufferList
ExtAudioFileSeek(sound->m_fileRef, startFrame); ExtAudioFileSeek(sound->m_fileRef, startFrame);
ExtAudioFileRead(sound->m_fileRef, (UInt32*)&frameCount, &outputBufferInfo); ExtAudioFileRead(sound->m_fileRef, (UInt32*)&frameCount, &outputBufferInfo);
#endif #endif
} }
KRAudioBuffer *KRAudioSample::getBuffer(int index) KRAudioBuffer* KRAudioSample::getBuffer(int index)
{ {
openFile(); openFile();
int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame; int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame;
int startFrame = index * maxFramesPerBuffer; int startFrame = index * maxFramesPerBuffer;
__uint32_t frameCount = (__uint32_t)KRMIN(m_totalFrames - startFrame, maxFramesPerBuffer); __uint32_t frameCount = (__uint32_t)KRMIN(m_totalFrames - startFrame, maxFramesPerBuffer);
KRAudioBuffer *buffer = new KRAudioBuffer(getContext().getAudioManager(), this, index, frameCount, m_frameRate, m_bytesPerFrame, PopulateBuffer); KRAudioBuffer* buffer = new KRAudioBuffer(getContext().getAudioManager(), this, index, frameCount, m_frameRate, m_bytesPerFrame, PopulateBuffer);
if(m_bufferCount == 1) { if (m_bufferCount == 1) {
// [self closeFile]; // We don't need to hold on to a file handle if not streaming // [self closeFile]; // We don't need to hold on to a file handle if not streaming
} }
return buffer; return buffer;
} }
void KRAudioSample::_endFrame() void KRAudioSample::_endFrame()
{ {
const __int64_t AUDIO_SAMPLE_EXPIRY_FRAMES = 500; const __int64_t AUDIO_SAMPLE_EXPIRY_FRAMES = 500;
__int64_t current_frame = getContext().getAudioManager()->getAudioFrame(); __int64_t current_frame = getContext().getAudioManager()->getAudioFrame();
if(current_frame > m_last_frame_used + AUDIO_SAMPLE_EXPIRY_FRAMES) { if (current_frame > m_last_frame_used + AUDIO_SAMPLE_EXPIRY_FRAMES) {
closeFile(); closeFile();
} }
} }

View File

@@ -38,73 +38,74 @@
class KRAudioBuffer; class KRAudioBuffer;
class KRAudioSample : public KRResource { class KRAudioSample : public KRResource
{
public: public:
KRAudioSample(KRContext &context, std::string name, std::string extension); KRAudioSample(KRContext& context, std::string name, std::string extension);
KRAudioSample(KRContext &context, std::string name, std::string extension, KRDataBlock *data); KRAudioSample(KRContext& context, std::string name, std::string extension, KRDataBlock* data);
virtual ~KRAudioSample(); virtual ~KRAudioSample();
virtual std::string getExtension(); virtual std::string getExtension();
virtual bool save(KRDataBlock &data); virtual bool save(KRDataBlock& data);
float getDuration(); float getDuration();
KRAudioBuffer *getBuffer(int index); KRAudioBuffer* getBuffer(int index);
int getBufferCount(); int getBufferCount();
// Siren audio engine interface // Siren audio engine interface
int getChannelCount(); int getChannelCount();
__int64_t getFrameCount(); __int64_t getFrameCount();
float sample(int frame_offset, int frame_rate, int channel); float sample(int frame_offset, int frame_rate, int channel);
void sample(__int64_t frame_offset, int frame_count, int channel, float *buffer, float amplitude, bool loop); void sample(__int64_t frame_offset, int frame_count, int channel, float* buffer, float amplitude, bool loop);
void _endFrame(); void _endFrame();
private: private:
__int64_t m_last_frame_used; __int64_t m_last_frame_used;
std::string m_extension; std::string m_extension;
KRDataBlock *m_pData; KRDataBlock* m_pData;
#ifdef __APPLE__ #ifdef __APPLE__
// Apple Audio Toolbox // Apple Audio Toolbox
AudioFileID m_audio_file_id; AudioFileID m_audio_file_id;
ExtAudioFileRef m_fileRef; ExtAudioFileRef m_fileRef;
static OSStatus ReadProc( // AudioFile_ReadProc static OSStatus ReadProc( // AudioFile_ReadProc
void * inClientData, void* inClientData,
SInt64 inPosition, SInt64 inPosition,
UInt32 requestCount, UInt32 requestCount,
void * buffer, void* buffer,
UInt32 * actualCount); UInt32* actualCount);
static OSStatus WriteProc( // AudioFile_WriteProc static OSStatus WriteProc( // AudioFile_WriteProc
void * inClientData, void* inClientData,
SInt64 inPosition, SInt64 inPosition,
UInt32 requestCount, UInt32 requestCount,
const void *buffer, const void* buffer,
UInt32 * actualCount); UInt32* actualCount);
static SInt64 GetSizeProc( // AudioFile_GetSizeProc static SInt64 GetSizeProc( // AudioFile_GetSizeProc
void * inClientData); void* inClientData);
static OSStatus SetSizeProc( // AudioFile_SetSizeProc static OSStatus SetSizeProc( // AudioFile_SetSizeProc
void * inClientData, void* inClientData,
SInt64 inSize); SInt64 inSize);
#endif #endif
int m_bufferCount;
__int64_t m_totalFrames;
int m_frameRate;
int m_bytesPerFrame;
int m_channelsPerFrame;
void openFile();
void closeFile();
void loadInfo();
static void PopulateBuffer(KRAudioSample *sound, int index, void *data); int m_bufferCount;
__int64_t m_totalFrames;
int m_frameRate;
int m_bytesPerFrame;
int m_channelsPerFrame;
void openFile();
void closeFile();
void loadInfo();
static void PopulateBuffer(KRAudioSample* sound, int index, void* data);
}; };

View File

@@ -51,409 +51,410 @@ void KRAudioSource::InitNodeInfo(KrNodeInfo* nodeInfo)
nodeInfo->audio_source.sample = -1; nodeInfo->audio_source.sample = -1;
} }
KRAudioSource::KRAudioSource(KRScene &scene, std::string name) : KRNode(scene, name) KRAudioSource::KRAudioSource(KRScene& scene, std::string name) : KRNode(scene, name)
{ {
m_currentBufferFrame = 0; m_currentBufferFrame = 0;
m_playing = false; m_playing = false;
m_is3d = true; m_is3d = true;
m_isPrimed = false; m_isPrimed = false;
m_audioFile = NULL; m_audioFile = NULL;
m_gain = 1.0f; m_gain = 1.0f;
m_pitch = 1.0f; m_pitch = 1.0f;
m_looping = false; m_looping = false;
m_referenceDistance = 1.0f; m_referenceDistance = 1.0f;
m_reverb = 0.0f; m_reverb = 0.0f;
m_rolloffFactor = 2.0f; m_rolloffFactor = 2.0f;
m_enable_occlusion = true; m_enable_occlusion = true;
m_enable_obstruction = true; m_enable_obstruction = true;
m_start_audio_frame = -1; m_start_audio_frame = -1;
m_paused_audio_frame = 0; m_paused_audio_frame = 0;
} }
KRAudioSource::~KRAudioSource() KRAudioSource::~KRAudioSource()
{ {
while(m_audioBuffers.size()) { while (m_audioBuffers.size()) {
delete m_audioBuffers.front(); delete m_audioBuffers.front();
m_audioBuffers.pop(); m_audioBuffers.pop();
} }
} }
std::string KRAudioSource::getElementName() { std::string KRAudioSource::getElementName()
return "audio_source";
}
tinyxml2::XMLElement *KRAudioSource::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); return "audio_source";
e->SetAttribute("sample", m_audio_sample_name.c_str());
e->SetAttribute("gain", m_gain);
e->SetAttribute("pitch", m_pitch);
e->SetAttribute("looping", m_looping ? "true" : "false");
e->SetAttribute("is3d", m_is3d ? "true" : "false");
e->SetAttribute("reference_distance", m_referenceDistance);
e->SetAttribute("reverb", m_reverb);
e->SetAttribute("rolloff_factor", m_rolloffFactor);
e->SetAttribute("enable_occlusion", m_enable_occlusion ? "true" : "false");
e->SetAttribute("enable_obstruction", m_enable_obstruction ? "true" : "false");
return e;
} }
void KRAudioSource::loadXML(tinyxml2::XMLElement *e) tinyxml2::XMLElement* KRAudioSource::saveXML(tinyxml2::XMLNode* parent)
{ {
m_audio_sample_name = e->Attribute("sample"); tinyxml2::XMLElement* e = KRNode::saveXML(parent);
e->SetAttribute("sample", m_audio_sample_name.c_str());
float gain = 1.0f; e->SetAttribute("gain", m_gain);
if(e->QueryFloatAttribute("gain", &gain) != tinyxml2::XML_SUCCESS) { e->SetAttribute("pitch", m_pitch);
gain = 1.0f; e->SetAttribute("looping", m_looping ? "true" : "false");
} e->SetAttribute("is3d", m_is3d ? "true" : "false");
setGain(gain); e->SetAttribute("reference_distance", m_referenceDistance);
e->SetAttribute("reverb", m_reverb);
float pitch = 1.0f; e->SetAttribute("rolloff_factor", m_rolloffFactor);
if(e->QueryFloatAttribute("pitch", &pitch) != tinyxml2::XML_SUCCESS) { e->SetAttribute("enable_occlusion", m_enable_occlusion ? "true" : "false");
pitch = 1.0f; e->SetAttribute("enable_obstruction", m_enable_obstruction ? "true" : "false");
} return e;
setPitch(m_pitch); }
bool looping = false; void KRAudioSource::loadXML(tinyxml2::XMLElement* e)
if(e->QueryBoolAttribute("looping", &looping) != tinyxml2::XML_SUCCESS) { {
looping = false; m_audio_sample_name = e->Attribute("sample");
}
setLooping(looping); float gain = 1.0f;
if (e->QueryFloatAttribute("gain", &gain) != tinyxml2::XML_SUCCESS) {
bool is3d = true; gain = 1.0f;
if(e->QueryBoolAttribute("is3d", &is3d) != tinyxml2::XML_SUCCESS) { }
is3d = true; setGain(gain);
}
setIs3D(is3d); float pitch = 1.0f;
if (e->QueryFloatAttribute("pitch", &pitch) != tinyxml2::XML_SUCCESS) {
float reference_distance = 1.0f; pitch = 1.0f;
if(e->QueryFloatAttribute("reference_distance", &reference_distance) != tinyxml2::XML_SUCCESS) { }
reference_distance = 1.0f; setPitch(m_pitch);
}
setReferenceDistance(reference_distance); bool looping = false;
if (e->QueryBoolAttribute("looping", &looping) != tinyxml2::XML_SUCCESS) {
float reverb = 0.0f; looping = false;
if(e->QueryFloatAttribute("reverb", &reverb) != tinyxml2::XML_SUCCESS) { }
reverb = 0.0f; setLooping(looping);
}
setReverb(reverb); bool is3d = true;
if (e->QueryBoolAttribute("is3d", &is3d) != tinyxml2::XML_SUCCESS) {
float rolloff_factor = 2.0f; is3d = true;
if(e->QueryFloatAttribute("rolloff_factor", &rolloff_factor) != tinyxml2::XML_SUCCESS) { }
rolloff_factor = 2.0f; setIs3D(is3d);
}
setRolloffFactor(rolloff_factor); float reference_distance = 1.0f;
if (e->QueryFloatAttribute("reference_distance", &reference_distance) != tinyxml2::XML_SUCCESS) {
reference_distance = 1.0f;
}
setReferenceDistance(reference_distance);
float reverb = 0.0f;
if (e->QueryFloatAttribute("reverb", &reverb) != tinyxml2::XML_SUCCESS) {
reverb = 0.0f;
}
setReverb(reverb);
float rolloff_factor = 2.0f;
if (e->QueryFloatAttribute("rolloff_factor", &rolloff_factor) != tinyxml2::XML_SUCCESS) {
rolloff_factor = 2.0f;
}
setRolloffFactor(rolloff_factor);
m_enable_obstruction = true;
if (e->QueryBoolAttribute("enable_obstruction", &m_enable_obstruction) != tinyxml2::XML_SUCCESS) {
m_enable_obstruction = true; m_enable_obstruction = true;
if(e->QueryBoolAttribute("enable_obstruction", &m_enable_obstruction) != tinyxml2::XML_SUCCESS) { }
m_enable_obstruction = true;
}
m_enable_occlusion = true;
if (e->QueryBoolAttribute("enable_occlusion", &m_enable_occlusion) != tinyxml2::XML_SUCCESS) {
m_enable_occlusion = true; m_enable_occlusion = true;
if(e->QueryBoolAttribute("enable_occlusion", &m_enable_occlusion) != tinyxml2::XML_SUCCESS) { }
m_enable_occlusion = true;
} KRNode::loadXML(e);
KRNode::loadXML(e);
} }
void KRAudioSource::prime() void KRAudioSource::prime()
{ {
if(!m_isPrimed) { if (!m_isPrimed) {
if(m_audioFile == NULL && m_audio_sample_name.size() != 0) { if (m_audioFile == NULL && m_audio_sample_name.size() != 0) {
m_audioFile = getContext().getAudioManager()->get(m_audio_sample_name); m_audioFile = getContext().getAudioManager()->get(m_audio_sample_name);
}
if(m_audioFile) {
// Prime the buffer queue
m_nextBufferIndex = 0;
for(int i=0; i < KRENGINE_AUDIO_BUFFERS_PER_SOURCE; i++) {
queueBuffer();
}
m_isPrimed = true;
}
} }
if (m_audioFile) {
// Prime the buffer queue
m_nextBufferIndex = 0;
for (int i = 0; i < KRENGINE_AUDIO_BUFFERS_PER_SOURCE; i++) {
queueBuffer();
}
m_isPrimed = true;
}
}
} }
void KRAudioSource::queueBuffer() void KRAudioSource::queueBuffer()
{ {
KRAudioBuffer *buffer = m_audioFile->getBuffer(m_nextBufferIndex); KRAudioBuffer* buffer = m_audioFile->getBuffer(m_nextBufferIndex);
m_audioBuffers.push(buffer); m_audioBuffers.push(buffer);
m_nextBufferIndex = (m_nextBufferIndex + 1) % m_audioFile->getBufferCount(); m_nextBufferIndex = (m_nextBufferIndex + 1) % m_audioFile->getBufferCount();
} }
void KRAudioSource::render(RenderInfo& ri) void KRAudioSource::render(RenderInfo& ri)
{ {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(ri);
bool bVisualize = false;
if(ri.renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
KRMesh* sphereModel = getContext().getMeshManager()->getMaxLODModel("__sphere");
if (sphereModel) {
Matrix4 sphereModelMatrix = getModelMatrix();
PipelineInfo info{}; if (m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
std::string shader_name("visualize_overlay");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &ri.point_lights;
info.directional_lights = &ri.directional_lights;
info.spot_lights = &ri.spot_lights;
info.renderPass = ri.renderPass;
info.rasterMode = RasterMode::kAdditive;
info.modelFormat = sphereModel->getModelFormat();
info.vertexAttributes = sphereModel->getVertexAttributes();
KRPipeline* pShader = getContext().getPipelineManager()->getPipeline(*ri.surface, info); KRNode::render(ri);
pShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, sphereModelMatrix, &ri.point_lights, &ri.directional_lights, &ri.spot_lights, ri.renderPass);
sphereModel->renderNoMaterials(ri.commandBuffer, ri.renderPass, getName(), "visualize_overlay", 1.0f); bool bVisualize = false;
} // sphereModels.size()
} if (ri.renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
KRMesh* sphereModel = getContext().getMeshManager()->getMaxLODModel("__sphere");
if (sphereModel) {
Matrix4 sphereModelMatrix = getModelMatrix();
PipelineInfo info{};
std::string shader_name("visualize_overlay");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &ri.point_lights;
info.directional_lights = &ri.directional_lights;
info.spot_lights = &ri.spot_lights;
info.renderPass = ri.renderPass;
info.rasterMode = RasterMode::kAdditive;
info.modelFormat = sphereModel->getModelFormat();
info.vertexAttributes = sphereModel->getVertexAttributes();
KRPipeline* pShader = getContext().getPipelineManager()->getPipeline(*ri.surface, info);
pShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, sphereModelMatrix, &ri.point_lights, &ri.directional_lights, &ri.spot_lights, ri.renderPass);
sphereModel->renderNoMaterials(ri.commandBuffer, ri.renderPass, getName(), "visualize_overlay", 1.0f);
} // sphereModels.size()
}
} }
void KRAudioSource::setGain(float gain) void KRAudioSource::setGain(float gain)
{ {
m_gain = gain; m_gain = gain;
} }
float KRAudioSource::getGain() float KRAudioSource::getGain()
{ {
return m_gain; return m_gain;
} }
void KRAudioSource::setPitch(float pitch) void KRAudioSource::setPitch(float pitch)
{ {
m_pitch = pitch; m_pitch = pitch;
} }
float KRAudioSource::getReferenceDistance() float KRAudioSource::getReferenceDistance()
{ {
return m_referenceDistance; return m_referenceDistance;
} }
void KRAudioSource::setReferenceDistance(float reference_distance) void KRAudioSource::setReferenceDistance(float reference_distance)
{ {
m_referenceDistance = reference_distance; m_referenceDistance = reference_distance;
} }
float KRAudioSource::getReverb() float KRAudioSource::getReverb()
{ {
return m_reverb; return m_reverb;
} }
void KRAudioSource::setReverb(float reverb) void KRAudioSource::setReverb(float reverb)
{ {
m_reverb = reverb; m_reverb = reverb;
} }
float KRAudioSource::getRolloffFactor() float KRAudioSource::getRolloffFactor()
{ {
return m_rolloffFactor; return m_rolloffFactor;
} }
void KRAudioSource::setRolloffFactor(float rolloff_factor) void KRAudioSource::setRolloffFactor(float rolloff_factor)
{ {
m_rolloffFactor = rolloff_factor; m_rolloffFactor = rolloff_factor;
} }
void KRAudioSource::setLooping(bool looping) void KRAudioSource::setLooping(bool looping)
{ {
// Enable or disable looping playback; Audio source must be stopped and re-started for loop mode changes to take effect // Enable or disable looping playback; Audio source must be stopped and re-started for loop mode changes to take effect
m_looping = looping; m_looping = looping;
} }
bool KRAudioSource::getLooping() bool KRAudioSource::getLooping()
{ {
// Returns true if the playback will automatically loop // Returns true if the playback will automatically loop
return m_looping; return m_looping;
} }
bool KRAudioSource::getEnableOcclusion() bool KRAudioSource::getEnableOcclusion()
{ {
return m_enable_occlusion; return m_enable_occlusion;
} }
void KRAudioSource::setEnableOcclusion(bool enable_occlusion) void KRAudioSource::setEnableOcclusion(bool enable_occlusion)
{ {
m_enable_occlusion = enable_occlusion; m_enable_occlusion = enable_occlusion;
} }
bool KRAudioSource::getEnableObstruction() bool KRAudioSource::getEnableObstruction()
{ {
return m_enable_obstruction; return m_enable_obstruction;
} }
void KRAudioSource::setEnableObstruction(bool enable_obstruction) void KRAudioSource::setEnableObstruction(bool enable_obstruction)
{ {
m_enable_obstruction = enable_obstruction; m_enable_obstruction = enable_obstruction;
} }
bool KRAudioSource::getIs3D() bool KRAudioSource::getIs3D()
{ {
return m_is3d; return m_is3d;
} }
void KRAudioSource::setIs3D(bool is3D) void KRAudioSource::setIs3D(bool is3D)
{ {
// Audio source must be stopped and re-started for mode change to take effect // Audio source must be stopped and re-started for mode change to take effect
m_is3d = is3D; m_is3d = is3D;
} }
void KRAudioSource::advanceBuffer() void KRAudioSource::advanceBuffer()
{ {
if(m_audioBuffers.size()) { if (m_audioBuffers.size()) {
delete m_audioBuffers.front(); delete m_audioBuffers.front();
m_audioBuffers.pop(); m_audioBuffers.pop();
} }
queueBuffer(); queueBuffer();
} }
void KRAudioSource::physicsUpdate(float deltaTime) void KRAudioSource::physicsUpdate(float deltaTime)
{ {
KRNode::physicsUpdate(deltaTime); KRNode::physicsUpdate(deltaTime);
KRAudioManager *audioManager = getContext().getAudioManager(); KRAudioManager* audioManager = getContext().getAudioManager();
audioManager->activateAudioSource(this); audioManager->activateAudioSource(this);
} }
void KRAudioSource::play() void KRAudioSource::play()
{ {
// Start playback of audio at the current audio sample position. If audio is already playing, this has no effect. // Start playback of audio at the current audio sample position. If audio is already playing, this has no effect.
// play() does not automatically seek to the beginning of the sample. Call setAudioFrame( 0 ) first if you wish the playback to begin at the start of the audio sample. // play() does not automatically seek to the beginning of the sample. Call setAudioFrame( 0 ) first if you wish the playback to begin at the start of the audio sample.
// If not set to looping, audio playback ends automatically at the end of the sample // If not set to looping, audio playback ends automatically at the end of the sample
if(!m_playing) { if (!m_playing) {
KRAudioManager *audioManager = getContext().getAudioManager(); KRAudioManager* audioManager = getContext().getAudioManager();
assert(m_start_audio_frame == -1); assert(m_start_audio_frame == -1);
m_start_audio_frame = audioManager->getAudioFrame() - m_paused_audio_frame; m_start_audio_frame = audioManager->getAudioFrame() - m_paused_audio_frame;
m_paused_audio_frame = -1; m_paused_audio_frame = -1;
audioManager->activateAudioSource(this); audioManager->activateAudioSource(this);
} }
m_playing = true; m_playing = true;
} }
void KRAudioSource::stop() void KRAudioSource::stop()
{ {
// Stop playback of audio. If audio is already stopped, this has no effect. // Stop playback of audio. If audio is already stopped, this has no effect.
// If play() is called afterwards, playback will continue at the current audio sample position. // If play() is called afterwards, playback will continue at the current audio sample position.
if(m_playing) { if (m_playing) {
m_paused_audio_frame = getAudioFrame(); m_paused_audio_frame = getAudioFrame();
m_start_audio_frame = -1; m_start_audio_frame = -1;
m_playing = false; m_playing = false;
getContext().getAudioManager()->deactivateAudioSource(this); getContext().getAudioManager()->deactivateAudioSource(this);
} }
} }
bool KRAudioSource::isPlaying() bool KRAudioSource::isPlaying()
{ {
// Returns true if audio is playing. Will return false if a non-looped playback has reached the end of the audio sample. // Returns true if audio is playing. Will return false if a non-looped playback has reached the end of the audio sample.
return m_playing; return m_playing;
} }
void KRAudioSource::setSample(const std::string &sound_name) void KRAudioSource::setSample(const std::string& sound_name)
{ {
m_audio_sample_name = sound_name; m_audio_sample_name = sound_name;
} }
std::string KRAudioSource::getSample() std::string KRAudioSource::getSample()
{ {
return m_audio_sample_name; return m_audio_sample_name;
} }
KRAudioSample *KRAudioSource::getAudioSample() KRAudioSample* KRAudioSource::getAudioSample()
{ {
if(m_audioFile == NULL && m_audio_sample_name.size() != 0) { if (m_audioFile == NULL && m_audio_sample_name.size() != 0) {
m_audioFile = getContext().getAudioManager()->get(m_audio_sample_name); m_audioFile = getContext().getAudioManager()->get(m_audio_sample_name);
} }
return m_audioFile; return m_audioFile;
} }
void KRAudioSource::advanceFrames(int frame_count) void KRAudioSource::advanceFrames(int frame_count)
{ {
m_currentBufferFrame += frame_count; m_currentBufferFrame += frame_count;
KRAudioBuffer *buffer = getBuffer(); KRAudioBuffer* buffer = getBuffer();
while(buffer != NULL && m_currentBufferFrame >= buffer->getFrameCount()) { while (buffer != NULL && m_currentBufferFrame >= buffer->getFrameCount()) {
m_currentBufferFrame -= buffer->getFrameCount(); m_currentBufferFrame -= buffer->getFrameCount();
advanceBuffer(); advanceBuffer();
buffer = getBuffer(); buffer = getBuffer();
} }
if(buffer == NULL) { if (buffer == NULL) {
m_currentBufferFrame = 0; m_currentBufferFrame = 0;
stop(); stop();
} }
} }
KRAudioBuffer *KRAudioSource::getBuffer() KRAudioBuffer* KRAudioSource::getBuffer()
{ {
if(m_playing) { if (m_playing) {
prime(); prime();
return m_audioBuffers.front(); return m_audioBuffers.front();
} else { } else {
return NULL; return NULL;
} }
} }
int KRAudioSource::getBufferFrame() int KRAudioSource::getBufferFrame()
{ {
return m_currentBufferFrame; return m_currentBufferFrame;
} }
__int64_t KRAudioSource::getAudioFrame() __int64_t KRAudioSource::getAudioFrame()
{ {
// Returns the audio playback position in units of integer audio frames. // Returns the audio playback position in units of integer audio frames.
if(m_playing) { if (m_playing) {
return getContext().getAudioManager()->getAudioFrame() - m_start_audio_frame; return getContext().getAudioManager()->getAudioFrame() - m_start_audio_frame;
} else { } else {
return m_paused_audio_frame; return m_paused_audio_frame;
} }
} }
void KRAudioSource::setAudioFrame(__int64_t next_frame) void KRAudioSource::setAudioFrame(__int64_t next_frame)
{ {
// Sets the audio playback position with units of integer audio frames. // Sets the audio playback position with units of integer audio frames.
if(m_playing) { if (m_playing) {
m_start_audio_frame = getContext().getAudioManager()->getAudioFrame() - next_frame; m_start_audio_frame = getContext().getAudioManager()->getAudioFrame() - next_frame;
} else { } else {
m_paused_audio_frame = next_frame; m_paused_audio_frame = next_frame;
} }
} }
float KRAudioSource::getAudioTime() float KRAudioSource::getAudioTime()
{ {
// Gets the audio playback position with units of floating point seconds. // Gets the audio playback position with units of floating point seconds.
return getAudioFrame() / 44100.0f; return getAudioFrame() / 44100.0f;
} }
void KRAudioSource::setAudioTime(float new_position) void KRAudioSource::setAudioTime(float new_position)
{ {
// Sets the audio playback position with units of floating point seconds. // Sets the audio playback position with units of floating point seconds.
setAudioFrame((__int64_t)(new_position * 44100.0f)); setAudioFrame((__int64_t)(new_position * 44100.0f));
} }
void KRAudioSource::sample(int frame_count, int channel, float *buffer, float gain) void KRAudioSource::sample(int frame_count, int channel, float* buffer, float gain)
{ {
KRAudioSample *source_sample = getAudioSample(); KRAudioSample* source_sample = getAudioSample();
if(source_sample && m_playing) { if (source_sample && m_playing) {
__int64_t next_frame = getAudioFrame(); __int64_t next_frame = getAudioFrame();
source_sample->sample(next_frame, frame_count, channel, buffer, gain, m_looping); source_sample->sample(next_frame, frame_count, channel, buffer, gain, m_looping);
if(!m_looping && next_frame > source_sample->getFrameCount()) { if (!m_looping && next_frame > source_sample->getFrameCount()) {
stop(); stop();
}
} else {
memset(buffer, 0, sizeof(float) * frame_count);
} }
} else {
memset(buffer, 0, sizeof(float) * frame_count);
}
} }

View File

@@ -39,119 +39,120 @@
class KRAudioSample; class KRAudioSample;
class KRAudioBuffer; class KRAudioBuffer;
class KRAudioSource : public KRNode { class KRAudioSource : public KRNode
{
public: public:
static void InitNodeInfo(KrNodeInfo* nodeInfo); static void InitNodeInfo(KrNodeInfo* nodeInfo);
KRAudioSource(KRScene &scene, std::string name); KRAudioSource(KRScene& scene, std::string name);
virtual ~KRAudioSource(); virtual ~KRAudioSource();
virtual std::string getElementName(); virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
virtual void loadXML(tinyxml2::XMLElement *e); virtual void loadXML(tinyxml2::XMLElement* e);
virtual void physicsUpdate(float deltaTime); virtual void physicsUpdate(float deltaTime);
void render(RenderInfo& ri);
// ---- Audio Playback Controls ---- void render(RenderInfo& ri);
// Start playback of audio at the current audio sample position. If audio is already playing, this has no effect. // ---- Audio Playback Controls ----
// play() does not automatically seek to the beginning of the sample. Call setAudioFrame( 0 ) first if you wish the playback to begin at the start of the audio sample.
// If not set to looping, audio playback ends automatically at the end of the sample // Start playback of audio at the current audio sample position. If audio is already playing, this has no effect.
void play(); // play() does not automatically seek to the beginning of the sample. Call setAudioFrame( 0 ) first if you wish the playback to begin at the start of the audio sample.
// If not set to looping, audio playback ends automatically at the end of the sample
// Stop playback of audio. If audio is already stopped, this has no effect. void play();
// If play() is called afterwards, playback will continue at the current audio sample position.
void stop(); // Stop playback of audio. If audio is already stopped, this has no effect.
// If play() is called afterwards, playback will continue at the current audio sample position.
// Returns true if audio is playing. Will return false if a non-looped playback has reached the end of the audio sample. void stop();
bool isPlaying();
// Returns true if audio is playing. Will return false if a non-looped playback has reached the end of the audio sample.
// Returns the audio playback position in units of integer audio frames. bool isPlaying();
__int64_t getAudioFrame();
// Returns the audio playback position in units of integer audio frames.
// Sets the audio playback position with units of integer audio frames. __int64_t getAudioFrame();
void setAudioFrame(__int64_t next_frame);
// Sets the audio playback position with units of integer audio frames.
// Gets the audio playback position with units of floating point seconds. void setAudioFrame(__int64_t next_frame);
float getAudioTime();
// Gets the audio playback position with units of floating point seconds.
// Sets the audio playback position with units of floating point seconds. float getAudioTime();
void setAudioTime(float new_position);
// Sets the audio playback position with units of floating point seconds.
// Returns true if the playback will automatically loop void setAudioTime(float new_position);
bool getLooping();
// Returns true if the playback will automatically loop
// Enable or disable looping playback; Audio source must be stopped and re-started for loop mode changes to take effect bool getLooping();
void setLooping(bool looping);
// Enable or disable looping playback; Audio source must be stopped and re-started for loop mode changes to take effect
// ---- End: Audio Playback Controls ---- void setLooping(bool looping);
void setSample(const std::string &sound_name); // ---- End: Audio Playback Controls ----
std::string getSample();
void setSample(const std::string& sound_name);
KRAudioSample *getAudioSample(); std::string getSample();
float getGain(); KRAudioSample* getAudioSample();
void setGain(float gain);
float getGain();
float getPitch(); void setGain(float gain);
void setPitch(float pitch);
float getPitch();
void setPitch(float pitch);
bool getIs3D();
void setIs3D(bool is3D);
// 3d only properties:
float getReverb();
void setReverb(float reverb);
float getReferenceDistance();
void setReferenceDistance(float reference_distance);
float getRolloffFactor();
void setRolloffFactor(float rolloff_factor);
bool getEnableOcclusion();
void setEnableOcclusion(bool enable_occlusion);
bool getEnableObstruction();
void setEnableObstruction(bool enable_obstruction);
// ---- Siren Audio Engine Interface ----
void advanceFrames(int frame_count);
KRAudioBuffer* getBuffer();
int getBufferFrame();
void sample(int frame_count, int channel, float* buffer, float gain);
bool getIs3D();
void setIs3D(bool is3D);
// 3d only properties:
float getReverb();
void setReverb(float reverb);
float getReferenceDistance();
void setReferenceDistance(float reference_distance);
float getRolloffFactor();
void setRolloffFactor(float rolloff_factor);
bool getEnableOcclusion();
void setEnableOcclusion(bool enable_occlusion);
bool getEnableObstruction();
void setEnableObstruction(bool enable_obstruction);
// ---- Siren Audio Engine Interface ----
void advanceFrames(int frame_count);
KRAudioBuffer *getBuffer();
int getBufferFrame();
void sample(int frame_count, int channel, float *buffer, float gain);
private: private:
__int64_t m_start_audio_frame; // Global audio frame that matches the start of the audio sample playback; when paused or not playing, this contains a value of -1 __int64_t m_start_audio_frame; // Global audio frame that matches the start of the audio sample playback; when paused or not playing, this contains a value of -1
__int64_t m_paused_audio_frame; // When paused or not playing, this contains the local audio frame number. When playing, this contains a value of -1 __int64_t m_paused_audio_frame; // When paused or not playing, this contains the local audio frame number. When playing, this contains a value of -1
int m_currentBufferFrame; // Siren Audio Engine frame number within current buffer int m_currentBufferFrame; // Siren Audio Engine frame number within current buffer
void advanceBuffer(); void advanceBuffer();
std::string m_audio_sample_name; std::string m_audio_sample_name;
KRAudioSample *m_audioFile; KRAudioSample* m_audioFile;
unsigned int m_sourceID; unsigned int m_sourceID;
float m_gain; float m_gain;
float m_pitch; float m_pitch;
bool m_looping; bool m_looping;
std::queue<KRAudioBuffer *> m_audioBuffers; std::queue<KRAudioBuffer*> m_audioBuffers;
int m_nextBufferIndex; int m_nextBufferIndex;
bool m_playing; bool m_playing;
bool m_is3d; bool m_is3d;
bool m_isPrimed; bool m_isPrimed;
void prime(); void prime();
void queueBuffer(); void queueBuffer();
// 3d only properties: // 3d only properties:
float m_referenceDistance; float m_referenceDistance;
float m_reverb; // type ALfloat 0.0 (dry) - 1.0 (wet) (0-100% dry/wet mix, 0.0 default) float m_reverb; // type ALfloat 0.0 (dry) - 1.0 (wet) (0-100% dry/wet mix, 0.0 default)
float m_rolloffFactor; float m_rolloffFactor;
bool m_enable_occlusion; bool m_enable_occlusion;
bool m_enable_obstruction; bool m_enable_obstruction;
}; };

View File

@@ -36,54 +36,54 @@ KRBehaviorFactoryFunctionMap m_factoryFunctions;
KRBehavior::KRBehavior() KRBehavior::KRBehavior()
{ {
__node = NULL; __node = NULL;
} }
KRBehavior::~KRBehavior() KRBehavior::~KRBehavior()
{ {
} }
void KRBehavior::init() void KRBehavior::init()
{ {
// Note: Subclasses are not expected to call this method // Note: Subclasses are not expected to call this method
} }
KRNode *KRBehavior::getNode() const KRNode* KRBehavior::getNode() const
{ {
return __node; return __node;
} }
void KRBehavior::__setNode(KRNode *node) void KRBehavior::__setNode(KRNode* node)
{ {
__node = node; __node = node;
} }
KRBehavior *KRBehavior::LoadXML(KRNode *node, tinyxml2::XMLElement *e) KRBehavior* KRBehavior::LoadXML(KRNode* node, tinyxml2::XMLElement* e)
{ {
std::map<std::string, std::string> attributes; std::map<std::string, std::string> attributes;
for(const tinyxml2::XMLAttribute *attribute = e->FirstAttribute(); attribute != NULL; attribute = attribute->Next()) { for (const tinyxml2::XMLAttribute* attribute = e->FirstAttribute(); attribute != NULL; attribute = attribute->Next()) {
attributes[attribute->Name()] = attribute->Value(); attributes[attribute->Name()] = attribute->Value();
} }
const char *szElementName = e->Attribute("type"); const char* szElementName = e->Attribute("type");
if(szElementName == NULL) { if (szElementName == NULL) {
return NULL; return NULL;
} }
KRBehaviorFactoryFunctionMap::const_iterator itr = m_factoryFunctions.find(szElementName); KRBehaviorFactoryFunctionMap::const_iterator itr = m_factoryFunctions.find(szElementName);
if(itr == m_factoryFunctions.end()) { if (itr == m_factoryFunctions.end()) {
return NULL; return NULL;
} }
return (*itr->second)(attributes); return (*itr->second)(attributes);
} }
void KRBehavior::RegisterFactoryCTOR(std::string behaviorName, KRBehaviorFactoryFunction fnFactory) void KRBehavior::RegisterFactoryCTOR(std::string behaviorName, KRBehaviorFactoryFunction fnFactory)
{ {
m_factoryFunctions[behaviorName] = fnFactory; m_factoryFunctions[behaviorName] = fnFactory;
} }
void KRBehavior::UnregisterFactoryCTOR(std::string behaviorName) void KRBehavior::UnregisterFactoryCTOR(std::string behaviorName)
{ {
m_factoryFunctions.erase(behaviorName); m_factoryFunctions.erase(behaviorName);
} }

View File

@@ -46,25 +46,25 @@ namespace tinyxml2 {
class XMLElement; class XMLElement;
} // namespace tinyxml2 } // namespace tinyxml2
typedef KRBehavior *(*KRBehaviorFactoryFunction)(std::map<std::string, std::string> attributes); typedef KRBehavior* (*KRBehaviorFactoryFunction)(std::map<std::string, std::string> attributes);
typedef std::map<std::string, KRBehaviorFactoryFunction> KRBehaviorFactoryFunctionMap; typedef std::map<std::string, KRBehaviorFactoryFunction> KRBehaviorFactoryFunctionMap;
class KRBehavior class KRBehavior
{ {
public: public:
static void RegisterFactoryCTOR(std::string behaviorName, KRBehaviorFactoryFunction fnFactory); static void RegisterFactoryCTOR(std::string behaviorName, KRBehaviorFactoryFunction fnFactory);
static void UnregisterFactoryCTOR(std::string behaviorName); static void UnregisterFactoryCTOR(std::string behaviorName);
KRBehavior(); KRBehavior();
virtual ~KRBehavior(); virtual ~KRBehavior();
KRNode *getNode() const; KRNode* getNode() const;
virtual void init(); virtual void init();
virtual void update(float deltaTime) = 0; virtual void update(float deltaTime) = 0;
virtual void visibleUpdate(float deltatime) = 0; virtual void visibleUpdate(float deltatime) = 0;
void __setNode(KRNode *node); void __setNode(KRNode* node);
static KRBehavior *LoadXML(KRNode *node, tinyxml2::XMLElement *e); static KRBehavior* LoadXML(KRNode* node, tinyxml2::XMLElement* e);
private: private:
KRNode *__node; KRNode* __node;
}; };

View File

@@ -39,75 +39,76 @@ void KRBone::InitNodeInfo(KrNodeInfo* nodeInfo)
// No additional members // No additional members
} }
KRBone::KRBone(KRScene &scene, std::string name) : KRNode(scene, name) KRBone::KRBone(KRScene& scene, std::string name) : KRNode(scene, name)
{ {
setScaleCompensation(true); setScaleCompensation(true);
} }
KRBone::~KRBone() KRBone::~KRBone()
{}
std::string KRBone::getElementName()
{ {
return "bone";
} }
std::string KRBone::getElementName() { tinyxml2::XMLElement* KRBone::saveXML(tinyxml2::XMLNode* parent)
return "bone";
}
tinyxml2::XMLElement *KRBone::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement* e = KRNode::saveXML(parent);
return e; return e;
} }
void KRBone::loadXML(tinyxml2::XMLElement *e) void KRBone::loadXML(tinyxml2::XMLElement* e)
{ {
KRNode::loadXML(e); KRNode::loadXML(e);
setScaleCompensation(true); setScaleCompensation(true);
} }
AABB KRBone::getBounds() { AABB KRBone::getBounds()
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix()); // Only required for bone debug visualization {
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix()); // Only required for bone debug visualization
} }
void KRBone::render(RenderInfo& ri) void KRBone::render(RenderInfo& ri)
{ {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if (m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(ri);
bool bVisualize = ri.camera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_BONES;
if(ri.renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
KRMesh* sphereModel = getContext().getMeshManager()->getMaxLODModel("__sphere");
if (sphereModel) {
Matrix4 sphereModelMatrix = getModelMatrix();
PipelineInfo info{};
std::string shader_name("visualize_overlay");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &ri.point_lights;
info.directional_lights = &ri.directional_lights;
info.spot_lights = &ri.spot_lights;
info.renderPass = ri.renderPass;
info.rasterMode = RasterMode::kAdditiveNoTest;
info.modelFormat = sphereModel->getModelFormat();
info.vertexAttributes = sphereModel->getVertexAttributes();
KRPipeline *pShader = getContext().getPipelineManager()->getPipeline(*ri.surface, info); KRNode::render(ri);
pShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, sphereModelMatrix, &ri.point_lights, &ri.directional_lights, &ri.spot_lights, ri.renderPass);
sphereModel->renderNoMaterials(ri.commandBuffer, ri.renderPass, getName(), "visualize_overlay", 1.0f); bool bVisualize = ri.camera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_BONES;
} // sphereModel
} if (ri.renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
KRMesh* sphereModel = getContext().getMeshManager()->getMaxLODModel("__sphere");
if (sphereModel) {
Matrix4 sphereModelMatrix = getModelMatrix();
PipelineInfo info{};
std::string shader_name("visualize_overlay");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &ri.point_lights;
info.directional_lights = &ri.directional_lights;
info.spot_lights = &ri.spot_lights;
info.renderPass = ri.renderPass;
info.rasterMode = RasterMode::kAdditiveNoTest;
info.modelFormat = sphereModel->getModelFormat();
info.vertexAttributes = sphereModel->getVertexAttributes();
KRPipeline* pShader = getContext().getPipelineManager()->getPipeline(*ri.surface, info);
pShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, sphereModelMatrix, &ri.point_lights, &ri.directional_lights, &ri.spot_lights, ri.renderPass);
sphereModel->renderNoMaterials(ri.commandBuffer, ri.renderPass, getName(), "visualize_overlay", 1.0f);
} // sphereModel
}
} }
void KRBone::setBindPose(const Matrix4 &pose) void KRBone::setBindPose(const Matrix4& pose)
{ {
m_bind_pose = pose; m_bind_pose = pose;
} }
const Matrix4 &KRBone::getBindPose() const Matrix4& KRBone::getBindPose()
{ {
return m_bind_pose; return m_bind_pose;
} }

View File

@@ -37,21 +37,22 @@
class RenderInfo; class RenderInfo;
class KRBone : public KRNode { class KRBone : public KRNode
{
public: public:
static void InitNodeInfo(KrNodeInfo* nodeInfo); static void InitNodeInfo(KrNodeInfo* nodeInfo);
KRBone(KRScene &scene, std::string name); KRBone(KRScene& scene, std::string name);
virtual ~KRBone(); virtual ~KRBone();
virtual std::string getElementName(); virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
virtual void loadXML(tinyxml2::XMLElement *e); virtual void loadXML(tinyxml2::XMLElement* e);
virtual AABB getBounds(); virtual AABB getBounds();
void render(RenderInfo& ri);
void setBindPose(const Matrix4 &pose); void render(RenderInfo& ri);
const Matrix4 &getBindPose();
void setBindPose(const Matrix4& pose);
const Matrix4& getBindPose();
private: private:
Matrix4 m_bind_pose; Matrix4 m_bind_pose;
}; };

View File

@@ -37,133 +37,134 @@ const int KRENGINE_KRBUNDLE_HEADER_SIZE = 512;
typedef struct _tar_header typedef struct _tar_header
{ {
char file_name[100]; char file_name[100];
char file_mode[8]; char file_mode[8];
char owner_id[8]; // Owner's numeric user ID (OCTAL!) char owner_id[8]; // Owner's numeric user ID (OCTAL!)
char group_id[8]; // Group's numeric user ID (OCTAL!) char group_id[8]; // Group's numeric user ID (OCTAL!)
char file_size[12]; // File size in bytes (OCTAL!) char file_size[12]; // File size in bytes (OCTAL!)
char mod_time[12]; // Last modification time in numeric Unix time format char mod_time[12]; // Last modification time in numeric Unix time format
char checksum[8]; // Checksum for header block char checksum[8]; // Checksum for header block
char file_type[1]; // Link indicator (file type) char file_type[1]; // Link indicator (file type)
char linked_file[100]; // Name of linked file char linked_file[100]; // Name of linked file
} tar_header_type; } tar_header_type;
KRBundle::KRBundle(KRContext &context, std::string name, KRDataBlock *pData) : KRResource(context, name) KRBundle::KRBundle(KRContext& context, std::string name, KRDataBlock* pData) : KRResource(context, name)
{ {
m_pData = pData; m_pData = pData;
__int64_t file_pos = 0; __int64_t file_pos = 0;
while(file_pos < (__int64_t)m_pData->getSize()) { while (file_pos < (__int64_t)m_pData->getSize()) {
tar_header_type file_header; tar_header_type file_header;
m_pData->copy(&file_header, (int)file_pos, sizeof(file_header)); m_pData->copy(&file_header, (int)file_pos, sizeof(file_header));
size_t file_size = strtol(file_header.file_size, NULL, 8); size_t file_size = strtol(file_header.file_size, NULL, 8);
file_pos += 512; // Skip past the header to the file contents file_pos += 512; // Skip past the header to the file contents
if(file_header.file_name[0] != '\0' && file_header.file_name[0] != '.') { if (file_header.file_name[0] != '\0' && file_header.file_name[0] != '.') {
// We ignore the last two records in the tar file, which are zero'ed out tar_header structures // We ignore the last two records in the tar file, which are zero'ed out tar_header structures
KRDataBlock *pFileData = pData->getSubBlock((int)file_pos, (int)file_size); KRDataBlock* pFileData = pData->getSubBlock((int)file_pos, (int)file_size);
context.loadResource(file_header.file_name, pFileData); context.loadResource(file_header.file_name, pFileData);
}
file_pos += RoundUpSize(file_size);
} }
file_pos += RoundUpSize(file_size);
}
} }
KRBundle::KRBundle(KRContext &context, std::string name) : KRResource(context, name) KRBundle::KRBundle(KRContext& context, std::string name) : KRResource(context, name)
{ {
// Create an empty krbundle (tar) file, initialized with two zero-ed out file headers, which terminate it. // Create an empty krbundle (tar) file, initialized with two zero-ed out file headers, which terminate it.
m_pData = new KRDataBlock(); m_pData = new KRDataBlock();
m_pData->expand(KRENGINE_KRBUNDLE_HEADER_SIZE * 2); m_pData->expand(KRENGINE_KRBUNDLE_HEADER_SIZE * 2);
m_pData->lock(); m_pData->lock();
memset(m_pData->getStart(), 0, m_pData->getSize()); memset(m_pData->getStart(), 0, m_pData->getSize());
m_pData->unlock(); m_pData->unlock();
} }
size_t KRBundle::RoundUpSize(size_t s) size_t KRBundle::RoundUpSize(size_t s)
{ {
// Get amount of padding needed to increase s to a 512 byte alignment // Get amount of padding needed to increase s to a 512 byte alignment
if((s & 0x01ff) == 0) { if ((s & 0x01ff) == 0) {
// file size is a multiple of 512 bytes, we can just add it // file size is a multiple of 512 bytes, we can just add it
return s; return s;
} else { } else {
// We would not be on a 512 byte boundary, round up to the next one // We would not be on a 512 byte boundary, round up to the next one
return (s + 0x0200) - (s & 0x1ff); return (s + 0x0200) - (s & 0x1ff);
} }
} }
KRBundle::~KRBundle() KRBundle::~KRBundle()
{ {
delete m_pData; delete m_pData;
} }
std::string KRBundle::getExtension() std::string KRBundle::getExtension()
{ {
return "krbundle"; return "krbundle";
} }
bool KRBundle::save(const std::string& path) bool KRBundle::save(const std::string& path)
{ {
return m_pData->save(path); return m_pData->save(path);
} }
bool KRBundle::save(KRDataBlock &data) { bool KRBundle::save(KRDataBlock& data)
if(m_pData->getSize() > KRENGINE_KRBUNDLE_HEADER_SIZE * 2) {
// Only output krbundles that contain files
data.append(*m_pData);
}
return true;
}
KRDataBlock* KRBundle::append(KRResource &resource)
{ {
// Serialize resource to binary representation if (m_pData->getSize() > KRENGINE_KRBUNDLE_HEADER_SIZE * 2) {
KRDataBlock resource_data; // Only output krbundles that contain files
resource.save(resource_data); data.append(*m_pData);
}
std::string file_name = resource.getName() + "." + resource.getExtension(); return true;
}
// Padding is added at the end of file to align next header to a 512 byte boundary. Padding at the end of the archive includes an additional 1024 bytes -- two zero-ed out file headers that mark the end of the archive
size_t padding_size = RoundUpSize(resource_data.getSize()) - resource_data.getSize() + KRENGINE_KRBUNDLE_HEADER_SIZE * 2; KRDataBlock* KRBundle::append(KRResource& resource)
size_t resource_data_start = m_pData->getSize() + KRENGINE_KRBUNDLE_HEADER_SIZE; {
m_pData->expand(KRENGINE_KRBUNDLE_HEADER_SIZE + resource_data.getSize() + padding_size - KRENGINE_KRBUNDLE_HEADER_SIZE * 2); // We will overwrite the existing zero-ed out file headers that marked the end of the archive, so we don't have to include their size here // Serialize resource to binary representation
KRDataBlock resource_data;
m_pData->lock(); resource.save(resource_data);
// Get location of file header std::string file_name = resource.getName() + "." + resource.getExtension();
tar_header_type *file_header = (tar_header_type *)((unsigned char *)m_pData->getEnd() - padding_size - resource_data.getSize() - KRENGINE_KRBUNDLE_HEADER_SIZE);
// Padding is added at the end of file to align next header to a 512 byte boundary. Padding at the end of the archive includes an additional 1024 bytes -- two zero-ed out file headers that mark the end of the archive
// Zero out new file header size_t padding_size = RoundUpSize(resource_data.getSize()) - resource_data.getSize() + KRENGINE_KRBUNDLE_HEADER_SIZE * 2;
memset(file_header, 0, KRENGINE_KRBUNDLE_HEADER_SIZE); size_t resource_data_start = m_pData->getSize() + KRENGINE_KRBUNDLE_HEADER_SIZE;
m_pData->expand(KRENGINE_KRBUNDLE_HEADER_SIZE + resource_data.getSize() + padding_size - KRENGINE_KRBUNDLE_HEADER_SIZE * 2); // We will overwrite the existing zero-ed out file headers that marked the end of the archive, so we don't have to include their size here
// Copy resource data
resource_data.lock(); m_pData->lock();
memcpy((unsigned char *)m_pData->getEnd() - padding_size - resource_data.getSize(), resource_data.getStart(), resource_data.getSize());
resource_data.unlock(); // Get location of file header
tar_header_type* file_header = (tar_header_type*)((unsigned char*)m_pData->getEnd() - padding_size - resource_data.getSize() - KRENGINE_KRBUNDLE_HEADER_SIZE);
// Zero out alignment padding and terminating set of file header blocks
memset((unsigned char *)m_pData->getEnd() - padding_size, 0, padding_size); // Zero out new file header
memset(file_header, 0, KRENGINE_KRBUNDLE_HEADER_SIZE);
// Populate new file header fields
strncpy(file_header->file_name, file_name.c_str(), 100); // Copy resource data
strcpy(file_header->file_mode, "000644 "); resource_data.lock();
strcpy(file_header->owner_id, "000000 "); memcpy((unsigned char*)m_pData->getEnd() - padding_size - resource_data.getSize(), resource_data.getStart(), resource_data.getSize());
strcpy(file_header->group_id, "000000 "); resource_data.unlock();
sprintf(file_header->file_size, "%011o", (int)resource_data.getSize());
file_header->file_size[11] = ' '; // Terminate with space rather than '\0' // Zero out alignment padding and terminating set of file header blocks
sprintf(file_header->mod_time, "%011o", (int)time(NULL)); memset((unsigned char*)m_pData->getEnd() - padding_size, 0, padding_size);
file_header->mod_time[11] = ' '; // Terminate with space rather than '\0'
// Populate new file header fields
// Calculate and write checksum for header strncpy(file_header->file_name, file_name.c_str(), 100);
memset(file_header->checksum, ' ', 8); // Must be filled with spaces and no null terminator during checksum calculation strcpy(file_header->file_mode, "000644 ");
int check_sum = 0; strcpy(file_header->owner_id, "000000 ");
for(int i=0; i < KRENGINE_KRBUNDLE_HEADER_SIZE; i++) { strcpy(file_header->group_id, "000000 ");
unsigned char *byte_ptr = (unsigned char *)file_header; sprintf(file_header->file_size, "%011o", (int)resource_data.getSize());
check_sum += byte_ptr[i]; file_header->file_size[11] = ' '; // Terminate with space rather than '\0'
} sprintf(file_header->mod_time, "%011o", (int)time(NULL));
sprintf(file_header->checksum, "%07o", check_sum); file_header->mod_time[11] = ' '; // Terminate with space rather than '\0'
m_pData->unlock(); // Calculate and write checksum for header
memset(file_header->checksum, ' ', 8); // Must be filled with spaces and no null terminator during checksum calculation
KRDataBlock *pFileData = m_pData->getSubBlock((int)resource_data_start, (int)resource_data.getSize()); int check_sum = 0;
return pFileData; for (int i = 0; i < KRENGINE_KRBUNDLE_HEADER_SIZE; i++) {
unsigned char* byte_ptr = (unsigned char*)file_header;
check_sum += byte_ptr[i];
}
sprintf(file_header->checksum, "%07o", check_sum);
m_pData->unlock();
KRDataBlock* pFileData = m_pData->getSubBlock((int)resource_data_start, (int)resource_data.getSize());
return pFileData;
} }

View File

@@ -34,18 +34,19 @@
#include "KRResource.h" #include "KRResource.h"
#include "KRDataBlock.h" #include "KRDataBlock.h"
class KRBundle : public KRResource { class KRBundle : public KRResource
{
public: public:
KRBundle(KRContext &context, std::string name, KRDataBlock *pData); KRBundle(KRContext& context, std::string name, KRDataBlock* pData);
KRBundle(KRContext &context, std::string name); KRBundle(KRContext& context, std::string name);
virtual ~KRBundle(); virtual ~KRBundle();
virtual std::string getExtension(); virtual std::string getExtension();
virtual bool save(const std::string& path); virtual bool save(const std::string& path);
virtual bool save(KRDataBlock &data); virtual bool save(KRDataBlock& data);
KRDataBlock* append(KRResource &resource); KRDataBlock* append(KRResource& resource);
private: private:
KRDataBlock *m_pData; KRDataBlock* m_pData;
static size_t RoundUpSize(size_t s); static size_t RoundUpSize(size_t s);
}; };

View File

@@ -33,21 +33,23 @@
#include "KRBundle.h" #include "KRBundle.h"
KRBundleManager::KRBundleManager(KRContext &context) : KRResourceManager(context) { KRBundleManager::KRBundleManager(KRContext& context) : KRResourceManager(context)
{
} }
KRBundleManager::~KRBundleManager() { KRBundleManager::~KRBundleManager()
for(unordered_map<std::string, KRBundle *>::iterator itr = m_bundles.begin(); itr != m_bundles.end(); ++itr){ {
delete (*itr).second; for (unordered_map<std::string, KRBundle*>::iterator itr = m_bundles.begin(); itr != m_bundles.end(); ++itr) {
} delete (*itr).second;
m_bundles.clear(); }
m_bundles.clear();
} }
KRResource* KRBundleManager::loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) KRResource* KRBundleManager::loadResource(const std::string& name, const std::string& extension, KRDataBlock* data)
{ {
if (extension.compare("krbundle") == 0) { if (extension.compare("krbundle") == 0) {
return loadBundle(name.c_str() , data); return loadBundle(name.c_str(), data);
} }
return nullptr; return nullptr;
} }
@@ -59,25 +61,27 @@ KRResource* KRBundleManager::getResource(const std::string& name, const std::str
return nullptr; return nullptr;
} }
KRBundle *KRBundleManager::loadBundle(const char *szName, KRDataBlock *pData) KRBundle* KRBundleManager::loadBundle(const char* szName, KRDataBlock* pData)
{ {
KRBundle *pBundle = new KRBundle(*m_pContext, szName, pData); KRBundle* pBundle = new KRBundle(*m_pContext, szName, pData);
m_bundles[szName] = pBundle;
return pBundle;
}
KRBundle *KRBundleManager::createBundle(const char *szName)
{
// TODO: Check for name conflicts
KRBundle *pBundle = new KRBundle(*m_pContext, szName);
m_bundles[szName] = pBundle; m_bundles[szName] = pBundle;
return pBundle; return pBundle;
} }
KRBundle *KRBundleManager::getBundle(const char *szName) { KRBundle* KRBundleManager::createBundle(const char* szName)
return m_bundles[szName]; {
// TODO: Check for name conflicts
KRBundle* pBundle = new KRBundle(*m_pContext, szName);
m_bundles[szName] = pBundle;
return pBundle;
} }
unordered_map<std::string, KRBundle *> KRBundleManager::getBundles() { KRBundle* KRBundleManager::getBundle(const char* szName)
return m_bundles; {
return m_bundles[szName];
}
unordered_map<std::string, KRBundle*> KRBundleManager::getBundles()
{
return m_bundles;
} }

View File

@@ -40,21 +40,22 @@
class KRContext; class KRContext;
class KRBundle; class KRBundle;
class KRBundleManager : public KRResourceManager { class KRBundleManager : public KRResourceManager
{
public: public:
KRBundleManager(KRContext &context); KRBundleManager(KRContext& context);
~KRBundleManager(); ~KRBundleManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
KRBundle* loadBundle(const char* szName, KRDataBlock* pData);
KRBundle* getBundle(const char* szName);
KRBundle* createBundle(const char* szName);
std::vector<std::string> getBundleNames();
unordered_map<std::string, KRBundle*> getBundles();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
KRBundle *loadBundle(const char *szName, KRDataBlock *pData);
KRBundle *getBundle(const char *szName);
KRBundle* createBundle(const char* szName);
std::vector<std::string> getBundleNames();
unordered_map<std::string, KRBundle *> getBundles();
private: private:
unordered_map<std::string, KRBundle *> m_bundles; unordered_map<std::string, KRBundle*> m_bundles;
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -48,74 +48,76 @@ class KRScene;
class KRViewport; class KRViewport;
class KRSurface; class KRSurface;
class KRCamera : public KRNode { class KRCamera : public KRNode
{
public: public:
static void InitNodeInfo(KrNodeInfo* nodeInfo); static void InitNodeInfo(KrNodeInfo* nodeInfo);
KRCamera(KRScene &scene, std::string name); KRCamera(KRScene& scene, std::string name);
virtual ~KRCamera(); virtual ~KRCamera();
void renderFrame(VkCommandBuffer& commandBuffer, KRSurface& compositeSurface); void renderFrame(VkCommandBuffer& commandBuffer, KRSurface& compositeSurface);
KRRenderSettings settings; KRRenderSettings settings;
const KRViewport &getViewport() const; const KRViewport& getViewport() const;
virtual std::string getElementName(); virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
virtual void loadXML(tinyxml2::XMLElement *e); virtual void loadXML(tinyxml2::XMLElement* e);
std::string getDebugText(); std::string getDebugText();
void flushSkybox(); // this will delete the skybox and cause the camera to reload a new skybox based on the settings void flushSkybox(); // this will delete the skybox and cause the camera to reload a new skybox based on the settings
Vector2 getDownsample(); Vector2 getDownsample();
void setDownsample(float v); void setDownsample(float v);
void setFadeColor(const Vector4 &fade_color); void setFadeColor(const Vector4& fade_color);
Vector4 getFadeColor(); Vector4 getFadeColor();
void setSkyBox(const std::string &skyBox); void setSkyBox(const std::string& skyBox);
const std::string getSkyBox() const; const std::string getSkyBox() const;
private: private:
void createBuffers(GLint renderBufferWidth, GLint renderBufferHeight); void createBuffers(GLint renderBufferWidth, GLint renderBufferHeight);
GLint volumetricBufferWidth, volumetricBufferHeight; GLint volumetricBufferWidth, volumetricBufferHeight;
GLuint compositeFramebuffer, compositeDepthTexture, compositeColorTexture; GLuint compositeFramebuffer, compositeDepthTexture, compositeColorTexture;
GLuint lightAccumulationBuffer, lightAccumulationTexture; GLuint lightAccumulationBuffer, lightAccumulationTexture;
GLuint volumetricLightAccumulationBuffer, volumetricLightAccumulationTexture; GLuint volumetricLightAccumulationBuffer, volumetricLightAccumulationTexture;
void renderPost(VkCommandBuffer& commandBuffer, KRSurface& surface); void renderPost(VkCommandBuffer& commandBuffer, KRSurface& surface);
void destroyBuffers(); void destroyBuffers();
KRTexture *m_pSkyBoxTexture; KRTexture* m_pSkyBoxTexture;
std::string m_skyBox; std::string m_skyBox;
KRViewport m_viewport; KRViewport m_viewport;
float m_particlesAbsoluteTime; float m_particlesAbsoluteTime;
Vector2 m_downsample; Vector2 m_downsample;
Vector4 m_fade_color; Vector4 m_fade_color;
typedef struct { typedef struct
float x; {
float y; float x;
float z; float y;
float u; float z;
float v; float u;
} DebugTextVertexData; float v;
} DebugTextVertexData;
KRDataBlock m_debug_text_vertices;
KRMeshManager::KRVBOData m_debug_text_vbo_data; KRDataBlock m_debug_text_vertices;
KRMeshManager::KRVBOData m_debug_text_vbo_data;
// std::string getDebugText();
// std::string getDebugText();
uint64_t m_last_frame_start;
int m_frame_times[KRAKEN_FPS_AVERAGE_FRAME_COUNT]; uint64_t m_last_frame_start;
int m_frame_times_filled; int m_frame_times[KRAKEN_FPS_AVERAGE_FRAME_COUNT];
int m_frame_times_filled;
}; };

View File

@@ -43,187 +43,193 @@ void KRCollider::InitNodeInfo(KrNodeInfo* nodeInfo)
nodeInfo->collider.mesh = -1; nodeInfo->collider.mesh = -1;
} }
KRCollider::KRCollider(KRScene &scene, std::string collider_name, std::string model_name, unsigned int layer_mask, float audio_occlusion) : KRNode(scene, collider_name) { KRCollider::KRCollider(KRScene& scene, std::string collider_name, std::string model_name, unsigned int layer_mask, float audio_occlusion) : KRNode(scene, collider_name)
m_model_name = model_name;
m_layer_mask = layer_mask;
m_audio_occlusion = audio_occlusion;
m_model = nullptr;
}
KRCollider::~KRCollider() {
}
std::string KRCollider::getElementName() {
return "collider";
}
tinyxml2::XMLElement *KRCollider::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); m_model_name = model_name;
e->SetAttribute("mesh", m_model_name.c_str()); m_layer_mask = layer_mask;
e->SetAttribute("layer_mask", m_layer_mask); m_audio_occlusion = audio_occlusion;
e->SetAttribute("audio_occlusion", m_audio_occlusion); m_model = nullptr;
return e;
} }
void KRCollider::loadXML(tinyxml2::XMLElement *e) { KRCollider::~KRCollider()
KRNode::loadXML(e); {
m_model_name = e->Attribute("mesh"); }
std::string KRCollider::getElementName()
{
return "collider";
}
tinyxml2::XMLElement* KRCollider::saveXML(tinyxml2::XMLNode* parent)
{
tinyxml2::XMLElement* e = KRNode::saveXML(parent);
e->SetAttribute("mesh", m_model_name.c_str());
e->SetAttribute("layer_mask", m_layer_mask);
e->SetAttribute("audio_occlusion", m_audio_occlusion);
return e;
}
void KRCollider::loadXML(tinyxml2::XMLElement* e)
{
KRNode::loadXML(e);
m_model_name = e->Attribute("mesh");
m_layer_mask = 65535;
if (e->QueryUnsignedAttribute("layer_mask", &m_layer_mask) != tinyxml2::XML_SUCCESS) {
m_layer_mask = 65535; m_layer_mask = 65535;
if(e->QueryUnsignedAttribute("layer_mask", &m_layer_mask) != tinyxml2::XML_SUCCESS) { }
m_layer_mask = 65535;
} m_audio_occlusion = 1.0f;
if (e->QueryFloatAttribute("audio_occlusion", &m_audio_occlusion) != tinyxml2::XML_SUCCESS) {
m_audio_occlusion = 1.0f; m_audio_occlusion = 1.0f;
if(e->QueryFloatAttribute("audio_occlusion", &m_audio_occlusion) != tinyxml2::XML_SUCCESS) { }
m_audio_occlusion = 1.0f;
}
} }
void KRCollider::loadModel() { void KRCollider::loadModel()
if(m_model == nullptr) { {
m_model = m_pContext->getMeshManager()->getMaxLODModel(m_model_name.c_str()); if (m_model == nullptr) {
if(m_model) { m_model = m_pContext->getMeshManager()->getMaxLODModel(m_model_name.c_str());
getScene().notify_sceneGraphModify(this); if (m_model) {
} getScene().notify_sceneGraphModify(this);
} }
}
} }
AABB KRCollider::getBounds() { AABB KRCollider::getBounds()
{
loadModel(); loadModel();
if(m_model) { if (m_model) {
return AABB::Create(m_model->getMinPoint(), m_model->getMaxPoint(), getModelMatrix()); return AABB::Create(m_model->getMinPoint(), m_model->getMaxPoint(), getModelMatrix());
} else { } else {
return AABB::Infinite(); return AABB::Infinite();
} }
} }
bool KRCollider::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask) bool KRCollider::lineCast(const Vector3& v0, const Vector3& v1, HitInfo& hitinfo, unsigned int layer_mask)
{ {
if(layer_mask & m_layer_mask ) { // Only test if layer masks have a common bit set if (layer_mask & m_layer_mask) { // Only test if layer masks have a common bit set
loadModel(); loadModel();
if(m_model) { if (m_model) {
if(getBounds().intersectsLine(v0, v1)) { if (getBounds().intersectsLine(v0, v1)) {
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0); Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
Vector3 v1_model_space = Matrix4::Dot(getInverseModelMatrix(), v1); Vector3 v1_model_space = Matrix4::Dot(getInverseModelMatrix(), v1);
HitInfo hitinfo_model_space; HitInfo hitinfo_model_space;
if(hitinfo.didHit()) { if (hitinfo.didHit()) {
Vector3 hit_position_model_space = Matrix4::Dot(getInverseModelMatrix(), hitinfo.getPosition()); Vector3 hit_position_model_space = Matrix4::Dot(getInverseModelMatrix(), hitinfo.getPosition());
hitinfo_model_space = HitInfo(hit_position_model_space, Matrix4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal()), (hit_position_model_space - v0_model_space).magnitude(), hitinfo.getNode()); hitinfo_model_space = HitInfo(hit_position_model_space, Matrix4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal()), (hit_position_model_space - v0_model_space).magnitude(), hitinfo.getNode());
}
if(m_model->lineCast(v0_model_space, v1_model_space, hitinfo_model_space)) {
Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition());
hitinfo = HitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
return true;
}
}
} }
if (m_model->lineCast(v0_model_space, v1_model_space, hitinfo_model_space)) {
Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition());
hitinfo = HitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
return true;
}
}
} }
return false; }
return false;
} }
bool KRCollider::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask) bool KRCollider::rayCast(const Vector3& v0, const Vector3& dir, HitInfo& hitinfo, unsigned int layer_mask)
{ {
if(layer_mask & m_layer_mask) { // Only test if layer masks have a common bit set if (layer_mask & m_layer_mask) { // Only test if layer masks have a common bit set
loadModel(); loadModel();
if(m_model) { if (m_model) {
if(getBounds().intersectsRay(v0, dir)) { if (getBounds().intersectsRay(v0, dir)) {
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0); Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
Vector3 dir_model_space = Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), dir)); Vector3 dir_model_space = Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), dir));
HitInfo hitinfo_model_space; HitInfo hitinfo_model_space;
if(hitinfo.didHit()) { if (hitinfo.didHit()) {
Vector3 hit_position_model_space = Matrix4::Dot(getInverseModelMatrix(), hitinfo.getPosition()); Vector3 hit_position_model_space = Matrix4::Dot(getInverseModelMatrix(), hitinfo.getPosition());
hitinfo_model_space = HitInfo(hit_position_model_space, Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal())), (hit_position_model_space - v0_model_space).magnitude(), hitinfo.getNode()); hitinfo_model_space = HitInfo(hit_position_model_space, Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal())), (hit_position_model_space - v0_model_space).magnitude(), hitinfo.getNode());
}
if(m_model->rayCast(v0_model_space, dir_model_space, hitinfo_model_space)) {
Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition());
hitinfo = HitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
return true;
}
}
} }
if (m_model->rayCast(v0_model_space, dir_model_space, hitinfo_model_space)) {
Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition());
hitinfo = HitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
return true;
}
}
} }
return false; }
return false;
} }
bool KRCollider::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask) bool KRCollider::sphereCast(const Vector3& v0, const Vector3& v1, float radius, HitInfo& hitinfo, unsigned int layer_mask)
{ {
if(layer_mask & m_layer_mask) { // Only test if layer masks have a common bit set if (layer_mask & m_layer_mask) { // Only test if layer masks have a common bit set
loadModel(); loadModel();
if(m_model) { if (m_model) {
AABB sphereCastBounds = AABB::Create( // TODO - Need to cache this; perhaps encasulate within a "spherecast" class to be passed through these functions AABB sphereCastBounds = AABB::Create( // TODO - Need to cache this; perhaps encasulate within a "spherecast" class to be passed through these functions
Vector3::Create(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius), Vector3::Create(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius),
Vector3::Create(KRMAX(v0.x, v1.x) + radius, KRMAX(v0.y, v1.y) + radius, KRMAX(v0.z, v1.z) + radius) Vector3::Create(KRMAX(v0.x, v1.x) + radius, KRMAX(v0.y, v1.y) + radius, KRMAX(v0.z, v1.z) + radius)
); );
if(getBounds().intersects(sphereCastBounds)) { if (getBounds().intersects(sphereCastBounds)) {
if(m_model->sphereCast(getModelMatrix(), v0, v1, radius, hitinfo)) { if (m_model->sphereCast(getModelMatrix(), v0, v1, radius, hitinfo)) {
hitinfo = HitInfo(hitinfo.getPosition(), hitinfo.getNormal(), hitinfo.getDistance(), this); hitinfo = HitInfo(hitinfo.getPosition(), hitinfo.getNormal(), hitinfo.getDistance(), this);
return true; return true;
}
}
} }
}
} }
return false; }
return false;
} }
unsigned int KRCollider::getLayerMask() unsigned int KRCollider::getLayerMask()
{ {
return m_layer_mask; return m_layer_mask;
} }
void KRCollider::setLayerMask(unsigned int layer_mask) void KRCollider::setLayerMask(unsigned int layer_mask)
{ {
m_layer_mask = layer_mask; m_layer_mask = layer_mask;
} }
float KRCollider::getAudioOcclusion() float KRCollider::getAudioOcclusion()
{ {
return m_audio_occlusion; return m_audio_occlusion;
} }
void KRCollider::setAudioOcclusion(float audio_occlusion) void KRCollider::setAudioOcclusion(float audio_occlusion)
{ {
m_audio_occlusion = audio_occlusion; m_audio_occlusion = audio_occlusion;
} }
void KRCollider::render(RenderInfo& ri) void KRCollider::render(RenderInfo& ri)
{ {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if (m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(ri);
if(ri.renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && ri.camera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_COLLIDERS) {
loadModel();
if(m_model) {
GL_PUSH_GROUP_MARKER("Debug Overlays");
PipelineInfo info{};
std::string shader_name("visualize_overlay");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &ri.point_lights;
info.directional_lights = &ri.directional_lights;
info.spot_lights = &ri.spot_lights;
info.renderPass = ri.renderPass;
info.rasterMode = RasterMode::kAdditive;
info.modelFormat = m_model->getModelFormat();
info.vertexAttributes = m_model->getVertexAttributes();
KRPipeline *pShader = getContext().getPipelineManager()->getPipeline(*ri.surface, info); KRNode::render(ri);
pShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, getModelMatrix(), &ri.point_lights, &ri.directional_lights, &ri.spot_lights, ri.renderPass); if (ri.renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && ri.camera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_COLLIDERS) {
loadModel();
m_model->renderNoMaterials(ri.commandBuffer, ri.renderPass, getName(), "visualize_overlay", 1.0f); if (m_model) {
GL_POP_GROUP_MARKER; GL_PUSH_GROUP_MARKER("Debug Overlays");
}
PipelineInfo info{};
std::string shader_name("visualize_overlay");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &ri.point_lights;
info.directional_lights = &ri.directional_lights;
info.spot_lights = &ri.spot_lights;
info.renderPass = ri.renderPass;
info.rasterMode = RasterMode::kAdditive;
info.modelFormat = m_model->getModelFormat();
info.vertexAttributes = m_model->getVertexAttributes();
KRPipeline* pShader = getContext().getPipelineManager()->getPipeline(*ri.surface, info);
pShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, getModelMatrix(), &ri.point_lights, &ri.directional_lights, &ri.spot_lights, ri.renderPass);
m_model->renderNoMaterials(ri.commandBuffer, ri.renderPass, getName(), "visualize_overlay", 1.0f);
GL_POP_GROUP_MARKER;
} }
}
} }

View File

@@ -46,37 +46,38 @@
#include "KRMesh.h" #include "KRMesh.h"
#include "KRTexture.h" #include "KRTexture.h"
class KRCollider : public KRNode { class KRCollider : public KRNode
{
public:
static void InitNodeInfo(KrNodeInfo* nodeInfo); public:
static void InitNodeInfo(KrNodeInfo* nodeInfo);
KRCollider(KRScene& scene, std::string collider_name, std::string model_name, unsigned int layer_mask, float audio_occlusion);
virtual ~KRCollider();
virtual std::string getElementName();
virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
virtual void loadXML(tinyxml2::XMLElement* e);
virtual AABB getBounds();
bool lineCast(const Vector3& v0, const Vector3& v1, HitInfo& hitinfo, unsigned int layer_mask);
bool rayCast(const Vector3& v0, const Vector3& v1, HitInfo& hitinfo, unsigned int layer_mask);
bool sphereCast(const Vector3& v0, const Vector3& v1, float radius, HitInfo& hitinfo, unsigned int layer_mask);
unsigned int getLayerMask();
void setLayerMask(unsigned int layer_mask);
float getAudioOcclusion();
void setAudioOcclusion(float audio_occlusion);
void render(RenderInfo& ri);
KRCollider(KRScene &scene, std::string collider_name, std::string model_name, unsigned int layer_mask, float audio_occlusion);
virtual ~KRCollider();
virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
virtual void loadXML(tinyxml2::XMLElement *e);
virtual AABB getBounds();
bool lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask);
bool rayCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask);
bool sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask);
unsigned int getLayerMask();
void setLayerMask(unsigned int layer_mask);
float getAudioOcclusion();
void setAudioOcclusion(float audio_occlusion);
void render(RenderInfo& ri);
private: private:
KRMesh* m_model; KRMesh* m_model;
std::string m_model_name; std::string m_model_name;
unsigned int m_layer_mask; unsigned int m_layer_mask;
float m_audio_occlusion; float m_audio_occlusion;
void loadModel(); void loadModel();
}; };

View File

@@ -79,326 +79,343 @@ int KRContext::KRENGINE_SYS_PAGE_SIZE;
std::mutex KRContext::g_SurfaceInfoMutex; std::mutex KRContext::g_SurfaceInfoMutex;
std::mutex KRContext::g_DeviceInfoMutex; std::mutex KRContext::g_DeviceInfoMutex;
KRContext::log_callback *KRContext::s_log_callback = NULL; KRContext::log_callback* KRContext::s_log_callback = NULL;
void *KRContext::s_log_callback_user_data = NULL; void* KRContext::s_log_callback_user_data = NULL;
KRContext::KRContext(const KrInitializeInfo* initializeInfo) KRContext::KRContext(const KrInitializeInfo* initializeInfo)
: m_resourceMapSize(initializeInfo->resourceMapSize) : m_resourceMapSize(initializeInfo->resourceMapSize)
{ {
m_presentationThread = std::make_unique<KRPresentationThread>(*this); m_presentationThread = std::make_unique<KRPresentationThread>(*this);
m_streamerThread = std::make_unique<KRStreamerThread>(*this); m_streamerThread = std::make_unique<KRStreamerThread>(*this);
m_resourceMap = (KRResource **)malloc(sizeof(KRResource*) * m_resourceMapSize); m_resourceMap = (KRResource**)malloc(sizeof(KRResource*) * m_resourceMapSize);
memset(m_resourceMap, 0, m_resourceMapSize * sizeof(KRResource*)); memset(m_resourceMap, 0, m_resourceMapSize * sizeof(KRResource*));
m_streamingEnabled = false; m_streamingEnabled = false;
#ifdef __APPLE__ #ifdef __APPLE__
mach_timebase_info(&m_timebase_info); mach_timebase_info(&m_timebase_info);
#endif #endif
m_current_frame = 0; m_current_frame = 0;
m_last_memory_warning_frame = 0; m_last_memory_warning_frame = 0;
m_last_fully_streamed_frame = 0; m_last_fully_streamed_frame = 0;
m_absolute_time = 0.0f; m_absolute_time = 0.0f;
m_pBundleManager = std::make_unique<KRBundleManager>(*this); m_pBundleManager = std::make_unique<KRBundleManager>(*this);
m_pPipelineManager = std::make_unique<KRPipelineManager>(*this); m_pPipelineManager = std::make_unique<KRPipelineManager>(*this);
m_pTextureManager = std::make_unique<KRTextureManager>(*this); m_pTextureManager = std::make_unique<KRTextureManager>(*this);
m_pMaterialManager = std::make_unique<KRMaterialManager>(*this, m_pTextureManager.get(), m_pPipelineManager.get()); m_pMaterialManager = std::make_unique<KRMaterialManager>(*this, m_pTextureManager.get(), m_pPipelineManager.get());
m_pMeshManager = std::make_unique<KRMeshManager>(*this); m_pMeshManager = std::make_unique<KRMeshManager>(*this);
m_pMeshManager->init(); m_pMeshManager->init();
m_pSceneManager = std::make_unique<KRSceneManager>(*this); m_pSceneManager = std::make_unique<KRSceneManager>(*this);
m_pAnimationManager = std::make_unique<KRAnimationManager>(*this); m_pAnimationManager = std::make_unique<KRAnimationManager>(*this);
m_pAnimationCurveManager = std::make_unique<KRAnimationCurveManager>(*this); m_pAnimationCurveManager = std::make_unique<KRAnimationCurveManager>(*this);
m_pSoundManager = std::make_unique<KRAudioManager>(*this); m_pSoundManager = std::make_unique<KRAudioManager>(*this);
m_pUnknownManager = std::make_unique<KRUnknownManager>(*this); m_pUnknownManager = std::make_unique<KRUnknownManager>(*this);
m_pShaderManager = std::make_unique<KRShaderManager>(*this); m_pShaderManager = std::make_unique<KRShaderManager>(*this);
m_pSourceManager = std::make_unique<KRSourceManager>(*this); m_pSourceManager = std::make_unique<KRSourceManager>(*this);
m_deviceManager = std::make_unique<KRDeviceManager>(*this); m_deviceManager = std::make_unique<KRDeviceManager>(*this);
m_surfaceManager = std::make_unique<KRSurfaceManager>(*this); m_surfaceManager = std::make_unique<KRSurfaceManager>(*this);
m_streamingEnabled = true; m_streamingEnabled = true;
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
SYSTEM_INFO winSysInfo; SYSTEM_INFO winSysInfo;
GetSystemInfo(&winSysInfo); GetSystemInfo(&winSysInfo);
KRENGINE_SYS_ALLOCATION_GRANULARITY = winSysInfo.dwAllocationGranularity; KRENGINE_SYS_ALLOCATION_GRANULARITY = winSysInfo.dwAllocationGranularity;
KRENGINE_SYS_PAGE_SIZE = winSysInfo.dwPageSize; KRENGINE_SYS_PAGE_SIZE = winSysInfo.dwPageSize;
#elif defined(__APPLE__) || defined(ANDROID) #elif defined(__APPLE__) || defined(ANDROID)
KRENGINE_SYS_PAGE_SIZE = getpagesize(); KRENGINE_SYS_PAGE_SIZE = getpagesize();
KRENGINE_SYS_ALLOCATION_GRANULARITY = KRENGINE_SYS_PAGE_SIZE; KRENGINE_SYS_ALLOCATION_GRANULARITY = KRENGINE_SYS_PAGE_SIZE;
#else #else
#error Unsupported #error Unsupported
#endif #endif
m_deviceManager->initialize(); m_deviceManager->initialize();
m_presentationThread->start(); m_presentationThread->start();
m_streamerThread->start(); m_streamerThread->start();
} }
KRContext::~KRContext() { KRContext::~KRContext()
m_presentationThread->stop();
m_streamerThread->stop();
m_pSceneManager.reset();
m_pMeshManager.reset();
m_pMaterialManager.reset();
m_pTextureManager->destroy();
m_pTextureManager.reset();
m_pPipelineManager.reset();
m_pAnimationManager.reset();
m_pAnimationCurveManager.reset();
m_pSoundManager->destroy();
m_pSoundManager.reset();
m_pSourceManager.reset();
m_pUnknownManager.reset();
m_pShaderManager.reset();
m_surfaceManager.reset();
m_deviceManager.reset();
// The bundles must be destroyed last, as the other objects may be using mmap'ed data from bundles
m_pBundleManager.reset();
if (m_resourceMap) {
delete m_resourceMap;
m_resourceMap = NULL;
}
}
void KRContext::SetLogCallback(log_callback *log_callback, void *user_data)
{ {
s_log_callback = log_callback; m_presentationThread->stop();
s_log_callback_user_data = user_data; m_streamerThread->stop();
m_pSceneManager.reset();
m_pMeshManager.reset();
m_pMaterialManager.reset();
m_pTextureManager->destroy();
m_pTextureManager.reset();
m_pPipelineManager.reset();
m_pAnimationManager.reset();
m_pAnimationCurveManager.reset();
m_pSoundManager->destroy();
m_pSoundManager.reset();
m_pSourceManager.reset();
m_pUnknownManager.reset();
m_pShaderManager.reset();
m_surfaceManager.reset();
m_deviceManager.reset();
// The bundles must be destroyed last, as the other objects may be using mmap'ed data from bundles
m_pBundleManager.reset();
if (m_resourceMap) {
delete m_resourceMap;
m_resourceMap = NULL;
}
}
void KRContext::SetLogCallback(log_callback* log_callback, void* user_data)
{
s_log_callback = log_callback;
s_log_callback_user_data = user_data;
} }
void KRContext::Log(log_level level, const std::string message_format, ...) void KRContext::Log(log_level level, const std::string message_format, ...)
{ {
va_list args; va_list args;
va_start(args, message_format); va_start(args, message_format);
if(s_log_callback) { if (s_log_callback) {
const int LOG_BUFFER_SIZE = 32768; const int LOG_BUFFER_SIZE = 32768;
char log_buffer[LOG_BUFFER_SIZE]; char log_buffer[LOG_BUFFER_SIZE];
vsnprintf(log_buffer, LOG_BUFFER_SIZE, message_format.c_str(), args); vsnprintf(log_buffer, LOG_BUFFER_SIZE, message_format.c_str(), args);
s_log_callback(s_log_callback_user_data, std::string(log_buffer), level); s_log_callback(s_log_callback_user_data, std::string(log_buffer), level);
} else { } else {
FILE *out_file = level == LOG_LEVEL_INFORMATION ? stdout : stderr; FILE* out_file = level == LOG_LEVEL_INFORMATION ? stdout : stderr;
fprintf(out_file, "Kraken - INFO: "); fprintf(out_file, "Kraken - INFO: ");
vfprintf(out_file, message_format.c_str(), args); vfprintf(out_file, message_format.c_str(), args);
fprintf(out_file, "\n"); fprintf(out_file, "\n");
} }
va_end(args); va_end(args);
} }
KRBundleManager *KRContext::getBundleManager() { KRBundleManager* KRContext::getBundleManager()
return m_pBundleManager.get(); {
return m_pBundleManager.get();
} }
KRSceneManager *KRContext::getSceneManager() { KRSceneManager* KRContext::getSceneManager()
return m_pSceneManager.get(); {
return m_pSceneManager.get();
} }
KRTextureManager *KRContext::getTextureManager() { KRTextureManager* KRContext::getTextureManager()
return m_pTextureManager.get(); {
return m_pTextureManager.get();
} }
KRMaterialManager *KRContext::getMaterialManager() { KRMaterialManager* KRContext::getMaterialManager()
return m_pMaterialManager.get(); {
return m_pMaterialManager.get();
} }
KRPipelineManager *KRContext::getPipelineManager() { KRPipelineManager* KRContext::getPipelineManager()
return m_pPipelineManager.get(); {
return m_pPipelineManager.get();
} }
KRMeshManager *KRContext::getMeshManager() { KRMeshManager* KRContext::getMeshManager()
return m_pMeshManager.get(); {
return m_pMeshManager.get();
} }
KRAnimationManager *KRContext::getAnimationManager() { KRAnimationManager* KRContext::getAnimationManager()
return m_pAnimationManager.get(); {
return m_pAnimationManager.get();
} }
KRAnimationCurveManager *KRContext::getAnimationCurveManager() { KRAnimationCurveManager* KRContext::getAnimationCurveManager()
return m_pAnimationCurveManager.get(); {
return m_pAnimationCurveManager.get();
} }
KRAudioManager *KRContext::getAudioManager() { KRAudioManager* KRContext::getAudioManager()
return m_pSoundManager.get(); {
return m_pSoundManager.get();
} }
KRShaderManager *KRContext::getShaderManager() { KRShaderManager* KRContext::getShaderManager()
return m_pShaderManager.get(); {
return m_pShaderManager.get();
} }
KRSourceManager *KRContext::getSourceManager() { KRSourceManager* KRContext::getSourceManager()
return m_pSourceManager.get(); {
return m_pSourceManager.get();
} }
KRSurfaceManager* KRContext::getSurfaceManager() { KRSurfaceManager* KRContext::getSurfaceManager()
{
return m_surfaceManager.get(); return m_surfaceManager.get();
} }
KRDeviceManager* KRContext::getDeviceManager() { KRDeviceManager* KRContext::getDeviceManager()
{
return m_deviceManager.get(); return m_deviceManager.get();
} }
KRUnknownManager *KRContext::getUnknownManager() { KRUnknownManager* KRContext::getUnknownManager()
return m_pUnknownManager.get();
}
std::vector<KRResource *> KRContext::getResources()
{ {
std::vector<KRResource *> resources; return m_pUnknownManager.get();
}
for(unordered_map<std::string, KRScene *>::iterator itr = m_pSceneManager->getScenes().begin(); itr != m_pSceneManager->getScenes().end(); itr++) { std::vector<KRResource*> KRContext::getResources()
resources.push_back((*itr).second); {
} std::vector<KRResource*> resources;
for(unordered_map<std::string, KRTexture *>::iterator itr = m_pTextureManager->getTextures().begin(); itr != m_pTextureManager->getTextures().end(); itr++) {
resources.push_back((*itr).second);
}
for(unordered_map<std::string, KRMaterial *>::iterator itr = m_pMaterialManager->getMaterials().begin(); itr != m_pMaterialManager->getMaterials().end(); itr++) {
resources.push_back((*itr).second);
}
for(unordered_multimap<std::string, KRMesh *>::iterator itr = m_pMeshManager->getModels().begin(); itr != m_pMeshManager->getModels().end(); itr++) {
resources.push_back((*itr).second);
}
for(unordered_map<std::string, KRAnimation *>::iterator itr = m_pAnimationManager->getAnimations().begin(); itr != m_pAnimationManager->getAnimations().end(); itr++) {
resources.push_back((*itr).second);
}
for(unordered_map<std::string, KRAnimationCurve *>::iterator itr = m_pAnimationCurveManager->getAnimationCurves().begin(); itr != m_pAnimationCurveManager->getAnimationCurves().end(); itr++) {
resources.push_back((*itr).second);
}
for(unordered_map<std::string, KRAudioSample *>::iterator itr = m_pSoundManager->getSounds().begin(); itr != m_pSoundManager->getSounds().end(); itr++) {
resources.push_back((*itr).second);
}
unordered_map<std::string, unordered_map<std::string, KRSource *> > sources = m_pSourceManager->getSources(); for (unordered_map<std::string, KRScene*>::iterator itr = m_pSceneManager->getScenes().begin(); itr != m_pSceneManager->getScenes().end(); itr++) {
for(unordered_map<std::string, unordered_map<std::string, KRSource *> >::iterator itr = sources.begin(); itr != sources.end(); itr++) { resources.push_back((*itr).second);
for(unordered_map<std::string, KRSource *>::iterator itr2 = (*itr).second.begin(); itr2 != (*itr).second.end(); itr2++) { }
resources.push_back((*itr2).second); for (unordered_map<std::string, KRTexture*>::iterator itr = m_pTextureManager->getTextures().begin(); itr != m_pTextureManager->getTextures().end(); itr++) {
} resources.push_back((*itr).second);
} }
for (unordered_map<std::string, KRMaterial*>::iterator itr = m_pMaterialManager->getMaterials().begin(); itr != m_pMaterialManager->getMaterials().end(); itr++) {
resources.push_back((*itr).second);
}
for (unordered_multimap<std::string, KRMesh*>::iterator itr = m_pMeshManager->getModels().begin(); itr != m_pMeshManager->getModels().end(); itr++) {
resources.push_back((*itr).second);
}
for (unordered_map<std::string, KRAnimation*>::iterator itr = m_pAnimationManager->getAnimations().begin(); itr != m_pAnimationManager->getAnimations().end(); itr++) {
resources.push_back((*itr).second);
}
for (unordered_map<std::string, KRAnimationCurve*>::iterator itr = m_pAnimationCurveManager->getAnimationCurves().begin(); itr != m_pAnimationCurveManager->getAnimationCurves().end(); itr++) {
resources.push_back((*itr).second);
}
for (unordered_map<std::string, KRAudioSample*>::iterator itr = m_pSoundManager->getSounds().begin(); itr != m_pSoundManager->getSounds().end(); itr++) {
resources.push_back((*itr).second);
}
unordered_map<std::string, unordered_map<std::string, KRShader *> > shaders = m_pShaderManager->getShaders(); unordered_map<std::string, unordered_map<std::string, KRSource*> > sources = m_pSourceManager->getSources();
for(unordered_map<std::string, unordered_map<std::string, KRShader *> >::iterator itr = shaders.begin(); itr != shaders.end(); itr++) { for (unordered_map<std::string, unordered_map<std::string, KRSource*> >::iterator itr = sources.begin(); itr != sources.end(); itr++) {
for(unordered_map<std::string, KRShader *>::iterator itr2 = (*itr).second.begin(); itr2 != (*itr).second.end(); itr2++) { for (unordered_map<std::string, KRSource*>::iterator itr2 = (*itr).second.begin(); itr2 != (*itr).second.end(); itr2++) {
resources.push_back((*itr2).second); resources.push_back((*itr2).second);
}
} }
}
unordered_map<std::string, unordered_map<std::string, KRUnknown *> > unknowns = m_pUnknownManager->getUnknowns();
for(unordered_map<std::string, unordered_map<std::string, KRUnknown *> >::iterator itr = unknowns.begin(); itr != unknowns.end(); itr++) { unordered_map<std::string, unordered_map<std::string, KRShader*> > shaders = m_pShaderManager->getShaders();
for(unordered_map<std::string, KRUnknown *>::iterator itr2 = (*itr).second.begin(); itr2 != (*itr).second.end(); itr2++) { for (unordered_map<std::string, unordered_map<std::string, KRShader*> >::iterator itr = shaders.begin(); itr != shaders.end(); itr++) {
resources.push_back((*itr2).second); for (unordered_map<std::string, KRShader*>::iterator itr2 = (*itr).second.begin(); itr2 != (*itr).second.end(); itr2++) {
} resources.push_back((*itr2).second);
} }
}
return resources;
unordered_map<std::string, unordered_map<std::string, KRUnknown*> > unknowns = m_pUnknownManager->getUnknowns();
for (unordered_map<std::string, unordered_map<std::string, KRUnknown*> >::iterator itr = unknowns.begin(); itr != unknowns.end(); itr++) {
for (unordered_map<std::string, KRUnknown*>::iterator itr2 = (*itr).second.begin(); itr2 != (*itr).second.end(); itr2++) {
resources.push_back((*itr2).second);
}
}
return resources;
} }
KRResource* KRContext::loadResource(const std::string &file_name, KRDataBlock *data) { KRResource* KRContext::loadResource(const std::string& file_name, KRDataBlock* data)
std::string name = KRResource::GetFileBase(file_name); {
std::string extension = KRResource::GetFileExtension(file_name); std::string name = KRResource::GetFileBase(file_name);
std::string extension = KRResource::GetFileExtension(file_name);
KRResource *resource = nullptr; KRResource* resource = nullptr;
// fprintf(stderr, "KRContext::loadResource - Loading: %s\n", file_name.c_str()); // fprintf(stderr, "KRContext::loadResource - Loading: %s\n", file_name.c_str());
if(extension.compare("krbundle") == 0) { if (extension.compare("krbundle") == 0) {
resource = m_pBundleManager->loadBundle(name.c_str(), data); resource = m_pBundleManager->loadBundle(name.c_str(), data);
} else if(extension.compare("krmesh") == 0) { } else if (extension.compare("krmesh") == 0) {
resource = m_pMeshManager->loadModel(name.c_str(), data); resource = m_pMeshManager->loadModel(name.c_str(), data);
} else if(extension.compare("krscene") == 0) { } else if (extension.compare("krscene") == 0) {
resource = m_pSceneManager->loadScene(name.c_str(), data); resource = m_pSceneManager->loadScene(name.c_str(), data);
} else if(extension.compare("kranimation") == 0) { } else if (extension.compare("kranimation") == 0) {
resource = m_pAnimationManager->loadAnimation(name.c_str(), data); resource = m_pAnimationManager->loadAnimation(name.c_str(), data);
} else if(extension.compare("kranimationcurve") == 0) { } else if (extension.compare("kranimationcurve") == 0) {
resource = m_pAnimationCurveManager->loadAnimationCurve(name.c_str(), data); resource = m_pAnimationCurveManager->loadAnimationCurve(name.c_str(), data);
} else if(extension.compare("pvr") == 0) { } else if (extension.compare("pvr") == 0) {
resource = m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data); resource = m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data);
} else if(extension.compare("ktx") == 0) { } else if (extension.compare("ktx") == 0) {
resource = m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data); resource = m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data);
} else if(extension.compare("tga") == 0) { } else if (extension.compare("tga") == 0) {
resource = m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data); resource = m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data);
} else if(extension.compare("spv") == 0) { } else if (extension.compare("spv") == 0) {
// SPIR-V shader binary // SPIR-V shader binary
resource = m_pShaderManager->load(name, extension, data); resource = m_pShaderManager->load(name, extension, data);
} else if(extension.compare("vert") == 0) { } else if (extension.compare("vert") == 0) {
// vertex shader // vertex shader
resource = m_pSourceManager->load(name, extension, data); resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("frag") == 0) { } else if (extension.compare("frag") == 0) {
// fragment shader // fragment shader
resource = m_pSourceManager->load(name, extension, data); resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("tesc") == 0) { } else if (extension.compare("tesc") == 0) {
// tessellation control shader // tessellation control shader
resource = m_pSourceManager->load(name, extension, data); resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("tese") == 0) { } else if (extension.compare("tese") == 0) {
// tessellation evaluation shader // tessellation evaluation shader
resource = m_pSourceManager->load(name, extension, data); resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("geom") == 0) { } else if (extension.compare("geom") == 0) {
// geometry shader // geometry shader
resource = m_pSourceManager->load(name, extension, data); resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("comp") == 0) { } else if (extension.compare("comp") == 0) {
// compute shader // compute shader
resource = m_pSourceManager->load(name, extension, data); resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("mesh") == 0) { } else if (extension.compare("mesh") == 0) {
// mesh shader // mesh shader
resource = m_pSourceManager->load(name, extension, data); resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("task") == 0) { } else if (extension.compare("task") == 0) {
// task shader // task shader
resource = m_pSourceManager->load(name, extension, data); resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("rgen") == 0) { } else if (extension.compare("rgen") == 0) {
// ray generation shader // ray generation shader
resource = m_pSourceManager->load(name, extension, data); resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("rint") == 0) { } else if (extension.compare("rint") == 0) {
// ray intersection shader // ray intersection shader
resource = m_pSourceManager->load(name, extension, data); resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("rahit") == 0) { } else if (extension.compare("rahit") == 0) {
// ray any hit shader // ray any hit shader
resource = m_pSourceManager->load(name, extension, data); resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("rchit") == 0) { } else if (extension.compare("rchit") == 0) {
// ray closest hit shader // ray closest hit shader
resource = m_pSourceManager->load(name, extension, data); resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("rmiss") == 0) { } else if (extension.compare("rmiss") == 0) {
// ray miss shader // ray miss shader
resource = m_pSourceManager->load(name, extension, data); resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("rcall") == 0) { } else if (extension.compare("rcall") == 0) {
// ray callable shader // ray callable shader
resource = m_pSourceManager->load(name, extension, data); resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("glsl") == 0) { } else if (extension.compare("glsl") == 0) {
// glsl included by other shaders // glsl included by other shaders
resource = m_pSourceManager->load(name, extension, data); resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("options") == 0) { } else if (extension.compare("options") == 0) {
// shader pre-processor options definition file // shader pre-processor options definition file
resource = m_pSourceManager->load(name, extension, data); resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("mtl") == 0) { } else if (extension.compare("mtl") == 0) {
resource = m_pMaterialManager->load(name.c_str(), data); resource = m_pMaterialManager->load(name.c_str(), data);
} else if(extension.compare("mp3") == 0) { } else if (extension.compare("mp3") == 0) {
resource = m_pSoundManager->load(name.c_str(), extension, data); resource = m_pSoundManager->load(name.c_str(), extension, data);
} else if(extension.compare("wav") == 0) { } else if (extension.compare("wav") == 0) {
resource = m_pSoundManager->load(name.c_str(), extension, data); resource = m_pSoundManager->load(name.c_str(), extension, data);
} else if(extension.compare("aac") == 0) { } else if (extension.compare("aac") == 0) {
resource = m_pSoundManager->load(name.c_str(), extension, data); resource = m_pSoundManager->load(name.c_str(), extension, data);
} else if(extension.compare("obj") == 0) { } else if (extension.compare("obj") == 0) {
resource = KRResource::LoadObj(*this, file_name); resource = KRResource::LoadObj(*this, file_name);
#if !TARGET_OS_IPHONE #if !TARGET_OS_IPHONE
/* /*
// FINDME, TODO, HACK! - Uncomment // FINDME, TODO, HACK! - Uncomment
} else if(extension.compare("fbx") == 0) { } else if(extension.compare("fbx") == 0) {
resource = KRResource::LoadFbx(*this, file_name); resource = KRResource::LoadFbx(*this, file_name);
*/ */
} else if(extension.compare("blend") == 0) { } else if (extension.compare("blend") == 0) {
resource = KRResource::LoadBlenderScene(*this, file_name); resource = KRResource::LoadBlenderScene(*this, file_name);
#endif #endif
} else { } else {
resource = m_pUnknownManager->load(name, extension, data); resource = m_pUnknownManager->load(name, extension, data);
} }
return resource; return resource;
} }
KrResult KRContext::loadResource(const KrLoadResourceInfo* loadResourceInfo) { KrResult KRContext::loadResource(const KrLoadResourceInfo* loadResourceInfo)
if (loadResourceInfo->resourceHandle < 0 || loadResourceInfo->resourceHandle >= m_resourceMapSize) { {
return KR_ERROR_OUT_OF_BOUNDS; if (loadResourceInfo->resourceHandle < 0 || loadResourceInfo->resourceHandle >= m_resourceMapSize) {
} return KR_ERROR_OUT_OF_BOUNDS;
KRDataBlock *data = new KRDataBlock(); }
if(!data->load(loadResourceInfo->pResourcePath)) { KRDataBlock* data = new KRDataBlock();
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "KRContext::loadResource - Failed to open file: %s", loadResourceInfo->pResourcePath); if (!data->load(loadResourceInfo->pResourcePath)) {
delete data; KRContext::Log(KRContext::LOG_LEVEL_ERROR, "KRContext::loadResource - Failed to open file: %s", loadResourceInfo->pResourcePath);
return KR_ERROR_UNEXPECTED; delete data;
} return KR_ERROR_UNEXPECTED;
}
KRResource *resource = loadResource(loadResourceInfo->pResourcePath, data); KRResource* resource = loadResource(loadResourceInfo->pResourcePath, data);
m_resourceMap[loadResourceInfo->resourceHandle] = resource; m_resourceMap[loadResourceInfo->resourceHandle] = resource;
return KR_SUCCESS; return KR_SUCCESS;
} }
KrResult KRContext::unloadResource(const KrUnloadResourceInfo* unloadResourceInfo) KrResult KRContext::unloadResource(const KrUnloadResourceInfo* unloadResourceInfo)
@@ -472,7 +489,7 @@ KrResult KRContext::getResourceData(const KrGetResourceDataInfo* getResourceData
result.result = KR_ERROR_UNEXPECTED; result.result = KR_ERROR_UNEXPECTED;
callback(result); callback(result);
} }
return KR_SUCCESS; return KR_SUCCESS;
} }
@@ -574,69 +591,69 @@ KrResult KRContext::saveResource(const KrSaveResourceInfo* saveResourceInfo)
void KRContext::startFrame(float deltaTime) void KRContext::startFrame(float deltaTime)
{ {
m_pTextureManager->startFrame(deltaTime); m_pTextureManager->startFrame(deltaTime);
m_pAnimationManager->startFrame(deltaTime); m_pAnimationManager->startFrame(deltaTime);
m_pSoundManager->startFrame(deltaTime); m_pSoundManager->startFrame(deltaTime);
m_pMeshManager->startFrame(deltaTime); m_pMeshManager->startFrame(deltaTime);
} }
void KRContext::endFrame(float deltaTime) void KRContext::endFrame(float deltaTime)
{ {
m_pTextureManager->endFrame(deltaTime); m_pTextureManager->endFrame(deltaTime);
m_pAnimationManager->endFrame(deltaTime); m_pAnimationManager->endFrame(deltaTime);
m_pMeshManager->endFrame(deltaTime); m_pMeshManager->endFrame(deltaTime);
m_current_frame++; m_current_frame++;
m_absolute_time += deltaTime; m_absolute_time += deltaTime;
} }
long KRContext::getCurrentFrame() const long KRContext::getCurrentFrame() const
{ {
return m_current_frame; return m_current_frame;
} }
long KRContext::getLastFullyStreamedFrame() const long KRContext::getLastFullyStreamedFrame() const
{ {
return m_last_fully_streamed_frame; return m_last_fully_streamed_frame;
} }
float KRContext::getAbsoluteTime() const float KRContext::getAbsoluteTime() const
{ {
return m_absolute_time; return m_absolute_time;
} }
long KRContext::getAbsoluteTimeMilliseconds() long KRContext::getAbsoluteTimeMilliseconds()
{ {
#if defined(ANDROID) #if defined(ANDROID)
return std::chrono::duration_cast< std::chrono::milliseconds >( return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count(); std::chrono::system_clock::now().time_since_epoch()).count();
#elif defined(__APPLE__) #elif defined(__APPLE__)
return (long)(mach_absolute_time() / 1000 * m_timebase_info.numer / m_timebase_info.denom); // Division done first to avoid potential overflow return (long)(mach_absolute_time() / 1000 * m_timebase_info.numer / m_timebase_info.denom); // Division done first to avoid potential overflow
#else #else
return (long)GetTickCount64(); return (long)GetTickCount64();
#endif #endif
} }
#if TARGET_OS_IPHONE || TARGET_OS_MAC #if TARGET_OS_IPHONE || TARGET_OS_MAC
void KRContext::getMemoryStats(long &free_memory) void KRContext::getMemoryStats(long& free_memory)
{ {
free_memory = 0; free_memory = 0;
mach_port_t host_port = mach_host_self(); mach_port_t host_port = mach_host_self();
mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
vm_size_t pagesize = 0; vm_size_t pagesize = 0;
vm_statistics_data_t vm_stat; vm_statistics_data_t vm_stat;
// int total_ram = 256 * 1024 * 1024; // int total_ram = 256 * 1024 * 1024;
if(host_page_size(host_port, &pagesize) != KERN_SUCCESS) { if (host_page_size(host_port, &pagesize) != KERN_SUCCESS) {
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Could not get VM page size."); KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Could not get VM page size.");
} else if(host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) { } else if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) {
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Could not get VM stats."); KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Could not get VM stats.");
} else { } else {
// total_ram = (vm_stat.wire_count + vm_stat.active_count + vm_stat.inactive_count + vm_stat.free_count) * pagesize; // total_ram = (vm_stat.wire_count + vm_stat.active_count + vm_stat.inactive_count + vm_stat.free_count) * pagesize;
free_memory = (vm_stat.free_count + vm_stat.inactive_count) * pagesize; free_memory = (vm_stat.free_count + vm_stat.inactive_count) * pagesize;
} }
} }
#endif #endif
@@ -823,7 +840,7 @@ KrResult KRContext::createWindowSurface(const KrCreateWindowSurfaceInfo* createW
if (result != KR_SUCCESS) { if (result != KR_SUCCESS) {
return result; return result;
} }
m_surfaceHandleMap.insert(std::pair<KrSurfaceMapIndex, KrSurfaceHandle>(createWindowSurfaceInfo->surfaceHandle, surfaceHandle)); m_surfaceHandleMap.insert(std::pair<KrSurfaceMapIndex, KrSurfaceHandle>(createWindowSurfaceInfo->surfaceHandle, surfaceHandle));
return KR_SUCCESS; return KR_SUCCESS;
@@ -848,6 +865,6 @@ KrResult KRContext::deleteWindowSurface(const KrDeleteWindowSurfaceInfo* deleteW
} }
KrSurfaceHandle surfaceHandle = (*handleItr).second; KrSurfaceHandle surfaceHandle = (*handleItr).second;
m_surfaceHandleMap.erase(handleItr); m_surfaceHandleMap.erase(handleItr);
return m_surfaceManager->destroy(surfaceHandle); return m_surfaceManager->destroy(surfaceHandle);
} }

View File

@@ -54,141 +54,143 @@ class KRStreamerThread;
class KRDeviceManager; class KRDeviceManager;
class KRSurfaceManager; class KRSurfaceManager;
class KRContext { class KRContext
{
public: public:
static int KRENGINE_MAX_PIPELINE_HANDLES; static int KRENGINE_MAX_PIPELINE_HANDLES;
static int KRENGINE_GPU_MEM_MAX; static int KRENGINE_GPU_MEM_MAX;
static int KRENGINE_GPU_MEM_TARGET; static int KRENGINE_GPU_MEM_TARGET;
static int KRENGINE_MAX_TEXTURE_DIM; static int KRENGINE_MAX_TEXTURE_DIM;
static int KRENGINE_MIN_TEXTURE_DIM; static int KRENGINE_MIN_TEXTURE_DIM;
static int KRENGINE_PRESTREAM_DISTANCE; static int KRENGINE_PRESTREAM_DISTANCE;
static int KRENGINE_SYS_ALLOCATION_GRANULARITY; static int KRENGINE_SYS_ALLOCATION_GRANULARITY;
static int KRENGINE_SYS_PAGE_SIZE; static int KRENGINE_SYS_PAGE_SIZE;
KRContext(const KrInitializeInfo* initializeInfo);
~KRContext();
KrResult createWindowSurface(const KrCreateWindowSurfaceInfo* createWindowSurfaceInfo);
KrResult deleteWindowSurface(const KrDeleteWindowSurfaceInfo* deleteWindowSurfaceInfo);
KrResult createBundle(const KrCreateBundleInfo* createBundleInfo);
KrResult moveToBundle(const KrMoveToBundleInfo* moveToBundleInfo);
KrResult loadResource(const KrLoadResourceInfo* loadResourceInfo);
KrResult unloadResource(const KrUnloadResourceInfo* unloadResourceInfo);
KrResult getResourceData(const KrGetResourceDataInfo* getResourceDataInfo, KrGetResourceDataCallback callback);
KrResult mapResource(const KrMapResourceInfo* mapResourceInfo);
KrResult unmapResource(const KrUnmapResourceInfo* unmapResourceInfo);
KrResult saveResource(const KrSaveResourceInfo* saveResourceInfo);
KrResult compileAllShaders(const KrCompileAllShadersInfo* pCompileAllShadersInfo);
KrResult createScene(const KrCreateSceneInfo* createSceneInfo);
KrResult findNodeByName(const KrFindNodeByNameInfo* pFindNodeByNameInfo);
KrResult findAdjacentNodes(const KrFindAdjacentNodesInfo* pFindAdjacentNodesInfo);
KrResult setNodeLocalTransform(const KrSetNodeLocalTransformInfo* pSetNodeLocalTransform);
KrResult setNodeWorldTransform(const KrSetNodeWorldTransformInfo* pSetNodeWorldTransform);
KrResult deleteNode(const KrDeleteNodeInfo* pDeleteNodeInfo);
KrResult deleteNodeChildren(const KrDeleteNodeChildrenInfo* pDeleteNodeChildrenInfo);
KrResult appendBeforeNode(const KrAppendBeforeNodeInfo* pAppendBeforeNodeInfo);
KrResult appendAfterNode(const KrAppendAfterNodeInfo* pAppendAfterNodeInfo);
KrResult appendFirstChildNode(const KrAppendFirstChildNodeInfo* pAppendFirstChildNodeInfo);
KrResult appendLastChildNode(const KrAppendLastChildNodeInfo* pAppendLastChildNodeInfo);
KrResult updateNode(const KrUpdateNodeInfo* pUpdateNodeInfo);
KRResource* loadResource(const std::string &file_name, KRDataBlock *data); KRContext(const KrInitializeInfo* initializeInfo);
~KRContext();
KRBundleManager *getBundleManager(); KrResult createWindowSurface(const KrCreateWindowSurfaceInfo* createWindowSurfaceInfo);
KRSceneManager *getSceneManager(); KrResult deleteWindowSurface(const KrDeleteWindowSurfaceInfo* deleteWindowSurfaceInfo);
KRTextureManager *getTextureManager();
KRMaterialManager *getMaterialManager(); KrResult createBundle(const KrCreateBundleInfo* createBundleInfo);
KRPipelineManager *getPipelineManager(); KrResult moveToBundle(const KrMoveToBundleInfo* moveToBundleInfo);
KRMeshManager *getMeshManager(); KrResult loadResource(const KrLoadResourceInfo* loadResourceInfo);
KRAnimationManager *getAnimationManager(); KrResult unloadResource(const KrUnloadResourceInfo* unloadResourceInfo);
KRAnimationCurveManager *getAnimationCurveManager(); KrResult getResourceData(const KrGetResourceDataInfo* getResourceDataInfo, KrGetResourceDataCallback callback);
KRAudioManager *getAudioManager(); KrResult mapResource(const KrMapResourceInfo* mapResourceInfo);
KRUnknownManager *getUnknownManager(); KrResult unmapResource(const KrUnmapResourceInfo* unmapResourceInfo);
KRShaderManager *getShaderManager(); KrResult saveResource(const KrSaveResourceInfo* saveResourceInfo);
KRSourceManager *getSourceManager();
KRSurfaceManager* getSurfaceManager(); KrResult compileAllShaders(const KrCompileAllShadersInfo* pCompileAllShadersInfo);
KRDeviceManager* getDeviceManager();
KrResult createScene(const KrCreateSceneInfo* createSceneInfo);
void startFrame(float deltaTime); KrResult findNodeByName(const KrFindNodeByNameInfo* pFindNodeByNameInfo);
void endFrame(float deltaTime); KrResult findAdjacentNodes(const KrFindAdjacentNodesInfo* pFindAdjacentNodesInfo);
KrResult setNodeLocalTransform(const KrSetNodeLocalTransformInfo* pSetNodeLocalTransform);
long getCurrentFrame() const; KrResult setNodeWorldTransform(const KrSetNodeWorldTransformInfo* pSetNodeWorldTransform);
long getLastFullyStreamedFrame() const; KrResult deleteNode(const KrDeleteNodeInfo* pDeleteNodeInfo);
float getAbsoluteTime() const; KrResult deleteNodeChildren(const KrDeleteNodeChildrenInfo* pDeleteNodeChildrenInfo);
KrResult appendBeforeNode(const KrAppendBeforeNodeInfo* pAppendBeforeNodeInfo);
long getAbsoluteTimeMilliseconds(); KrResult appendAfterNode(const KrAppendAfterNodeInfo* pAppendAfterNodeInfo);
KrResult appendFirstChildNode(const KrAppendFirstChildNodeInfo* pAppendFirstChildNodeInfo);
std::vector<KRResource *> getResources(); KrResult appendLastChildNode(const KrAppendLastChildNodeInfo* pAppendLastChildNodeInfo);
KrResult updateNode(const KrUpdateNodeInfo* pUpdateNodeInfo);
KRResource* loadResource(const std::string& file_name, KRDataBlock* data);
KRBundleManager* getBundleManager();
KRSceneManager* getSceneManager();
KRTextureManager* getTextureManager();
KRMaterialManager* getMaterialManager();
KRPipelineManager* getPipelineManager();
KRMeshManager* getMeshManager();
KRAnimationManager* getAnimationManager();
KRAnimationCurveManager* getAnimationCurveManager();
KRAudioManager* getAudioManager();
KRUnknownManager* getUnknownManager();
KRShaderManager* getShaderManager();
KRSourceManager* getSourceManager();
KRSurfaceManager* getSurfaceManager();
KRDeviceManager* getDeviceManager();
void startFrame(float deltaTime);
void endFrame(float deltaTime);
long getCurrentFrame() const;
long getLastFullyStreamedFrame() const;
float getAbsoluteTime() const;
long getAbsoluteTimeMilliseconds();
std::vector<KRResource*> getResources();
#if TARGET_OS_IPHONE || TARGET_OS_MAC #if TARGET_OS_IPHONE || TARGET_OS_MAC
// XXX This doesn't belong here, and might not actually be needed at all // XXX This doesn't belong here, and might not actually be needed at all
void getMemoryStats(long &free_memory); void getMemoryStats(long& free_memory);
#endif #endif
typedef enum { typedef enum
LOG_LEVEL_INFORMATION, {
LOG_LEVEL_WARNING, LOG_LEVEL_INFORMATION,
LOG_LEVEL_ERROR LOG_LEVEL_WARNING,
} log_level; LOG_LEVEL_ERROR
} log_level;
typedef void log_callback(void *userdata, const std::string &message, log_level level);
static void SetLogCallback(log_callback *log_callback, void *user_data);
static void Log(log_level level, const std::string message_format, ...);
void doStreaming();
void receivedMemoryWarning();
static std::mutex g_SurfaceInfoMutex; typedef void log_callback(void* userdata, const std::string& message, log_level level);
static std::mutex g_DeviceInfoMutex;
void addResource(KRResource* resource, const std::string& name); static void SetLogCallback(log_callback* log_callback, void* user_data);
void removeResource(KRResource* resource); static void Log(log_level level, const std::string message_format, ...);
void doStreaming();
void receivedMemoryWarning();
static std::mutex g_SurfaceInfoMutex;
static std::mutex g_DeviceInfoMutex;
void addResource(KRResource* resource, const std::string& name);
void removeResource(KRResource* resource);
private: private:
std::unique_ptr<KRBundleManager> m_pBundleManager; std::unique_ptr<KRBundleManager> m_pBundleManager;
std::unique_ptr<KRSceneManager> m_pSceneManager; std::unique_ptr<KRSceneManager> m_pSceneManager;
std::unique_ptr<KRTextureManager> m_pTextureManager; std::unique_ptr<KRTextureManager> m_pTextureManager;
std::unique_ptr<KRMaterialManager> m_pMaterialManager; std::unique_ptr<KRMaterialManager> m_pMaterialManager;
std::unique_ptr<KRPipelineManager> m_pPipelineManager; std::unique_ptr<KRPipelineManager> m_pPipelineManager;
std::unique_ptr<KRMeshManager> m_pMeshManager; std::unique_ptr<KRMeshManager> m_pMeshManager;
std::unique_ptr<KRAnimationManager> m_pAnimationManager; std::unique_ptr<KRAnimationManager> m_pAnimationManager;
std::unique_ptr<KRAnimationCurveManager> m_pAnimationCurveManager; std::unique_ptr<KRAnimationCurveManager> m_pAnimationCurveManager;
std::unique_ptr<KRAudioManager> m_pSoundManager; std::unique_ptr<KRAudioManager> m_pSoundManager;
std::unique_ptr<KRUnknownManager> m_pUnknownManager; std::unique_ptr<KRUnknownManager> m_pUnknownManager;
std::unique_ptr<KRShaderManager> m_pShaderManager; std::unique_ptr<KRShaderManager> m_pShaderManager;
std::unique_ptr<KRSourceManager> m_pSourceManager; std::unique_ptr<KRSourceManager> m_pSourceManager;
std::unique_ptr<KRDeviceManager> m_deviceManager; std::unique_ptr<KRDeviceManager> m_deviceManager;
std::unique_ptr<KRSurfaceManager> m_surfaceManager; std::unique_ptr<KRSurfaceManager> m_surfaceManager;
KRResource** m_resourceMap;
size_t m_resourceMapSize;
long m_current_frame; // TODO - Does this need to be atomic?
long m_last_memory_warning_frame; // TODO - Does this need to be atomic?
long m_last_fully_streamed_frame; // TODO - Does this need to be atomic?
float m_absolute_time;
KRResource** m_resourceMap;
size_t m_resourceMapSize;
long m_current_frame; // TODO - Does this need to be atomic?
long m_last_memory_warning_frame; // TODO - Does this need to be atomic?
long m_last_fully_streamed_frame; // TODO - Does this need to be atomic?
float m_absolute_time;
#ifdef __APPLE__ #ifdef __APPLE__
mach_timebase_info_data_t m_timebase_info; mach_timebase_info_data_t m_timebase_info;
#endif #endif
// m_streamingEnabled is set to true once all managers are loaded // m_streamingEnabled is set to true once all managers are loaded
std::atomic<bool> m_streamingEnabled; std::atomic<bool> m_streamingEnabled;
static log_callback *s_log_callback;
static void *s_log_callback_user_data;
unordered_multimap<std::string, KRResource*> m_resources;
static log_callback* s_log_callback;
std::unique_ptr<KRStreamerThread> m_streamerThread; static void* s_log_callback_user_data;
std::unique_ptr<KRPresentationThread> m_presentationThread;
unordered_map<KrSurfaceMapIndex, KrSurfaceHandle> m_surfaceHandleMap; unordered_multimap<std::string, KRResource*> m_resources;
std::unique_ptr<KRStreamerThread> m_streamerThread;
std::unique_ptr<KRPresentationThread> m_presentationThread;
unordered_map<KrSurfaceMapIndex, KrSurfaceHandle> m_surfaceHandleMap;
}; };

View File

@@ -31,17 +31,17 @@
#include "KRContextObject.h" #include "KRContextObject.h"
KRContextObject::KRContextObject(KRContext &context) KRContextObject::KRContextObject(KRContext& context)
{ {
m_pContext = &context; m_pContext = &context;
} }
KRContextObject::~KRContextObject() KRContextObject::~KRContextObject()
{ {
} }
KRContext &KRContextObject::getContext() const KRContext& KRContextObject::getContext() const
{ {
return *m_pContext; return *m_pContext;
} }

View File

@@ -33,13 +33,14 @@
class KRContext; class KRContext;
class KRContextObject { class KRContextObject
{
public: public:
KRContextObject(KRContext &context); KRContextObject(KRContext& context);
~KRContextObject(); ~KRContextObject();
KRContext &getContext() const; KRContext& getContext() const;
protected: protected:
KRContext *m_pContext; KRContext* m_pContext;
}; };

View File

@@ -39,53 +39,56 @@ namespace KRDSP {
#define KRDSP_APPLE_VDSP #define KRDSP_APPLE_VDSP
#include <Accelerate/Accelerate.h> #include <Accelerate/Accelerate.h>
#else #else
// Slow, but portable fallback implementation // Slow, but portable fallback implementation
#define KRDSP_SLOW #define KRDSP_SLOW
#endif #endif
#if defined(KRDSP_APPLE_VDSP) #if defined(KRDSP_APPLE_VDSP)
// Apple vDSP // Apple vDSP
typedef DSPSplitComplex SplitComplex; typedef DSPSplitComplex SplitComplex;
struct FFTWorkspace { struct FFTWorkspace
FFTSetup setup; {
FFTSetup setup;
void create(size_t length); void create(size_t length);
void destroy(); void destroy();
FFTWorkspace(); FFTWorkspace();
~FFTWorkspace(); ~FFTWorkspace();
}; };
#elif defined(KRDSP_SLOW) #elif defined(KRDSP_SLOW)
typedef struct { typedef struct
float *realp; {
float *imagp; float* realp;
} SplitComplex; float* imagp;
} SplitComplex;
struct FFTWorkspace { struct FFTWorkspace
float *sin_table; {
float *cos_table; float* sin_table;
float* cos_table;
void create(size_t length); void create(size_t length);
void destroy(); void destroy();
FFTWorkspace(); FFTWorkspace();
~FFTWorkspace(); ~FFTWorkspace();
}; };
#else #else
#error Not Implemented #error Not Implemented
#endif #endif
void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count); void FFTForward(const FFTWorkspace& workspace, SplitComplex* src, size_t count);
void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count); void FFTInverse(const FFTWorkspace& workspace, SplitComplex* src, size_t count);
void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destStride, size_t count); void Int16ToFloat(const short* src, size_t srcStride, float* dest, size_t destStride, size_t count);
void Scale(float *buffer, float scale, size_t count); void Scale(float* buffer, float scale, size_t count);
void ScaleCopy(const float *src, float scale, float *dest, size_t count); void ScaleCopy(const float* src, float scale, float* dest, size_t count);
void ScaleCopy(const SplitComplex *src, float scale, SplitComplex *dest, size_t count); void ScaleCopy(const SplitComplex* src, float scale, SplitComplex* dest, size_t count);
void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count); void ScaleRamp(float* buffer, float scaleStart, float scaleStep, size_t count);
void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t buffer2Stride, size_t count); void Accumulate(float* buffer, size_t bufferStride, const float* buffer2, size_t buffer2Stride, size_t count);
void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count); void Accumulate(SplitComplex* buffer, const SplitComplex* buffer2, size_t count);
void Multiply(const SplitComplex *a, const SplitComplex *b, SplitComplex *c, size_t count); void Multiply(const SplitComplex* a, const SplitComplex* b, SplitComplex* c, size_t count);
} // namespace KRDSP } // namespace KRDSP

View File

@@ -72,7 +72,7 @@ void FFTWorkspace::destroy()
} }
} }
void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count) void FFTForward(const FFTWorkspace& workspace, SplitComplex* src, size_t count)
{ {
// Radix-2 Decimation in Time FFT Algorithm // Radix-2 Decimation in Time FFT Algorithm
// http://en.dsplib.org/content/fft_dec_in_time.html // http://en.dsplib.org/content/fft_dec_in_time.html
@@ -119,7 +119,7 @@ void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
} }
} }
void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count) void FFTInverse(const FFTWorkspace& workspace, SplitComplex* src, size_t count)
{ {
SplitComplex swapped; SplitComplex swapped;
swapped.imagp = src->realp; swapped.imagp = src->realp;
@@ -127,10 +127,10 @@ void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
FFTForward(workspace, &swapped, count); FFTForward(workspace, &swapped, count);
} }
void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destStride, size_t count) void Int16ToFloat(const short* src, size_t srcStride, float* dest, size_t destStride, size_t count)
{ {
const short *r = src; const short* r = src;
float *w = dest; float* w = dest;
while (w < dest + destStride * count) { while (w < dest + destStride * count) {
*w = (float)*r; *w = (float)*r;
r += srcStride; r += srcStride;
@@ -138,19 +138,19 @@ void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destSt
} }
} }
void Scale(float *buffer, float scale, size_t count) void Scale(float* buffer, float scale, size_t count)
{ {
float *w = buffer; float* w = buffer;
while (w < buffer + count) { while (w < buffer + count) {
*w *= scale; *w *= scale;
w++; w++;
} }
} }
void ScaleCopy(const float *src, float scale, float *dest, size_t count) void ScaleCopy(const float* src, float scale, float* dest, size_t count)
{ {
const float *r = src; const float* r = src;
float *w = dest; float* w = dest;
while (w < dest + count) { while (w < dest + count) {
*w = *r * scale; *w = *r * scale;
w++; w++;
@@ -158,15 +158,15 @@ void ScaleCopy(const float *src, float scale, float *dest, size_t count)
} }
} }
void ScaleCopy(const SplitComplex *src, float scale, SplitComplex *dest, size_t count) void ScaleCopy(const SplitComplex* src, float scale, SplitComplex* dest, size_t count)
{ {
ScaleCopy(src->realp, scale, dest->realp, count); ScaleCopy(src->realp, scale, dest->realp, count);
ScaleCopy(src->imagp, scale, dest->imagp, count); ScaleCopy(src->imagp, scale, dest->imagp, count);
} }
void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count) void ScaleRamp(float* buffer, float scaleStart, float scaleStep, size_t count)
{ {
float *w = buffer; float* w = buffer;
float s = scaleStart; float s = scaleStart;
while (w < buffer + count) { while (w < buffer + count) {
*w *= s; *w *= s;
@@ -175,10 +175,10 @@ void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count)
} }
} }
void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t buffer2Stride, size_t count) void Accumulate(float* buffer, size_t bufferStride, const float* buffer2, size_t buffer2Stride, size_t count)
{ {
float *w = buffer; float* w = buffer;
const float *r = buffer2; const float* r = buffer2;
while (w < buffer + bufferStride * count) { while (w < buffer + bufferStride * count) {
*w *= *r; *w *= *r;
w += bufferStride; w += bufferStride;
@@ -186,7 +186,7 @@ void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t
} }
} }
void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count) void Accumulate(SplitComplex* buffer, const SplitComplex* buffer2, size_t count)
{ {
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
buffer->imagp[i] += buffer2->imagp[i]; buffer->imagp[i] += buffer2->imagp[i];
@@ -194,7 +194,7 @@ void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count)
} }
} }
void Multiply(const SplitComplex *a, const SplitComplex *b, SplitComplex *c, size_t count) void Multiply(const SplitComplex* a, const SplitComplex* b, SplitComplex* c, size_t count)
{ {
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
c->realp[i] = a->realp[i] * b->realp[i] - a->imagp[i] * b->imagp[i]; c->realp[i] = a->realp[i] * b->realp[i] - a->imagp[i] * b->imagp[i];

View File

@@ -62,54 +62,54 @@ void FFTWorkspace::destroy()
} }
} }
void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count) void FFTForward(const FFTWorkspace& workspace, SplitComplex* src, size_t count)
{ {
vDSP_fft_zip(workspace.setup, src, 1, count, kFFTDirection_Forward); vDSP_fft_zip(workspace.setup, src, 1, count, kFFTDirection_Forward);
} }
void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count) void FFTInverse(const FFTWorkspace& workspace, SplitComplex* src, size_t count)
{ {
vDSP_fft_zip(workspace.setup, src, 1, count, kFFTDirection_Inverse); vDSP_fft_zip(workspace.setup, src, 1, count, kFFTDirection_Inverse);
} }
void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destStride, size_t count) void Int16ToFloat(const short* src, size_t srcStride, float* dest, size_t destStride, size_t count)
{ {
vDSP_vflt16(src, srcStride, dest, destStride, count); vDSP_vflt16(src, srcStride, dest, destStride, count);
} }
void Scale(float *buffer, float scale, size_t count) void Scale(float* buffer, float scale, size_t count)
{ {
vDSP_vsmul(buffer, 1, &scale, buffer, 1, count); vDSP_vsmul(buffer, 1, &scale, buffer, 1, count);
} }
void ScaleCopy(const float *src, float scale, float *dest, size_t count) void ScaleCopy(const float* src, float scale, float* dest, size_t count)
{ {
vDSP_vsmul(src, 1, &scale, dest, 1, count); vDSP_vsmul(src, 1, &scale, dest, 1, count);
} }
void ScaleCopy(const SplitComplex *src, float scale, SplitComplex *dest, size_t count) void ScaleCopy(const SplitComplex* src, float scale, SplitComplex* dest, size_t count)
{ {
ScaleCopy(src->realp, scale, dest->realp, count); ScaleCopy(src->realp, scale, dest->realp, count);
ScaleCopy(src->imagp, scale, dest->imagp, count); ScaleCopy(src->imagp, scale, dest->imagp, count);
} }
void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count) void ScaleRamp(float* buffer, float scaleStart, float scaleStep, size_t count)
{ {
vDSP_vrampmul(buffer, 1, &scaleStart, &scaleStep, buffer, 1, count); vDSP_vrampmul(buffer, 1, &scaleStart, &scaleStep, buffer, 1, count);
} }
void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t buffer2Stride, size_t count) void Accumulate(float* buffer, size_t bufferStride, const float* buffer2, size_t buffer2Stride, size_t count)
{ {
vDSP_vadd(buffer, bufferStride, buffer2, buffer2Stride, buffer, bufferStride, count); vDSP_vadd(buffer, bufferStride, buffer2, buffer2Stride, buffer, bufferStride, count);
} }
void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count) void Accumulate(SplitComplex* buffer, const SplitComplex* buffer2, size_t count)
{ {
vDSP_zvadd(buffer2, 1, buffer, 1, buffer, 1, count); vDSP_zvadd(buffer2, 1, buffer, 1, buffer, 1, count);
} }
void Multiply(const SplitComplex *a, const SplitComplex *b, SplitComplex *c, size_t count) void Multiply(const SplitComplex* a, const SplitComplex* b, SplitComplex* c, size_t count)
{ {
vDSP_zvmul(a, 1, b, 1, c, 1, count, 1); vDSP_zvmul(a, 1, b, 1, c, 1, count, 1);
} }

View File

@@ -47,236 +47,245 @@ int m_mapCount = 0;
size_t m_mapSize = 0; size_t m_mapSize = 0;
size_t m_mapOverhead = 0; size_t m_mapOverhead = 0;
KRDataBlock::KRDataBlock() { KRDataBlock::KRDataBlock()
m_data = NULL; {
m_data_size = 0; m_data = NULL;
m_data_offset = 0; m_data_size = 0;
m_data_offset = 0;
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
m_hPackFile = INVALID_HANDLE_VALUE; m_hPackFile = INVALID_HANDLE_VALUE;
m_hFileMapping = NULL; m_hFileMapping = NULL;
#elif defined(__APPLE__) #elif defined(__APPLE__)
m_fdPackFile = 0; m_fdPackFile = 0;
#endif #endif
m_fileName = ""; m_fileName = "";
m_mmapData = NULL; m_mmapData = NULL;
m_fileOwnerDataBlock = NULL; m_fileOwnerDataBlock = NULL;
m_bMalloced = false; m_bMalloced = false;
m_lockCount = 0; m_lockCount = 0;
m_bReadOnly = false; m_bReadOnly = false;
} }
KRDataBlock::KRDataBlock(void *data, size_t size) { KRDataBlock::KRDataBlock(void* data, size_t size)
m_data = NULL; {
m_data_size = 0; m_data = NULL;
m_data_offset = 0; m_data_size = 0;
m_data_offset = 0;
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
m_hPackFile = INVALID_HANDLE_VALUE; m_hPackFile = INVALID_HANDLE_VALUE;
m_hFileMapping = NULL; m_hFileMapping = NULL;
#elif defined(__APPLE__) #elif defined(__APPLE__)
m_fdPackFile = 0; m_fdPackFile = 0;
#endif #endif
m_fileName = ""; m_fileName = "";
m_mmapData = NULL; m_mmapData = NULL;
m_fileOwnerDataBlock = NULL; m_fileOwnerDataBlock = NULL;
m_bMalloced = false; m_bMalloced = false;
m_lockCount = 0; m_lockCount = 0;
m_bReadOnly = false; m_bReadOnly = false;
load(data, size); load(data, size);
} }
KRDataBlock::~KRDataBlock() { KRDataBlock::~KRDataBlock()
unload(); {
unload();
} }
// Unload a file, releasing any mmap'ed file handles or malloc'ed ram that was in use // Unload a file, releasing any mmap'ed file handles or malloc'ed ram that was in use
void KRDataBlock::unload() void KRDataBlock::unload()
{ {
assert(m_lockCount == 0); assert(m_lockCount == 0);
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
if (m_hPackFile != INVALID_HANDLE_VALUE) { if (m_hPackFile != INVALID_HANDLE_VALUE) {
// Memory mapped file // Memory mapped file
if (m_fileOwnerDataBlock == this) { if (m_fileOwnerDataBlock == this) {
CloseHandle(m_hPackFile); CloseHandle(m_hPackFile);
}
m_hPackFile = INVALID_HANDLE_VALUE;
} }
m_hPackFile = INVALID_HANDLE_VALUE;
}
#elif defined(__APPLE__) #elif defined(__APPLE__)
if(m_fdPackFile) { if (m_fdPackFile) {
// Memory mapped file // Memory mapped file
if(m_fileOwnerDataBlock == this) { if (m_fileOwnerDataBlock == this) {
close(m_fdPackFile); close(m_fdPackFile);
}
m_fdPackFile = 0;
} }
m_fdPackFile = 0;
}
#endif #endif
if(m_data != NULL && m_bMalloced) { if (m_data != NULL && m_bMalloced) {
// Malloc'ed data // Malloc'ed data
free(m_data); free(m_data);
} }
m_bMalloced = false; m_bMalloced = false;
m_data = NULL; m_data = NULL;
m_data_size = 0; m_data_size = 0;
m_data_offset = 0; m_data_offset = 0;
m_fileName = ""; m_fileName = "";
m_mmapData = NULL; m_mmapData = NULL;
m_fileOwnerDataBlock = NULL; m_fileOwnerDataBlock = NULL;
m_bReadOnly = false; m_bReadOnly = false;
} }
// Encapsulate a pointer. Note - The pointer will not be free'ed // Encapsulate a pointer. Note - The pointer will not be free'ed
bool KRDataBlock::load(void *data, size_t size) bool KRDataBlock::load(void* data, size_t size)
{ {
unload(); unload();
m_data = data; m_data = data;
m_data_size = size; m_data_size = size;
m_data_offset = 0; m_data_offset = 0;
m_bReadOnly = false; m_bReadOnly = false;
return true; return true;
} }
// Load a file into memory using mmap. The data pointer will be protected as read-only until append() or expand() is called // Load a file into memory using mmap. The data pointer will be protected as read-only until append() or expand() is called
bool KRDataBlock::load(const std::string &path) bool KRDataBlock::load(const std::string& path)
{ {
bool success = false; bool success = false;
unload(); unload();
m_bReadOnly = true; m_bReadOnly = true;
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
m_hPackFile = CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); m_hPackFile = CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(m_hPackFile != INVALID_HANDLE_VALUE) { if (m_hPackFile != INVALID_HANDLE_VALUE) {
m_fileOwnerDataBlock = this; m_fileOwnerDataBlock = this;
m_fileName = KRResource::GetFileBase(path); m_fileName = KRResource::GetFileBase(path);
FILE_STANDARD_INFO fileInfo; FILE_STANDARD_INFO fileInfo;
if(GetFileInformationByHandleEx(m_hPackFile, FileStandardInfo, &fileInfo, sizeof(fileInfo))) { if (GetFileInformationByHandleEx(m_hPackFile, FileStandardInfo, &fileInfo, sizeof(fileInfo))) {
m_data_size = fileInfo.EndOfFile.QuadPart; m_data_size = fileInfo.EndOfFile.QuadPart;
m_data_offset = 0; m_data_offset = 0;
success = true; success = true;
}
} }
}
#elif defined(__APPLE__) #elif defined(__APPLE__)
m_fdPackFile = open(path.c_str(), O_RDONLY); m_fdPackFile = open(path.c_str(), O_RDONLY);
if(m_fdPackFile >= 0) { if (m_fdPackFile >= 0) {
m_fileOwnerDataBlock = this; m_fileOwnerDataBlock = this;
m_fileName = KRResource::GetFileBase(path); m_fileName = KRResource::GetFileBase(path);
struct stat statbuf; struct stat statbuf;
if(fstat(m_fdPackFile, &statbuf) >= 0) { if (fstat(m_fdPackFile, &statbuf) >= 0) {
m_data_size = statbuf.st_size; m_data_size = statbuf.st_size;
m_data_offset = 0; m_data_offset = 0;
success = true; success = true;
}
} }
}
#endif #endif
if(!success) { if (!success) {
// If anything failed, don't leave the object in an invalid state // If anything failed, don't leave the object in an invalid state
unload(); unload();
} }
return success; return success;
} }
// Create a KRDataBlock encapsulating a sub-region of this block. The caller is responsible to free the object. // Create a KRDataBlock encapsulating a sub-region of this block. The caller is responsible to free the object.
KRDataBlock *KRDataBlock::getSubBlock(int start, int length) KRDataBlock* KRDataBlock::getSubBlock(int start, int length)
{ {
KRDataBlock *new_block = new KRDataBlock(); KRDataBlock* new_block = new KRDataBlock();
new_block->m_data_size = length; new_block->m_data_size = length;
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
if(m_hPackFile != INVALID_HANDLE_VALUE) { if (m_hPackFile != INVALID_HANDLE_VALUE) {
new_block->m_hPackFile = m_hPackFile; new_block->m_hPackFile = m_hPackFile;
#elif defined(__APPLE__) || defined(ANDROID) #elif defined(__APPLE__) || defined(ANDROID)
if (m_fdPackFile) { if (m_fdPackFile) {
new_block->m_fdPackFile = m_fdPackFile; new_block->m_fdPackFile = m_fdPackFile;
#else #else
#error Unsupported #error Unsupported
#endif #endif
new_block->m_fileOwnerDataBlock = m_fileOwnerDataBlock; new_block->m_fileOwnerDataBlock = m_fileOwnerDataBlock;
new_block->m_data_offset = start + m_data_offset; new_block->m_data_offset = start + m_data_offset;
} else if(m_bMalloced) { } else if (m_bMalloced) {
new_block->m_data = (unsigned char *)m_data + start + m_data_offset; new_block->m_data = (unsigned char*)m_data + start + m_data_offset;
} }
new_block->m_bReadOnly = true; new_block->m_bReadOnly = true;
return new_block; return new_block;
} }
// Return a pointer to the start of the data block // Return a pointer to the start of the data block
void *KRDataBlock::getStart() { void* KRDataBlock::getStart()
assertLocked(); {
return m_data; assertLocked();
return m_data;
} }
// Return a pointer to the byte after the end of the data block // Return a pointer to the byte after the end of the data block
void *KRDataBlock::getEnd() { void* KRDataBlock::getEnd()
assertLocked(); {
return (unsigned char *)m_data + m_data_size; assertLocked();
return (unsigned char*)m_data + m_data_size;
} }
// Return the size of the data block. Use append() or expand() to make the data block larger // Return the size of the data block. Use append() or expand() to make the data block larger
size_t KRDataBlock::getSize() const { size_t KRDataBlock::getSize() const
return m_data_size; {
return m_data_size;
} }
// Expand the data block, and switch it to read-write mode. Note - this may result in a mmap'ed file being copied to malloc'ed ram and then closed // Expand the data block, and switch it to read-write mode. Note - this may result in a mmap'ed file being copied to malloc'ed ram and then closed
void KRDataBlock::expand(size_t size) void KRDataBlock::expand(size_t size)
{ {
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
if(m_data == NULL && m_hPackFile == INVALID_HANDLE_VALUE) { if (m_data == NULL && m_hPackFile == INVALID_HANDLE_VALUE) {
#elif defined(__APPLE__) || defined(ANDROID) #elif defined(__APPLE__) || defined(ANDROID)
if (m_data == NULL && m_fdPackFile == 0) { if (m_data == NULL && m_fdPackFile == 0) {
#else #else
#error Unsupported #error Unsupported
#endif #endif
// Starting with an empty data block; allocate memory on the heap // Starting with an empty data block; allocate memory on the heap
m_data = malloc(size); m_data = malloc(size);
assert(m_data != NULL); assert(m_data != NULL);
m_data_size = size; m_data_size = size;
m_data_offset = 0; m_data_offset = 0;
m_bMalloced = true; m_bMalloced = true;
} else if(m_bMalloced) { } else if (m_bMalloced) {
// Starting with a malloc'ed data block; realloc it expand // Starting with a malloc'ed data block; realloc it expand
m_data = realloc(m_data, m_data_size + size); m_data = realloc(m_data, m_data_size + size);
m_data_size += size; m_data_size += size;
} else { } else {
// Starting with a mmap'ed data block, an encapsulated pointer, or a sub-block; copy it to ram before expanding to avoid updating the original file until save() is called // Starting with a mmap'ed data block, an encapsulated pointer, or a sub-block; copy it to ram before expanding to avoid updating the original file until save() is called
// ... Or starting with a pointer reference, we must make our own copy and must not free the pointer // ... Or starting with a pointer reference, we must make our own copy and must not free the pointer
void *pNewData = malloc(m_data_size + size); void* pNewData = malloc(m_data_size + size);
assert(pNewData != NULL); assert(pNewData != NULL);
// Copy exising data // Copy exising data
copy(pNewData); copy(pNewData);
// Unload existing data allocation, which is now redundant // Unload existing data allocation, which is now redundant
size_t new_size = m_data_size + size; // We need to store this before unload() as unload() will reset it size_t new_size = m_data_size + size; // We need to store this before unload() as unload() will reset it
unload(); unload();
m_bMalloced = true; m_bMalloced = true;
m_data = pNewData; m_data = pNewData;
m_data_size = new_size; m_data_size = new_size;
m_data_offset = 0; m_data_offset = 0;
} }
} }
// Append data to the end of the block, increasing the size of the block and making it read-write. // Append data to the end of the block, increasing the size of the block and making it read-write.
void KRDataBlock::append(void *data, size_t size) { void KRDataBlock::append(void* data, size_t size)
// Expand the data block {
expand(size); // Expand the data block
expand(size);
// Fill the new space with the data to append // Fill the new space with the data to append
lock(); lock();
memcpy((unsigned char *)m_data + m_data_size - size, data, size); memcpy((unsigned char*)m_data + m_data_size - size, data, size);
unlock(); unlock();
} }
// Copy the entire data block to the destination pointer // Copy the entire data block to the destination pointer
void KRDataBlock::copy(void *dest) { void KRDataBlock::copy(void* dest)
copy(dest, 0, (int)m_data_size); {
copy(dest, 0, (int)m_data_size);
} }
// Copy a range of data to the destination pointer // Copy a range of data to the destination pointer
void KRDataBlock::copy(void *dest, int start, int count) { void KRDataBlock::copy(void* dest, int start, int count)
{
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
if (m_lockCount == 0 && m_hPackFile != INVALID_HANDLE_VALUE) { if (m_lockCount == 0 && m_hPackFile != INVALID_HANDLE_VALUE) {
// Optimization: If we haven't mmap'ed or malloced the data already, ReadFile() it directly from the file into the buffer // Optimization: If we haven't mmap'ed or malloced the data already, ReadFile() it directly from the file into the buffer
@@ -285,41 +294,42 @@ void KRDataBlock::copy(void *dest, int start, int count) {
bool success = SetFilePointerEx(m_hPackFile, distance, NULL, FILE_BEGIN); bool success = SetFilePointerEx(m_hPackFile, distance, NULL, FILE_BEGIN);
assert(success); assert(success);
void *w = dest; void* w = dest;
DWORD bytes_remaining = count; DWORD bytes_remaining = count;
while(bytes_remaining > 0) { while (bytes_remaining > 0) {
DWORD bytes_read = 0; DWORD bytes_read = 0;
success = ReadFile(m_hPackFile, w, bytes_remaining, &bytes_read, NULL); success = ReadFile(m_hPackFile, w, bytes_remaining, &bytes_read, NULL);
assert(success); assert(success);
assert(bytes_read > 0); assert(bytes_read > 0);
w = (unsigned char *)w + bytes_read; w = (unsigned char*)w + bytes_read;
bytes_remaining -= bytes_read; bytes_remaining -= bytes_read;
} }
assert(bytes_remaining == 0); assert(bytes_remaining == 0);
#elif defined(__APPLE__) || defined(ANDROID) #elif defined(__APPLE__) || defined(ANDROID)
if(m_lockCount == 0 && m_fdPackFile != 0) { if (m_lockCount == 0 && m_fdPackFile != 0) {
// Optimization: If we haven't mmap'ed or malloced the data already, pread() it directly from the file into the buffer // Optimization: If we haven't mmap'ed or malloced the data already, pread() it directly from the file into the buffer
ssize_t r = pread(m_fdPackFile, dest, count, start + m_data_offset); ssize_t r = pread(m_fdPackFile, dest, count, start + m_data_offset);
assert(r != -1); assert(r != -1);
#else #else
#error Unsupported #error Unsupported
#endif #endif
} else { } else {
lock(); lock();
memcpy((unsigned char *)dest, (unsigned char *)m_data + start, count); memcpy((unsigned char*)dest, (unsigned char*)m_data + start, count);
unlock(); unlock();
} }
} }
// Append data to the end of the block, increasing the size of the block and making it read-write. // Append data to the end of the block, increasing the size of the block and making it read-write.
void KRDataBlock::append(KRDataBlock &data) { void KRDataBlock::append(KRDataBlock & data)
data.lock(); {
append(data.getStart(), data.getSize()); data.lock();
data.unlock(); append(data.getStart(), data.getSize());
data.unlock();
} }
// Append string to the end of the block, increasing the size of the block and making it read-write. The resulting datablock includes a terminating character // Append string to the end of the block, increasing the size of the block and making it read-write. The resulting datablock includes a terminating character
void KRDataBlock::append(const std::string &s) void KRDataBlock::append(const std::string & s)
{ {
const char* szText = s.c_str(); const char* szText = s.c_str();
size_t text_length = strlen(szText); size_t text_length = strlen(szText);
@@ -339,12 +349,13 @@ void KRDataBlock::append(const std::string &s)
} }
// Save the data to a file. // Save the data to a file.
bool KRDataBlock::save(const std::string& path) { bool KRDataBlock::save(const std::string & path)
{
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
bool success = true; bool success = true;
HANDLE hNewFile = INVALID_HANDLE_VALUE; HANDLE hNewFile = INVALID_HANDLE_VALUE;
HANDLE hFileMapping = NULL; HANDLE hFileMapping = NULL;
void *pNewData = NULL; void* pNewData = NULL;
hNewFile = CreateFile(path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); hNewFile = CreateFile(path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hNewFile == INVALID_HANDLE_VALUE) { if (hNewFile == INVALID_HANDLE_VALUE) {
@@ -385,32 +396,32 @@ bool KRDataBlock::save(const std::string& path) {
return success; return success;
#elif defined(__APPLE__) || defined(ANDROID) #elif defined(__APPLE__) || defined(ANDROID)
int fdNewFile = open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600); int fdNewFile = open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
if(fdNewFile == -1) { if (fdNewFile == -1) {
return false; return false;
} }
// Seek to end of file and write a byte to enlarge it // Seek to end of file and write a byte to enlarge it
lseek(fdNewFile, m_data_size-1, SEEK_SET); lseek(fdNewFile, m_data_size - 1, SEEK_SET);
write(fdNewFile, "", 1); write(fdNewFile, "", 1);
// Now map it... // Now map it...
void *pNewData = mmap(0, m_data_size, PROT_READ | PROT_WRITE, MAP_SHARED, fdNewFile, 0); void* pNewData = mmap(0, m_data_size, PROT_READ | PROT_WRITE, MAP_SHARED, fdNewFile, 0);
if(pNewData == (caddr_t) -1) { if (pNewData == (caddr_t)-1) {
close(fdNewFile); close(fdNewFile);
return false; return false;
} }
if(m_data != NULL) { if (m_data != NULL) {
// Copy data to new file // Copy data to new file
copy(pNewData); copy(pNewData);
// Unmap the new file // Unmap the new file
munmap(pNewData, m_data_size); munmap(pNewData, m_data_size);
// Close the new file // Close the new file
close(fdNewFile); close(fdNewFile);
} }
return true; return true;
#else #else
#error Unsupported #error Unsupported
@@ -420,13 +431,13 @@ bool KRDataBlock::save(const std::string& path) {
// Get contents as a string // Get contents as a string
std::string KRDataBlock::getString() std::string KRDataBlock::getString()
{ {
KRDataBlock b; KRDataBlock b;
b.append(*this); b.append(*this);
b.append((void *)"\0", 1); // Ensure data is null terminated, to read as a string safely b.append((void*)"\0", 1); // Ensure data is null terminated, to read as a string safely
b.lock(); b.lock();
std::string ret = std::string((char *)b.getStart()); std::string ret = std::string((char*)b.getStart());
b.unlock(); b.unlock();
return ret; return ret;
} }
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
@@ -462,133 +473,133 @@ void ReportWindowsLastError(LPCTSTR lpszFunction)
// Lock the memory, forcing it to be loaded into a contiguous block of address space // Lock the memory, forcing it to be loaded into a contiguous block of address space
void KRDataBlock::lock() void KRDataBlock::lock()
{ {
if(m_lockCount == 0) { if (m_lockCount == 0) {
// Memory mapped file; ensure data is mapped to ram // Memory mapped file; ensure data is mapped to ram
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
if(m_hPackFile != INVALID_HANDLE_VALUE) { if (m_hPackFile != INVALID_HANDLE_VALUE) {
#elif defined(__APPLE__) || defined(ANDROID) #elif defined(__APPLE__) || defined(ANDROID)
if(m_fdPackFile) { if (m_fdPackFile) {
#else #else
#error Unsupported #error Unsupported
#endif #endif
if(m_data_size < KRENGINE_MIN_MMAP) { if (m_data_size < KRENGINE_MIN_MMAP) {
m_data = malloc(m_data_size); m_data = malloc(m_data_size);
assert(m_data != NULL); assert(m_data != NULL);
copy(m_data); copy(m_data);
} else { } else {
size_t alignment_offset = m_data_offset & (KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY - 1); size_t alignment_offset = m_data_offset & (KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY - 1);
assert(m_mmapData == NULL); assert(m_mmapData == NULL);
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
m_hFileMapping = CreateFileMappingFromApp(m_hPackFile, NULL, m_bReadOnly ? PAGE_READONLY : PAGE_READWRITE, m_fileOwnerDataBlock->getSize(), NULL); m_hFileMapping = CreateFileMappingFromApp(m_hPackFile, NULL, m_bReadOnly ? PAGE_READONLY : PAGE_READWRITE, m_fileOwnerDataBlock->getSize(), NULL);
if(m_hFileMapping == NULL) { if (m_hFileMapping == NULL) {
ReportWindowsLastError("CreateFileMappingFromApp"); ReportWindowsLastError("CreateFileMappingFromApp");
} }
assert(m_hFileMapping != NULL); assert(m_hFileMapping != NULL);
m_mmapData = MapViewOfFileFromApp(m_hFileMapping, m_bReadOnly ? FILE_MAP_READ | FILE_MAP_COPY : FILE_MAP_WRITE, m_data_offset - alignment_offset, m_data_size + alignment_offset); m_mmapData = MapViewOfFileFromApp(m_hFileMapping, m_bReadOnly ? FILE_MAP_READ | FILE_MAP_COPY : FILE_MAP_WRITE, m_data_offset - alignment_offset, m_data_size + alignment_offset);
if(m_mmapData == NULL) { if (m_mmapData == NULL) {
ReportWindowsLastError("MapViewOfFileFromApp"); ReportWindowsLastError("MapViewOfFileFromApp");
} }
assert(m_mmapData != NULL); assert(m_mmapData != NULL);
#elif defined(__APPLE__) || defined(ANDROID) #elif defined(__APPLE__) || defined(ANDROID)
//fprintf(stderr, "KRDataBlock::lock - \"%s\" (%i)\n", m_fileOwnerDataBlock->m_fileName.c_str(), m_lockCount); //fprintf(stderr, "KRDataBlock::lock - \"%s\" (%i)\n", m_fileOwnerDataBlock->m_fileName.c_str(), m_lockCount);
// Round m_data_offset down to the next memory page, as required by mmap // Round m_data_offset down to the next memory page, as required by mmap
if ((m_mmapData = mmap(0, m_data_size + alignment_offset, m_bReadOnly ? PROT_READ : PROT_WRITE, MAP_SHARED, m_fdPackFile, m_data_offset - alignment_offset)) == (caddr_t) -1) { if ((m_mmapData = mmap(0, m_data_size + alignment_offset, m_bReadOnly ? PROT_READ : PROT_WRITE, MAP_SHARED, m_fdPackFile, m_data_offset - alignment_offset)) == (caddr_t)-1) {
int iError = errno; int iError = errno;
switch(iError) { switch (iError) {
case EACCES: case EACCES:
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EACCES"); KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EACCES");
break; break;
case EBADF: case EBADF:
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EBADF"); KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EBADF");
break; break;
case EMFILE: case EMFILE:
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EMFILE"); KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EMFILE");
break; break;
case EINVAL: case EINVAL:
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EINVAL"); KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EINVAL");
break; break;
case ENOMEM: case ENOMEM:
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with ENOMEM"); KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with ENOMEM");
break; break;
case ENXIO: case ENXIO:
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with ENXIO"); KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with ENXIO");
break; break;
case EOVERFLOW: case EOVERFLOW:
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EOVERFLOW"); KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EOVERFLOW");
break; break;
default: default:
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with errno: %i", iError); KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with errno: %i", iError);
break; break;
}
assert(false); // mmap() failed.
}
#else
#error Unsupported
#endif
m_mapCount++;
m_mapSize += m_data_size;
m_mapOverhead += alignment_offset + KRAKEN_MEM_ROUND_UP_PAGE(m_data_size + alignment_offset) - m_data_size + alignment_offset;
// fprintf(stderr, "Mapped: %i Size: %d Overhead: %d\n", m_mapCount, m_mapSize, m_mapOverhead);
m_data = (unsigned char *)m_mmapData + alignment_offset;
}
} }
assert(false); // mmap() failed.
}
#else
#error Unsupported
#endif
m_mapCount++;
m_mapSize += m_data_size;
m_mapOverhead += alignment_offset + KRAKEN_MEM_ROUND_UP_PAGE(m_data_size + alignment_offset) - m_data_size + alignment_offset;
// fprintf(stderr, "Mapped: %i Size: %d Overhead: %d\n", m_mapCount, m_mapSize, m_mapOverhead);
m_data = (unsigned char*)m_mmapData + alignment_offset;
} }
m_lockCount++; }
}
m_lockCount++;
} }
// Unlock the memory, releasing the address space for use by other allocations // Unlock the memory, releasing the address space for use by other allocations
void KRDataBlock::unlock() void KRDataBlock::unlock()
{ {
// We expect that the data block was previously locked // We expect that the data block was previously locked
assertLocked(); assertLocked();
if(m_lockCount == 1) { if (m_lockCount == 1) {
// Memory mapped file; ensure data is unmapped from ram // Memory mapped file; ensure data is unmapped from ram
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
if (m_hPackFile != INVALID_HANDLE_VALUE) { if (m_hPackFile != INVALID_HANDLE_VALUE) {
#elif defined(__APPLE__) || defined(ANDROID) #elif defined(__APPLE__) || defined(ANDROID)
if(m_fdPackFile) { if (m_fdPackFile) {
#else #else
#error Undefined #error Undefined
#endif #endif
if(m_data_size < KRENGINE_MIN_MMAP) { if (m_data_size < KRENGINE_MIN_MMAP) {
free(m_data); free(m_data);
m_data = NULL; m_data = NULL;
} else { } else {
//fprintf(stderr, "KRDataBlock::unlock - \"%s\" (%i)\n", m_fileOwnerDataBlock->m_fileName.c_str(), m_lockCount); //fprintf(stderr, "KRDataBlock::unlock - \"%s\" (%i)\n", m_fileOwnerDataBlock->m_fileName.c_str(), m_lockCount);
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
if (m_mmapData != NULL) { if (m_mmapData != NULL) {
UnmapViewOfFile(m_mmapData); UnmapViewOfFile(m_mmapData);
} }
if(m_hFileMapping != NULL) { if (m_hFileMapping != NULL) {
CloseHandle(m_hFileMapping); CloseHandle(m_hFileMapping);
m_hFileMapping = NULL; m_hFileMapping = NULL;
} }
#elif defined(__APPLE__) || defined(ANDROID) #elif defined(__APPLE__) || defined(ANDROID)
munmap(m_mmapData, m_data_size); munmap(m_mmapData, m_data_size);
#else #else
#error Undefined #error Undefined
#endif #endif
m_data = NULL; m_data = NULL;
m_mmapData = NULL; m_mmapData = NULL;
m_mapCount--; m_mapCount--;
m_mapSize -= m_data_size; m_mapSize -= m_data_size;
size_t alignment_offset = m_data_offset & (KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY - 1); size_t alignment_offset = m_data_offset & (KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY - 1);
m_mapOverhead -= alignment_offset + KRAKEN_MEM_ROUND_UP_PAGE(m_data_size + alignment_offset) - m_data_size + alignment_offset; m_mapOverhead -= alignment_offset + KRAKEN_MEM_ROUND_UP_PAGE(m_data_size + alignment_offset) - m_data_size + alignment_offset;
// fprintf(stderr, "Mapped: %i Size: %d Overhead: %d\n", m_mapCount, m_mapSize, m_mapOverhead); // fprintf(stderr, "Mapped: %i Size: %d Overhead: %d\n", m_mapCount, m_mapSize, m_mapOverhead);
}
}
} }
m_lockCount--; }
}
m_lockCount--;
} }
// Assert if not locked // Assert if not locked
void KRDataBlock::assertLocked() void KRDataBlock::assertLocked()
{ {
assert(m_lockCount > 0); assert(m_lockCount > 0);
} }

View File

@@ -39,90 +39,91 @@
#define KRENGINE_MIN_MMAP 32768 #define KRENGINE_MIN_MMAP 32768
class KRDataBlock { class KRDataBlock
{
public: public:
KRDataBlock(); KRDataBlock();
KRDataBlock(void *data, size_t size); KRDataBlock(void* data, size_t size);
~KRDataBlock(); ~KRDataBlock();
// Encapsulate a pointer. Note - The pointer will not be free'ed // Encapsulate a pointer. Note - The pointer will not be free'ed
bool load(void *data, size_t size); bool load(void* data, size_t size);
// Load a file into memory using mmap. The data pointer will be protected as read-only until append() or expand() is called // Load a file into memory using mmap. The data pointer will be protected as read-only until append() or expand() is called
bool load(const std::string &path); bool load(const std::string& path);
// Save the data to a file. // Save the data to a file.
bool save(const std::string& path); bool save(const std::string& path);
// Create a KRDataBlock encapsulating a sub-region of this block. The caller is responsible to free the object. // Create a KRDataBlock encapsulating a sub-region of this block. The caller is responsible to free the object.
KRDataBlock *getSubBlock(int start, int length); KRDataBlock* getSubBlock(int start, int length);
// Append data to the end of the block, increasing the size of the block and making it read-write. // Append data to the end of the block, increasing the size of the block and making it read-write.
void append(void *data, size_t size); void append(void* data, size_t size);
// Append data to the end of the block, increasing the size of the block and making it read-write. // Append data to the end of the block, increasing the size of the block and making it read-write.
void append(KRDataBlock &data); void append(KRDataBlock& data);
// Append string to the end of the block, increasing the size of the block and making it read-write. The null terminating character is included // Append string to the end of the block, increasing the size of the block and making it read-write. The null terminating character is included
void append(const std::string &s); void append(const std::string& s);
// Expand or shrink the data block, and switch it to read-write mode. Note - this may result in a mmap'ed file being copied to malloc'ed ram and then closed // Expand or shrink the data block, and switch it to read-write mode. Note - this may result in a mmap'ed file being copied to malloc'ed ram and then closed
void expand(size_t size); void expand(size_t size);
// Unload a file, releasing any mmap'ed file handles or malloc'ed ram that was in use // Unload a file, releasing any mmap'ed file handles or malloc'ed ram that was in use
void unload(); void unload();
// Return a pointer to the start of the data block // Return a pointer to the start of the data block
void *getStart(); void* getStart();
// Return a pointer to the one byte after the end of the data block // Return a pointer to the one byte after the end of the data block
void *getEnd(); void* getEnd();
// Return the size of the data block. Use append() or expand() to make the data block larger // Return the size of the data block. Use append() or expand() to make the data block larger
size_t getSize() const; size_t getSize() const;
// Get the contents as a string // Get the contents as a string
std::string getString(); std::string getString();
// Copy the entire data block to the destination pointer // Copy the entire data block to the destination pointer
void copy(void *dest); void copy(void* dest);
// Copy a range of data to the destination pointer // Copy a range of data to the destination pointer
void copy(void *dest, int start, int count); void copy(void* dest, int start, int count);
// Lock the memory, forcing it to be loaded into a contiguous block of address space // Lock the memory, forcing it to be loaded into a contiguous block of address space
void lock(); void lock();
// Unlock the memory, releasing the address space for use by other allocations // Unlock the memory, releasing the address space for use by other allocations
void unlock(); void unlock();
private: private:
void *m_data; void* m_data;
size_t m_data_size; size_t m_data_size;
size_t m_data_offset; size_t m_data_offset;
// For memory mapped objects: // For memory mapped objects:
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
HANDLE m_hPackFile; HANDLE m_hPackFile;
HANDLE m_hFileMapping; HANDLE m_hFileMapping;
#elif defined(__APPLE__) || defined(ANDROID) #elif defined(__APPLE__) || defined(ANDROID)
int m_fdPackFile; int m_fdPackFile;
#endif #endif
std::string m_fileName; std::string m_fileName;
KRDataBlock *m_fileOwnerDataBlock; KRDataBlock* m_fileOwnerDataBlock;
void *m_mmapData; void* m_mmapData;
// For malloc'ed objects: // For malloc'ed objects:
bool m_bMalloced; bool m_bMalloced;
// Lock refcount // Lock refcount
int m_lockCount; int m_lockCount;
// Read-only allocation // Read-only allocation
bool m_bReadOnly; bool m_bReadOnly;
// Assert if not locked // Assert if not locked
void assertLocked(); void assertLocked();
}; };

View File

@@ -81,7 +81,7 @@ void KRDevice::destroy()
vkDestroyCommandPool(m_logicalDevice, m_graphicsCommandPool, nullptr); vkDestroyCommandPool(m_logicalDevice, m_graphicsCommandPool, nullptr);
m_graphicsCommandPool = VK_NULL_HANDLE; m_graphicsCommandPool = VK_NULL_HANDLE;
} }
if (m_computeCommandPool != VK_NULL_HANDLE) { if (m_computeCommandPool != VK_NULL_HANDLE) {
vkDestroyCommandPool(m_logicalDevice, m_computeCommandPool, nullptr); vkDestroyCommandPool(m_logicalDevice, m_computeCommandPool, nullptr);
m_computeCommandPool = VK_NULL_HANDLE; m_computeCommandPool = VK_NULL_HANDLE;
@@ -91,7 +91,7 @@ void KRDevice::destroy()
vkDestroyCommandPool(m_logicalDevice, m_transferCommandPool, nullptr); vkDestroyCommandPool(m_logicalDevice, m_transferCommandPool, nullptr);
m_transferCommandPool = VK_NULL_HANDLE; m_transferCommandPool = VK_NULL_HANDLE;
} }
if (m_logicalDevice != VK_NULL_HANDLE) { if (m_logicalDevice != VK_NULL_HANDLE) {
vkDestroyDevice(m_logicalDevice, nullptr); vkDestroyDevice(m_logicalDevice, nullptr);
m_logicalDevice = VK_NULL_HANDLE; m_logicalDevice = VK_NULL_HANDLE;
@@ -398,7 +398,7 @@ bool KRDevice::initStagingBuffers()
#if KRENGINE_DEBUG_GPU_LABELS #if KRENGINE_DEBUG_GPU_LABELS
, "Streaming Staging Buffer" , "Streaming Staging Buffer"
#endif // KRENGINE_DEBUG_GPU_LABELS #endif // KRENGINE_DEBUG_GPU_LABELS
)) { )) {
return false; return false;
} }
@@ -412,7 +412,7 @@ bool KRDevice::initStagingBuffers()
#if KRENGINE_DEBUG_GPU_LABELS #if KRENGINE_DEBUG_GPU_LABELS
, "Graphics Staging Buffer" , "Graphics Staging Buffer"
#endif // KRENGINE_DEBUG_GPU_LABELS #endif // KRENGINE_DEBUG_GPU_LABELS
)) { )) {
return false; return false;
} }
return true; return true;
@@ -422,7 +422,7 @@ bool KRDevice::initStagingBuffer(VkDeviceSize size, StagingBufferInfo* info
#if KRENGINE_DEBUG_GPU_LABELS #if KRENGINE_DEBUG_GPU_LABELS
, const char* debug_label , const char* debug_label
#endif // KRENGINE_DEBUG_GPU_LABELS #endif // KRENGINE_DEBUG_GPU_LABELS
) )
{ {
if (!createBuffer( if (!createBuffer(
size, size,
@@ -433,7 +433,7 @@ bool KRDevice::initStagingBuffer(VkDeviceSize size, StagingBufferInfo* info
#if KRENGINE_DEBUG_GPU_LABELS #if KRENGINE_DEBUG_GPU_LABELS
, debug_label , debug_label
#endif // KRENGINE_DEBUG_GPU_LABELS #endif // KRENGINE_DEBUG_GPU_LABELS
)) { )) {
return false; return false;
} }
if (vmaMapMemory(m_allocator, info->allocation, &info->data) != VK_SUCCESS) { if (vmaMapMemory(m_allocator, info->allocation, &info->data) != VK_SUCCESS) {
@@ -561,7 +561,7 @@ bool KRDevice::createImage(Vector2i dimensions, VkImageCreateFlags imageCreateFl
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageInfo.flags = imageCreateFlags; imageInfo.flags = imageCreateFlags;
uint32_t queueFamilyIndices[2] = {}; uint32_t queueFamilyIndices[2] = {};
imageInfo.pQueueFamilyIndices = queueFamilyIndices; imageInfo.pQueueFamilyIndices = queueFamilyIndices;

View File

@@ -76,7 +76,7 @@ public:
void streamStart(); void streamStart();
void streamUpload(KRDataBlock& data, VkBuffer destination); void streamUpload(KRDataBlock& data, VkBuffer destination);
void streamUpload(void *data, size_t size, VkBuffer destination); void streamUpload(void* data, size_t size, VkBuffer destination);
void streamUpload(void* data, size_t size, Vector2i dimensions, VkImage destination); void streamUpload(void* data, size_t size, Vector2i dimensions, VkImage destination);
void streamEnd(); void streamEnd();
@@ -101,7 +101,8 @@ public:
std::vector<VkCommandBuffer> m_transferCommandBuffers; std::vector<VkCommandBuffer> m_transferCommandBuffers;
VmaAllocator m_allocator; VmaAllocator m_allocator;
struct StagingBufferInfo { struct StagingBufferInfo
{
VkBuffer buffer; VkBuffer buffer;
VmaAllocation allocation; VmaAllocation allocation;
size_t size; size_t size;

View File

@@ -48,7 +48,7 @@ KRDeviceManager::KRDeviceManager(KRContext& context)
KRDeviceManager::~KRDeviceManager() KRDeviceManager::~KRDeviceManager()
{ {
destroyDevices(); destroyDevices();
if (m_vulkanInstance != VK_NULL_HANDLE) { if (m_vulkanInstance != VK_NULL_HANDLE) {
vkDestroyInstance(m_vulkanInstance, NULL); vkDestroyInstance(m_vulkanInstance, NULL);
m_vulkanInstance = VK_NULL_HANDLE; m_vulkanInstance = VK_NULL_HANDLE;
@@ -65,7 +65,7 @@ bool KRDeviceManager::haveDevice() const
return !m_devices.empty(); return !m_devices.empty();
} }
void void
KRDeviceManager::destroyDevices() KRDeviceManager::destroyDevices()
{ {
const std::lock_guard<std::mutex> lock(KRContext::g_DeviceInfoMutex); const std::lock_guard<std::mutex> lock(KRContext::g_DeviceInfoMutex);
@@ -162,23 +162,19 @@ void KRDeviceManager::createDevices()
bool addDevice = false; bool addDevice = false;
if (candidateDevices.empty()) { if (candidateDevices.empty()) {
addDevice = true; addDevice = true;
} } else {
else {
VkPhysicalDeviceType collectedType = candidateDevices[0]->m_deviceProperties.deviceType; VkPhysicalDeviceType collectedType = candidateDevices[0]->m_deviceProperties.deviceType;
if (collectedType == device->m_deviceProperties.deviceType) { if (collectedType == device->m_deviceProperties.deviceType) {
addDevice = true; addDevice = true;
} } else if (device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
else if (device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
// Discrete GPU's are always the best choice // Discrete GPU's are always the best choice
candidateDevices.clear(); candidateDevices.clear();
addDevice = true; addDevice = true;
} } else if (collectedType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
else if (collectedType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
// Integrated GPU's are the second best choice // Integrated GPU's are the second best choice
candidateDevices.clear(); candidateDevices.clear();
addDevice = true; addDevice = true;
} } else if (collectedType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && collectedType != VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU && device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) {
else if (collectedType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && collectedType != VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU && device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) {
// Virtual GPU's are the 3rd best choice // Virtual GPU's are the 3rd best choice
candidateDevices.clear(); candidateDevices.clear();
addDevice = true; addDevice = true;
@@ -204,7 +200,7 @@ void KRDeviceManager::createDevices()
snprintf(label, kMaxLabel, "GPU %i", iDevice + 1); snprintf(label, kMaxLabel, "GPU %i", iDevice + 1);
} }
device->setDebugLabel(device->m_logicalDevice, label); device->setDebugLabel(device->m_logicalDevice, label);
#endif #endif
m_devices[++m_topDeviceHandle] = std::move(device); m_devices[++m_topDeviceHandle] = std::move(device);

View File

@@ -43,127 +43,132 @@ void KRDirectionalLight::InitNodeInfo(KrNodeInfo* nodeInfo)
// No additional members // No additional members
} }
KRDirectionalLight::KRDirectionalLight(KRScene &scene, std::string name) : KRLight(scene, name) KRDirectionalLight::KRDirectionalLight(KRScene& scene, std::string name) : KRLight(scene, name)
{ {
} }
KRDirectionalLight::~KRDirectionalLight() KRDirectionalLight::~KRDirectionalLight()
{ {
} }
std::string KRDirectionalLight::getElementName() { std::string KRDirectionalLight::getElementName()
return "directional_light"; {
return "directional_light";
} }
Vector3 KRDirectionalLight::getWorldLightDirection() { Vector3 KRDirectionalLight::getWorldLightDirection()
return Matrix4::Dot(getWorldRotation().rotationMatrix(), getLocalLightDirection()); {
return Matrix4::Dot(getWorldRotation().rotationMatrix(), getLocalLightDirection());
} }
Vector3 KRDirectionalLight::getLocalLightDirection() { Vector3 KRDirectionalLight::getLocalLightDirection()
return Vector3::Up(); //&KRF HACK changed from Vector3::Forward(); - to compensate for the way Maya handles post rotation. {
return Vector3::Up(); //&KRF HACK changed from Vector3::Forward(); - to compensate for the way Maya handles post rotation.
} }
int KRDirectionalLight::configureShadowBufferViewports(const KRViewport &viewport) { int KRDirectionalLight::configureShadowBufferViewports(const KRViewport& viewport)
{
const float KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE = 1.25f; // Scale to apply to view frustrum bounds so that we don't need to refresh shadows on every frame
int cShadows = 1; const float KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE = 1.25f; // Scale to apply to view frustrum bounds so that we don't need to refresh shadows on every frame
for(int iShadow=0; iShadow < cShadows; iShadow++) { int cShadows = 1;
/* for (int iShadow = 0; iShadow < cShadows; iShadow++) {
TODO - Determine if we still need this... /*
TODO - Determine if we still need this...
GLfloat shadowMinDepths[3][3] = {{0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f},{0.0f, 0.05f, 0.3f}};
GLfloat shadowMaxDepths[3][3] = {{0.0f, 0.0f, 1.0f},{0.1f, 0.0f, 0.0f},{0.1f, 0.3f, 1.0f}}; GLfloat shadowMinDepths[3][3] = {{0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f},{0.0f, 0.05f, 0.3f}};
GLfloat shadowMaxDepths[3][3] = {{0.0f, 0.0f, 1.0f},{0.1f, 0.0f, 0.0f},{0.1f, 0.3f, 1.0f}};
float min_depth = 0.0f;
float max_depth = 1.0f; float min_depth = 0.0f;
*/ float max_depth = 1.0f;
*/
AABB worldSpacefrustrumSliceBounds = AABB::Create(Vector3::Create(-1.0f, -1.0f, -1.0f), Vector3::Create(1.0f, 1.0f, 1.0f), Matrix4::Invert(viewport.getViewProjectionMatrix()));
worldSpacefrustrumSliceBounds.scale(KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE); AABB worldSpacefrustrumSliceBounds = AABB::Create(Vector3::Create(-1.0f, -1.0f, -1.0f), Vector3::Create(1.0f, 1.0f, 1.0f), Matrix4::Invert(viewport.getViewProjectionMatrix()));
worldSpacefrustrumSliceBounds.scale(KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
Vector3 shadowLook = -Vector3::Normalize(getWorldLightDirection());
Vector3 shadowLook = -Vector3::Normalize(getWorldLightDirection());
Vector3 shadowUp = Vector3::Create(0.0, 1.0, 0.0);
if(Vector3::Dot(shadowUp, shadowLook) > 0.99f) shadowUp = Vector3::Create(0.0, 0.0, 1.0); // Ensure shadow look direction is not parallel with the shadowUp direction Vector3 shadowUp = Vector3::Create(0.0, 1.0, 0.0);
if (Vector3::Dot(shadowUp, shadowLook) > 0.99f) shadowUp = Vector3::Create(0.0, 0.0, 1.0); // Ensure shadow look direction is not parallel with the shadowUp direction
// Matrix4 matShadowView = Matrix4::LookAt(viewport.getCameraPosition() - shadowLook, viewport.getCameraPosition(), shadowUp); // Matrix4 matShadowView = Matrix4::LookAt(viewport.getCameraPosition() - shadowLook, viewport.getCameraPosition(), shadowUp);
// Matrix4 matShadowProjection = Matrix4(); // Matrix4 matShadowProjection = Matrix4();
// matShadowProjection.scale(0.001, 0.001, 0.001); // matShadowProjection.scale(0.001, 0.001, 0.001);
Matrix4 matShadowView = Matrix4::LookAt(worldSpacefrustrumSliceBounds.center() - shadowLook, worldSpacefrustrumSliceBounds.center(), shadowUp);
Matrix4 matShadowProjection = Matrix4();
AABB shadowSpaceFrustrumSliceBounds = AABB::Create(worldSpacefrustrumSliceBounds.min, worldSpacefrustrumSliceBounds.max, Matrix4::Invert(matShadowProjection));
AABB shadowSpaceSceneBounds = AABB::Create(getScene().getRootOctreeBounds().min, getScene().getRootOctreeBounds().max, Matrix4::Invert(matShadowProjection));
if(shadowSpaceSceneBounds.min.z < shadowSpaceFrustrumSliceBounds.min.z) shadowSpaceFrustrumSliceBounds.min.z = shadowSpaceSceneBounds.min.z; // Include any potential shadow casters that are outside the view frustrum
matShadowProjection.scale(1.0f / shadowSpaceFrustrumSliceBounds.size().x, 1.0f / shadowSpaceFrustrumSliceBounds.size().y, 1.0f / shadowSpaceFrustrumSliceBounds.size().z);
Matrix4 matBias;
matBias.bias();
matShadowProjection *= matBias;
KRViewport newShadowViewport = KRViewport(Vector2::Create(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection);
AABB prevShadowBounds = AABB::Create(-Vector3::One(), Vector3::One(), Matrix4::Invert(m_shadowViewports[iShadow].getViewProjectionMatrix()));
AABB minimumShadowBounds = AABB::Create(-Vector3::One(), Vector3::One(), Matrix4::Invert(newShadowViewport.getViewProjectionMatrix()));
minimumShadowBounds.scale(1.0f / KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
if(!prevShadowBounds.contains(minimumShadowBounds) || !shadowValid[iShadow] || true) { // FINDME, HACK - Re-generating the shadow map every frame. This should only be needed if the shadow contains non-static geometry
m_shadowViewports[iShadow] = newShadowViewport;
shadowValid[iShadow] = false;
fprintf(stderr, "Kraken - Generate shadow maps...\n");
}
}
return 1; Matrix4 matShadowView = Matrix4::LookAt(worldSpacefrustrumSliceBounds.center() - shadowLook, worldSpacefrustrumSliceBounds.center(), shadowUp);
Matrix4 matShadowProjection = Matrix4();
AABB shadowSpaceFrustrumSliceBounds = AABB::Create(worldSpacefrustrumSliceBounds.min, worldSpacefrustrumSliceBounds.max, Matrix4::Invert(matShadowProjection));
AABB shadowSpaceSceneBounds = AABB::Create(getScene().getRootOctreeBounds().min, getScene().getRootOctreeBounds().max, Matrix4::Invert(matShadowProjection));
if (shadowSpaceSceneBounds.min.z < shadowSpaceFrustrumSliceBounds.min.z) shadowSpaceFrustrumSliceBounds.min.z = shadowSpaceSceneBounds.min.z; // Include any potential shadow casters that are outside the view frustrum
matShadowProjection.scale(1.0f / shadowSpaceFrustrumSliceBounds.size().x, 1.0f / shadowSpaceFrustrumSliceBounds.size().y, 1.0f / shadowSpaceFrustrumSliceBounds.size().z);
Matrix4 matBias;
matBias.bias();
matShadowProjection *= matBias;
KRViewport newShadowViewport = KRViewport(Vector2::Create(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection);
AABB prevShadowBounds = AABB::Create(-Vector3::One(), Vector3::One(), Matrix4::Invert(m_shadowViewports[iShadow].getViewProjectionMatrix()));
AABB minimumShadowBounds = AABB::Create(-Vector3::One(), Vector3::One(), Matrix4::Invert(newShadowViewport.getViewProjectionMatrix()));
minimumShadowBounds.scale(1.0f / KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
if (!prevShadowBounds.contains(minimumShadowBounds) || !shadowValid[iShadow] || true) { // FINDME, HACK - Re-generating the shadow map every frame. This should only be needed if the shadow contains non-static geometry
m_shadowViewports[iShadow] = newShadowViewport;
shadowValid[iShadow] = false;
fprintf(stderr, "Kraken - Generate shadow maps...\n");
}
}
return 1;
} }
void KRDirectionalLight::render(RenderInfo& ri) { void KRDirectionalLight::render(RenderInfo& ri)
{
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRLight::render(ri);
if(ri.renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) { if (m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
// Lights are rendered on the second pass of the deferred renderer
std::vector<KRDirectionalLight *> this_light;
this_light.push_back(this);
Matrix4 matModelViewInverseTranspose = ri.viewport.getViewMatrix() * getModelMatrix(); KRLight::render(ri);
matModelViewInverseTranspose.transpose();
matModelViewInverseTranspose.invert();
Vector3 light_direction_view_space = getWorldLightDirection();
light_direction_view_space = Matrix4::Dot(matModelViewInverseTranspose, light_direction_view_space);
light_direction_view_space.normalize();
KRMeshManager::KRVBOData& vertices = getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES; if (ri.renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) {
// Lights are rendered on the second pass of the deferred renderer
PipelineInfo info{};
std::string shader_name("light_directional");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.directional_lights = &this_light;
info.renderPass = ri.renderPass;
info.rasterMode = RasterMode::kAdditiveNoTest;
info.vertexAttributes = vertices.getVertexAttributes(); std::vector<KRDirectionalLight*> this_light;
info.modelFormat = ModelFormat::KRENGINE_MODEL_FORMAT_STRIP; this_light.push_back(this);
KRPipeline *pShader = getContext().getPipelineManager()->getPipeline(*ri.surface, info); Matrix4 matModelViewInverseTranspose = ri.viewport.getViewMatrix() * getModelMatrix();
pShader->setUniform(KRPipeline::Uniform::light_direction_view_space, light_direction_view_space); matModelViewInverseTranspose.transpose();
pShader->setUniform(KRPipeline::Uniform::light_color, m_color); matModelViewInverseTranspose.invert();
pShader->setUniform(KRPipeline::Uniform::light_intensity, m_intensity * 0.01f);
pShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, getModelMatrix(), nullptr, &this_light, nullptr, ri.renderPass); Vector3 light_direction_view_space = getWorldLightDirection();
light_direction_view_space = Matrix4::Dot(matModelViewInverseTranspose, light_direction_view_space);
// Render a full screen quad light_direction_view_space.normalize();
m_pContext->getMeshManager()->bindVBO(ri.commandBuffer, &vertices, 1.0f);
vkCmdDraw(ri.commandBuffer, 4, 1, 0, 0); KRMeshManager::KRVBOData& vertices = getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES;
}
PipelineInfo info{};
std::string shader_name("light_directional");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.directional_lights = &this_light;
info.renderPass = ri.renderPass;
info.rasterMode = RasterMode::kAdditiveNoTest;
info.vertexAttributes = vertices.getVertexAttributes();
info.modelFormat = ModelFormat::KRENGINE_MODEL_FORMAT_STRIP;
KRPipeline* pShader = getContext().getPipelineManager()->getPipeline(*ri.surface, info);
pShader->setUniform(KRPipeline::Uniform::light_direction_view_space, light_direction_view_space);
pShader->setUniform(KRPipeline::Uniform::light_color, m_color);
pShader->setUniform(KRPipeline::Uniform::light_intensity, m_intensity * 0.01f);
pShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, getModelMatrix(), nullptr, &this_light, nullptr, ri.renderPass);
// Render a full screen quad
m_pContext->getMeshManager()->bindVBO(ri.commandBuffer, &vertices, 1.0f);
vkCmdDraw(ri.commandBuffer, 4, 1, 0, 0);
}
} }
AABB KRDirectionalLight::getBounds() AABB KRDirectionalLight::getBounds()
{ {
return AABB::Infinite(); return AABB::Infinite();
} }

View File

@@ -33,24 +33,25 @@
#include "KRLight.h" #include "KRLight.h"
class KRDirectionalLight : public KRLight { class KRDirectionalLight : public KRLight
{
public:
static void InitNodeInfo(KrNodeInfo* nodeInfo); public:
static void InitNodeInfo(KrNodeInfo* nodeInfo);
KRDirectionalLight(KRScene &scene, std::string name);
virtual ~KRDirectionalLight(); KRDirectionalLight(KRScene& scene, std::string name);
virtual ~KRDirectionalLight();
virtual std::string getElementName();
Vector3 getLocalLightDirection(); virtual std::string getElementName();
Vector3 getWorldLightDirection(); Vector3 getLocalLightDirection();
Vector3 getWorldLightDirection();
virtual void render(RenderInfo& ri);
virtual AABB getBounds();
virtual void render(RenderInfo& ri);
virtual AABB getBounds();
protected: protected:
virtual int configureShadowBufferViewports(const KRViewport &viewport); virtual int configureShadowBufferViewports(const KRViewport& viewport);
}; };

View File

@@ -253,10 +253,11 @@ fprintf(stderr, "Error at line number %d, in file %s. Returned %d for call %s\n"
#endif #endif
typedef enum { typedef enum
STREAM_LEVEL_OUT, {
STREAM_LEVEL_IN_LQ, STREAM_LEVEL_OUT,
STREAM_LEVEL_IN_HQ STREAM_LEVEL_IN_LQ,
STREAM_LEVEL_IN_HQ
} kraken_stream_level; } kraken_stream_level;
typedef int KrDeviceHandle; typedef int KrDeviceHandle;

View File

@@ -37,43 +37,46 @@
#include "KREngine-common.h" #include "KREngine-common.h"
typedef enum KREngineParameterType {KRENGINE_PARAMETER_INT, KRENGINE_PARAMETER_FLOAT, KRENGINE_PARAMETER_BOOL} KREngineParameterType; typedef enum KREngineParameterType
{
KRENGINE_PARAMETER_INT, KRENGINE_PARAMETER_FLOAT, KRENGINE_PARAMETER_BOOL
} KREngineParameterType;
namespace kraken { namespace kraken {
void set_parameter(const std::string &parameter_name, float parameter_value); void set_parameter(const std::string& parameter_name, float parameter_value);
void set_debug_text(const std::string &print_text); void set_debug_text(const std::string& print_text);
}; };
#ifdef __OBJC__ #ifdef __OBJC__
@interface KREngine : NSObject @interface KREngine : NSObject
+ (KREngine *)sharedInstance; + (KREngine*)sharedInstance;
@property(nonatomic, readonly) NSDictionary *parameter_names; @property(nonatomic, readonly) NSDictionary* parameter_names;
@property(nonatomic, assign) KRContext *context; @property(nonatomic, assign) KRContext* context;
@property(nonatomic, retain) NSString *debug_text; @property(nonatomic, retain) NSString* debug_text;
@property(nonatomic, assign, readonly) KRRenderSettings *settings; @property(nonatomic, assign, readonly) KRRenderSettings* settings;
- (id)init; -(id)init;
- (BOOL)loadResource:(NSString *)path; -(BOOL)loadResource:(NSString*)path;
// Parameter enumeration interface // Parameter enumeration interface
-(int)getParameterCount; -(int)getParameterCount;
-(NSString *)getParameterNameWithIndex: (int)i; -(NSString*)getParameterNameWithIndex: (int)i;
-(NSString *)getParameterLabelWithIndex: (int)i; -(NSString*)getParameterLabelWithIndex: (int)i;
-(KREngineParameterType)getParameterTypeWithIndex: (int)i; -(KREngineParameterType)getParameterTypeWithIndex: (int)i;
-(float)getParameterMinWithIndex: (int)i; -(float)getParameterMinWithIndex: (int)i;
-(float)getParameterMaxWithIndex: (int)i; -(float)getParameterMaxWithIndex: (int)i;
-(float)getParameterValueWithIndex: (int)i; -(float)getParameterValueWithIndex: (int)i;
-(void)setParameterValueWithIndex: (int)i Value: (float)v; -(void)setParameterValueWithIndex: (int)i Value : (float)v;
-(void)setParameterValueWithName: (NSString *)name Value: (float)v; -(void)setParameterValueWithName: (NSString*)name Value : (float)v;
-(int)getParameterIndexWithName: (NSString *)name; -(int)getParameterIndexWithName: (NSString*)name;
- (void)renderScene: (KRScene *)pScene WithDeltaTime: (float)deltaTime AndWidth: (int)width AndHeight: (int)height AndDefaultFBO: (GLint)defaultFBO; -(void)renderScene: (KRScene*)pScene WithDeltaTime : (float)deltaTime AndWidth : (int)width AndHeight : (int)height AndDefaultFBO : (GLint)defaultFBO;
//- (void)renderScene: (KRScene *)pScene WithDeltaTime: (float)deltaTime; //- (void)renderScene: (KRScene *)pScene WithDeltaTime: (float)deltaTime;
- (void)setNearZ: (float)dNearZ; -(void)setNearZ: (float)dNearZ;
- (void)setFarZ: (float)dFarZ; -(void)setFarZ: (float)dFarZ;
@end @end

View File

@@ -35,7 +35,7 @@
namespace kraken { namespace kraken {
void setXMLAttribute(const std::string &base_name, tinyxml2::XMLElement *e, const Vector3 &value, const Vector3 &default_value) void setXMLAttribute(const std::string& base_name, tinyxml2::XMLElement* e, const Vector3& value, const Vector3& default_value)
{ {
// TODO - Increase number of digits after the decimal in floating point format (6 -> 12?) // TODO - Increase number of digits after the decimal in floating point format (6 -> 12?)
// FINDME, TODO - This needs optimization... // FINDME, TODO - This needs optimization...
@@ -46,7 +46,7 @@ void setXMLAttribute(const std::string &base_name, tinyxml2::XMLElement *e, cons
} }
} }
const Vector3 getXMLAttribute(const std::string &base_name, tinyxml2::XMLElement *e, const Vector3 &default_value) const Vector3 getXMLAttribute(const std::string& base_name, tinyxml2::XMLElement* e, const Vector3& default_value)
{ {
Vector3 value; Vector3 value;
if (e->QueryFloatAttribute((base_name + "_x").c_str(), &value.x) == tinyxml2::XML_SUCCESS if (e->QueryFloatAttribute((base_name + "_x").c_str(), &value.x) == tinyxml2::XML_SUCCESS

View File

@@ -60,7 +60,7 @@ float const PI = 3.141592653589793f;
float const D2R = PI * 2 / 360; float const D2R = PI * 2 / 360;
namespace kraken { namespace kraken {
void setXMLAttribute(const std::string &base_name, ::tinyxml2::XMLElement *e, const Vector3 &value, const Vector3 &default_value); void setXMLAttribute(const std::string& base_name, ::tinyxml2::XMLElement* e, const Vector3& value, const Vector3& default_value);
const Vector3 getXMLAttribute(const std::string &base_name, ::tinyxml2::XMLElement *e, const Vector3 &default_value); const Vector3 getXMLAttribute(const std::string& base_name, ::tinyxml2::XMLElement* e, const Vector3& default_value);
} // namespace kraken } // namespace kraken

View File

@@ -44,164 +44,164 @@ void KRLODGroup::InitNodeInfo(KrNodeInfo* nodeInfo)
nodeInfo->lod_group.use_world_units = true; nodeInfo->lod_group.use_world_units = true;
} }
KRLODGroup::KRLODGroup(KRScene &scene, std::string name) : KRNode(scene, name) KRLODGroup::KRLODGroup(KRScene& scene, std::string name) : KRNode(scene, name)
{ {
m_min_distance = 0.0f; m_min_distance = 0.0f;
m_max_distance = 0.0f; m_max_distance = 0.0f;
m_reference = AABB::Create(Vector3::Zero(), Vector3::Zero()); m_reference = AABB::Create(Vector3::Zero(), Vector3::Zero());
m_use_world_units = true; m_use_world_units = true;
} }
KRLODGroup::~KRLODGroup() KRLODGroup::~KRLODGroup()
{}
std::string KRLODGroup::getElementName()
{ {
return "lod_group";
} }
std::string KRLODGroup::getElementName() { tinyxml2::XMLElement* KRLODGroup::saveXML(tinyxml2::XMLNode* parent)
return "lod_group"; {
tinyxml2::XMLElement* e = KRNode::saveXML(parent);
e->SetAttribute("min_distance", m_min_distance);
e->SetAttribute("max_distance", m_max_distance);
e->SetAttribute("reference_min_x", m_reference.min.x);
e->SetAttribute("reference_min_y", m_reference.min.y);
e->SetAttribute("reference_min_z", m_reference.min.z);
e->SetAttribute("reference_max_x", m_reference.max.x);
e->SetAttribute("reference_max_y", m_reference.max.y);
e->SetAttribute("reference_max_z", m_reference.max.z);
e->SetAttribute("use_world_units", m_use_world_units ? "true" : "false");
return e;
} }
tinyxml2::XMLElement *KRLODGroup::saveXML( tinyxml2::XMLNode *parent) void KRLODGroup::loadXML(tinyxml2::XMLElement* e)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); KRNode::loadXML(e);
e->SetAttribute("min_distance", m_min_distance);
e->SetAttribute("max_distance", m_max_distance);
e->SetAttribute("reference_min_x", m_reference.min.x);
e->SetAttribute("reference_min_y", m_reference.min.y);
e->SetAttribute("reference_min_z", m_reference.min.z);
e->SetAttribute("reference_max_x", m_reference.max.x);
e->SetAttribute("reference_max_y", m_reference.max.y);
e->SetAttribute("reference_max_z", m_reference.max.z);
e->SetAttribute("use_world_units", m_use_world_units ? "true" : "false");
return e;
}
void KRLODGroup::loadXML(tinyxml2::XMLElement *e)
{
KRNode::loadXML(e);
m_min_distance = 0.0f;
if (e->QueryFloatAttribute("min_distance", &m_min_distance) != tinyxml2::XML_SUCCESS) {
m_min_distance = 0.0f; m_min_distance = 0.0f;
if(e->QueryFloatAttribute("min_distance", &m_min_distance) != tinyxml2::XML_SUCCESS) { }
m_min_distance = 0.0f;
} m_max_distance = 0.0f;
if (e->QueryFloatAttribute("max_distance", &m_max_distance) != tinyxml2::XML_SUCCESS) {
m_max_distance = 0.0f; m_max_distance = 0.0f;
if(e->QueryFloatAttribute("max_distance", &m_max_distance) != tinyxml2::XML_SUCCESS) { }
m_max_distance = 0.0f;
}
float x = 0.0f, y = 0.0f, z = 0.0f;
if (e->QueryFloatAttribute("reference_min_x", &x) != tinyxml2::XML_SUCCESS) {
float x=0.0f, y=0.0f, z=0.0f; x = 0.0f;
if(e->QueryFloatAttribute("reference_min_x", &x) != tinyxml2::XML_SUCCESS) { }
x = 0.0f; if (e->QueryFloatAttribute("reference_min_y", &y) != tinyxml2::XML_SUCCESS) {
} y = 0.0f;
if(e->QueryFloatAttribute("reference_min_y", &y) != tinyxml2::XML_SUCCESS) { }
y = 0.0f; if (e->QueryFloatAttribute("reference_min_z", &z) != tinyxml2::XML_SUCCESS) {
} z = 0.0f;
if(e->QueryFloatAttribute("reference_min_z", &z) != tinyxml2::XML_SUCCESS) { }
z = 0.0f;
} m_reference.min = Vector3::Create(x, y, z);
m_reference.min = Vector3::Create(x,y,z); x = 0.0f; y = 0.0f; z = 0.0f;
if (e->QueryFloatAttribute("reference_max_x", &x) != tinyxml2::XML_SUCCESS) {
x=0.0f; y=0.0f; z=0.0f; x = 0.0f;
if(e->QueryFloatAttribute("reference_max_x", &x) != tinyxml2::XML_SUCCESS) { }
x = 0.0f; if (e->QueryFloatAttribute("reference_max_y", &y) != tinyxml2::XML_SUCCESS) {
} y = 0.0f;
if(e->QueryFloatAttribute("reference_max_y", &y) != tinyxml2::XML_SUCCESS) { }
y = 0.0f; if (e->QueryFloatAttribute("reference_max_z", &z) != tinyxml2::XML_SUCCESS) {
} z = 0.0f;
if(e->QueryFloatAttribute("reference_max_z", &z) != tinyxml2::XML_SUCCESS) { }
z = 0.0f; m_reference.max = Vector3::Create(x, y, z);
}
m_reference.max = Vector3::Create(x,y,z); m_use_world_units = true;
if (e->QueryBoolAttribute("use_world_units", &m_use_world_units) != tinyxml2::XML_SUCCESS) {
m_use_world_units = true; m_use_world_units = true;
if(e->QueryBoolAttribute("use_world_units", &m_use_world_units) != tinyxml2::XML_SUCCESS) { }
m_use_world_units = true;
}
} }
const AABB &KRLODGroup::getReference() const const AABB& KRLODGroup::getReference() const
{ {
return m_reference; return m_reference;
} }
void KRLODGroup::setReference(const AABB &reference) void KRLODGroup::setReference(const AABB& reference)
{ {
m_reference = reference; m_reference = reference;
} }
KRNode::LodVisibility KRLODGroup::calcLODVisibility(const KRViewport &viewport) KRNode::LodVisibility KRLODGroup::calcLODVisibility(const KRViewport& viewport)
{ {
if(m_min_distance == 0 && m_max_distance == 0) { if (m_min_distance == 0 && m_max_distance == 0) {
return LOD_VISIBILITY_VISIBLE; return LOD_VISIBILITY_VISIBLE;
} else {
float lod_bias = viewport.getLODBias();
lod_bias = pow(2.0f, -lod_bias);
// Compare using squared distances as sqrt is expensive
float sqr_distance;
float sqr_prestream_distance;
Vector3 world_camera_position = viewport.getCameraPosition();
Vector3 local_camera_position = worldToLocal(world_camera_position);
Vector3 local_reference_point = m_reference.nearestPoint(local_camera_position);
if (m_use_world_units) {
Vector3 world_reference_point = localToWorld(local_reference_point);
sqr_distance = (world_camera_position - world_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
sqr_prestream_distance = (float)(getContext().KRENGINE_PRESTREAM_DISTANCE * getContext().KRENGINE_PRESTREAM_DISTANCE);
} else { } else {
float lod_bias = viewport.getLODBias(); sqr_distance = (local_camera_position - local_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
lod_bias = pow(2.0f, -lod_bias);
Vector3 world_reference_point = localToWorld(local_reference_point);
// Compare using squared distances as sqrt is expensive sqr_prestream_distance = worldToLocal(Vector3::Normalize(world_reference_point - world_camera_position) * (float)getContext().KRENGINE_PRESTREAM_DISTANCE).sqrMagnitude(); // TODO, FINDME - Optimize with precalc?
float sqr_distance;
float sqr_prestream_distance;
Vector3 world_camera_position = viewport.getCameraPosition();
Vector3 local_camera_position = worldToLocal(world_camera_position);
Vector3 local_reference_point = m_reference.nearestPoint(local_camera_position);
if(m_use_world_units) {
Vector3 world_reference_point = localToWorld(local_reference_point);
sqr_distance = (world_camera_position - world_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
sqr_prestream_distance = (float)(getContext().KRENGINE_PRESTREAM_DISTANCE * getContext().KRENGINE_PRESTREAM_DISTANCE);
} else {
sqr_distance = (local_camera_position - local_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
Vector3 world_reference_point = localToWorld(local_reference_point);
sqr_prestream_distance = worldToLocal(Vector3::Normalize(world_reference_point - world_camera_position) * (float)getContext().KRENGINE_PRESTREAM_DISTANCE).sqrMagnitude(); // TODO, FINDME - Optimize with precalc?
}
float sqr_min_visible_distance = m_min_distance * m_min_distance;
float sqr_max_visible_distance = m_max_distance * m_max_distance;
if((sqr_distance >= sqr_min_visible_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance || m_max_distance == 0)) {
return LOD_VISIBILITY_VISIBLE;
} else if((sqr_distance >= sqr_min_visible_distance - sqr_prestream_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance + sqr_prestream_distance || m_max_distance == 0)) {
return LOD_VISIBILITY_PRESTREAM;
} else {
return LOD_VISIBILITY_HIDDEN;
}
} }
float sqr_min_visible_distance = m_min_distance * m_min_distance;
float sqr_max_visible_distance = m_max_distance * m_max_distance;
if ((sqr_distance >= sqr_min_visible_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance || m_max_distance == 0)) {
return LOD_VISIBILITY_VISIBLE;
} else if ((sqr_distance >= sqr_min_visible_distance - sqr_prestream_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance + sqr_prestream_distance || m_max_distance == 0)) {
return LOD_VISIBILITY_PRESTREAM;
} else {
return LOD_VISIBILITY_HIDDEN;
}
}
} }
float KRLODGroup::getMinDistance() float KRLODGroup::getMinDistance()
{ {
return m_min_distance; return m_min_distance;
} }
float KRLODGroup::getMaxDistance() float KRLODGroup::getMaxDistance()
{ {
return m_max_distance; return m_max_distance;
} }
void KRLODGroup::setMinDistance(float min_distance) void KRLODGroup::setMinDistance(float min_distance)
{ {
m_min_distance = min_distance; m_min_distance = min_distance;
} }
void KRLODGroup::setMaxDistance(float max_distance) void KRLODGroup::setMaxDistance(float max_distance)
{ {
m_max_distance = max_distance; m_max_distance = max_distance;
} }
void KRLODGroup::setUseWorldUnits(bool use_world_units) void KRLODGroup::setUseWorldUnits(bool use_world_units)
{ {
m_use_world_units = use_world_units; m_use_world_units = use_world_units;
} }
bool KRLODGroup::getUseWorldUnits() const bool KRLODGroup::getUseWorldUnits() const
{ {
return m_use_world_units; return m_use_world_units;
} }

View File

@@ -34,30 +34,31 @@
#include "KRResource.h" #include "KRResource.h"
#include "KRNode.h" #include "KRNode.h"
class KRLODGroup : public KRNode { class KRLODGroup : public KRNode
{
public: public:
static void InitNodeInfo(KrNodeInfo* nodeInfo); static void InitNodeInfo(KrNodeInfo* nodeInfo);
KRLODGroup(KRScene &scene, std::string name); KRLODGroup(KRScene& scene, std::string name);
virtual ~KRLODGroup(); virtual ~KRLODGroup();
virtual std::string getElementName(); virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
virtual void loadXML(tinyxml2::XMLElement *e); virtual void loadXML(tinyxml2::XMLElement* e);
float getMinDistance(); float getMinDistance();
float getMaxDistance(); float getMaxDistance();
void setMinDistance(float min_distance); void setMinDistance(float min_distance);
void setMaxDistance(float max_distance); void setMaxDistance(float max_distance);
const AABB &getReference() const; const AABB& getReference() const;
void setReference(const AABB &reference); void setReference(const AABB& reference);
void setUseWorldUnits(bool use_world_units); void setUseWorldUnits(bool use_world_units);
bool getUseWorldUnits() const; bool getUseWorldUnits() const;
LodVisibility calcLODVisibility(const KRViewport &viewport); LodVisibility calcLODVisibility(const KRViewport& viewport);
private: private:
float m_min_distance; float m_min_distance;
float m_max_distance; float m_max_distance;
AABB m_reference; // Point of reference, used for distance calculation. Usually set to the bounding box center AABB m_reference; // Point of reference, used for distance calculation. Usually set to the bounding box center
bool m_use_world_units; bool m_use_world_units;
}; };

View File

@@ -40,109 +40,109 @@ void KRLODSet::InitNodeInfo(KrNodeInfo* nodeInfo)
// No additional members // No additional members
} }
KRLODSet::KRLODSet(KRScene &scene, std::string name) : KRNode(scene, name) KRLODSet::KRLODSet(KRScene& scene, std::string name) : KRNode(scene, name)
{ {
} }
KRLODSet::~KRLODSet() KRLODSet::~KRLODSet()
{}
std::string KRLODSet::getElementName()
{ {
return "lod_set";
} }
std::string KRLODSet::getElementName() { tinyxml2::XMLElement* KRLODSet::saveXML(tinyxml2::XMLNode* parent)
return "lod_set"; {
tinyxml2::XMLElement* e = KRNode::saveXML(parent);
return e;
} }
tinyxml2::XMLElement *KRLODSet::saveXML( tinyxml2::XMLNode *parent) void KRLODSet::loadXML(tinyxml2::XMLElement* e)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); KRNode::loadXML(e);
return e;
}
void KRLODSet::loadXML(tinyxml2::XMLElement *e)
{
KRNode::loadXML(e);
} }
void KRLODSet::updateLODVisibility(const KRViewport &viewport) void KRLODSet::updateLODVisibility(const KRViewport& viewport)
{ {
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM) { if (m_lod_visible >= LOD_VISIBILITY_PRESTREAM) {
/* /*
// FINDME, TODO, HACK - Disabled streamer delayed LOD load due to performance issues: // FINDME, TODO, HACK - Disabled streamer delayed LOD load due to performance issues:
KRLODGroup *new_active_lod_group = NULL; KRLODGroup *new_active_lod_group = NULL;
*/ */
// Upgrade and downgrade LOD groups as needed // Upgrade and downgrade LOD groups as needed
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { for (std::set<KRNode*>::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
KRLODGroup *lod_group = dynamic_cast<KRLODGroup *>(*itr); KRLODGroup* lod_group = dynamic_cast<KRLODGroup*>(*itr);
assert(lod_group != NULL); assert(lod_group != NULL);
LodVisibility group_lod_visibility = KRMIN(lod_group->calcLODVisibility(viewport), m_lod_visible); LodVisibility group_lod_visibility = KRMIN(lod_group->calcLODVisibility(viewport), m_lod_visible);
/* /*
// FINDME, TODO, HACK - Disabled streamer delayed LOD load due to performance issues: // FINDME, TODO, HACK - Disabled streamer delayed LOD load due to performance issues:
if(group_lod_visibility == LOD_VISIBILITY_VISIBLE) { if(group_lod_visibility == LOD_VISIBILITY_VISIBLE) {
new_active_lod_group = lod_group; new_active_lod_group = lod_group;
} }
*/ */
lod_group->setLODVisibility(group_lod_visibility); lod_group->setLODVisibility(group_lod_visibility);
}
/*
// FINDME, TODO, HACK - Disabled streamer delayed LOD load due to performance issues:
bool streamer_ready = false;
if(new_active_lod_group == NULL) {
streamer_ready = true;
} else if(new_active_lod_group->getStreamLevel(viewport) >= kraken_stream_level::STREAM_LEVEL_IN_LQ) {
streamer_ready = true;
}
*/
bool streamer_ready = true;
if(streamer_ready) {
// Upgrade and downgrade LOD groups as needed
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
KRLODGroup *lod_group = dynamic_cast<KRLODGroup *>(*itr);
assert(lod_group != NULL);
LodVisibility group_lod_visibility = KRMIN(lod_group->calcLODVisibility(viewport), m_lod_visible);
lod_group->setLODVisibility(group_lod_visibility);
}
}
KRNode::updateLODVisibility(viewport);
} }
/*
// FINDME, TODO, HACK - Disabled streamer delayed LOD load due to performance issues:
bool streamer_ready = false;
if(new_active_lod_group == NULL) {
streamer_ready = true;
} else if(new_active_lod_group->getStreamLevel(viewport) >= kraken_stream_level::STREAM_LEVEL_IN_LQ) {
streamer_ready = true;
}
*/
bool streamer_ready = true;
if (streamer_ready) {
// Upgrade and downgrade LOD groups as needed
for (std::set<KRNode*>::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
KRLODGroup* lod_group = dynamic_cast<KRLODGroup*>(*itr);
assert(lod_group != NULL);
LodVisibility group_lod_visibility = KRMIN(lod_group->calcLODVisibility(viewport), m_lod_visible);
lod_group->setLODVisibility(group_lod_visibility);
}
}
KRNode::updateLODVisibility(viewport);
}
} }
void KRLODSet::setLODVisibility(KRNode::LodVisibility lod_visibility) void KRLODSet::setLODVisibility(KRNode::LodVisibility lod_visibility)
{ {
if(lod_visibility == LOD_VISIBILITY_HIDDEN) { if (lod_visibility == LOD_VISIBILITY_HIDDEN) {
KRNode::setLODVisibility(lod_visibility); KRNode::setLODVisibility(lod_visibility);
} else if(m_lod_visible != lod_visibility) { } else if (m_lod_visible != lod_visibility) {
// Don't automatically recurse into our children, as only one of those will be activated, by updateLODVisibility // Don't automatically recurse into our children, as only one of those will be activated, by updateLODVisibility
if(m_lod_visible == LOD_VISIBILITY_HIDDEN && lod_visibility >= LOD_VISIBILITY_PRESTREAM) { if (m_lod_visible == LOD_VISIBILITY_HIDDEN && lod_visibility >= LOD_VISIBILITY_PRESTREAM) {
getScene().notify_sceneGraphCreate(this); getScene().notify_sceneGraphCreate(this);
}
m_lod_visible = lod_visibility;
} }
m_lod_visible = lod_visibility;
}
} }
kraken_stream_level KRLODSet::getStreamLevel(const KRViewport &viewport) kraken_stream_level KRLODSet::getStreamLevel(const KRViewport& viewport)
{ {
KRLODGroup *new_active_lod_group = NULL; KRLODGroup* new_active_lod_group = NULL;
// Upgrade and downgrade LOD groups as needed // Upgrade and downgrade LOD groups as needed
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) { for (std::set<KRNode*>::iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
KRLODGroup *lod_group = dynamic_cast<KRLODGroup *>(*itr); KRLODGroup* lod_group = dynamic_cast<KRLODGroup*>(*itr);
assert(lod_group != NULL); assert(lod_group != NULL);
if(lod_group->calcLODVisibility(viewport) == LOD_VISIBILITY_VISIBLE) { if (lod_group->calcLODVisibility(viewport) == LOD_VISIBILITY_VISIBLE) {
new_active_lod_group = lod_group; new_active_lod_group = lod_group;
}
}
if(new_active_lod_group) {
return new_active_lod_group->getStreamLevel(viewport);
} else {
return kraken_stream_level::STREAM_LEVEL_IN_HQ;
} }
}
if (new_active_lod_group) {
return new_active_lod_group->getStreamLevel(viewport);
} else {
return kraken_stream_level::STREAM_LEVEL_IN_HQ;
}
} }

View File

@@ -36,18 +36,19 @@
class KRLODGroup; class KRLODGroup;
class KRLODSet : public KRNode { class KRLODSet : public KRNode
{
public: public:
static void InitNodeInfo(KrNodeInfo* nodeInfo); static void InitNodeInfo(KrNodeInfo* nodeInfo);
KRLODSet(KRScene &scene, std::string name); KRLODSet(KRScene& scene, std::string name);
virtual ~KRLODSet(); virtual ~KRLODSet();
virtual std::string getElementName(); virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
virtual void loadXML(tinyxml2::XMLElement *e); virtual void loadXML(tinyxml2::XMLElement* e);
virtual void updateLODVisibility(const KRViewport &viewport); virtual void updateLODVisibility(const KRViewport& viewport);
virtual void setLODVisibility(LodVisibility lod_visibility); virtual void setLODVisibility(LodVisibility lod_visibility);
virtual kraken_stream_level getStreamLevel(const KRViewport &viewport); virtual kraken_stream_level getStreamLevel(const KRViewport& viewport);
}; };

View File

@@ -60,497 +60,509 @@ void KRLight::InitNodeInfo(KrNodeInfo* nodeInfo)
nodeInfo->light.light_shafts = true; nodeInfo->light.light_shafts = true;
} }
KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name) KRLight::KRLight(KRScene& scene, std::string name) : KRNode(scene, name)
{ {
m_intensity = 1.0f; m_intensity = 1.0f;
m_dust_particle_intensity = 1.0f; m_dust_particle_intensity = 1.0f;
m_color = Vector3::One(); m_color = Vector3::One();
m_flareTexture = ""; m_flareTexture = "";
m_pFlareTexture = NULL; m_pFlareTexture = NULL;
m_flareSize = 0.0f; m_flareSize = 0.0f;
m_flareOcclusionSize = 0.05f; m_flareOcclusionSize = 0.05f;
m_casts_shadow = true; m_casts_shadow = true;
m_light_shafts = true; m_light_shafts = true;
m_dust_particle_density = 0.1f; m_dust_particle_density = 0.1f;
m_dust_particle_size = 1.0f; m_dust_particle_size = 1.0f;
m_dust_particle_intensity = 1.0f; m_dust_particle_intensity = 1.0f;
m_occlusionQuery = 0; m_occlusionQuery = 0;
m_decayStart = 0; m_decayStart = 0;
// Initialize shadow buffers // Initialize shadow buffers
m_cShadowBuffers = 0; m_cShadowBuffers = 0;
for(int iBuffer=0; iBuffer < KRENGINE_MAX_SHADOW_BUFFERS; iBuffer++) { for (int iBuffer = 0; iBuffer < KRENGINE_MAX_SHADOW_BUFFERS; iBuffer++) {
shadowFramebuffer[iBuffer] = 0; shadowFramebuffer[iBuffer] = 0;
shadowDepthTexture[iBuffer] = 0; shadowDepthTexture[iBuffer] = 0;
shadowValid[iBuffer] = false; shadowValid[iBuffer] = false;
} }
} }
KRLight::~KRLight() KRLight::~KRLight()
{ {
if(m_occlusionQuery) { if (m_occlusionQuery) {
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery)); GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
m_occlusionQuery = 0; m_occlusionQuery = 0;
} }
allocateShadowBuffers(0); allocateShadowBuffers(0);
} }
tinyxml2::XMLElement *KRLight::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement* KRLight::saveXML(tinyxml2::XMLNode* parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement* e = KRNode::saveXML(parent);
e->SetAttribute("intensity", m_intensity); e->SetAttribute("intensity", m_intensity);
e->SetAttribute("color_r", m_color.x); e->SetAttribute("color_r", m_color.x);
e->SetAttribute("color_g", m_color.y); e->SetAttribute("color_g", m_color.y);
e->SetAttribute("color_b", m_color.z); e->SetAttribute("color_b", m_color.z);
e->SetAttribute("decay_start", m_decayStart); e->SetAttribute("decay_start", m_decayStart);
e->SetAttribute("flare_size", m_flareSize); e->SetAttribute("flare_size", m_flareSize);
e->SetAttribute("flare_occlusion_size", m_flareOcclusionSize); e->SetAttribute("flare_occlusion_size", m_flareOcclusionSize);
e->SetAttribute("flare_texture", m_flareTexture.c_str()); e->SetAttribute("flare_texture", m_flareTexture.c_str());
e->SetAttribute("casts_shadow", m_casts_shadow ? "true" : "false"); e->SetAttribute("casts_shadow", m_casts_shadow ? "true" : "false");
e->SetAttribute("light_shafts", m_light_shafts ? "true" : "false"); e->SetAttribute("light_shafts", m_light_shafts ? "true" : "false");
e->SetAttribute("dust_particle_density", m_dust_particle_density); e->SetAttribute("dust_particle_density", m_dust_particle_density);
e->SetAttribute("dust_particle_size", m_dust_particle_size); e->SetAttribute("dust_particle_size", m_dust_particle_size);
e->SetAttribute("dust_particle_intensity", m_dust_particle_intensity); e->SetAttribute("dust_particle_intensity", m_dust_particle_intensity);
return e; return e;
} }
void KRLight::loadXML(tinyxml2::XMLElement *e) { void KRLight::loadXML(tinyxml2::XMLElement* e)
KRNode::loadXML(e); {
float x=1.0f,y=1.0f,z=1.0f; KRNode::loadXML(e);
if(e->QueryFloatAttribute("color_r", &x) != tinyxml2::XML_SUCCESS) { float x = 1.0f, y = 1.0f, z = 1.0f;
x = 1.0; if (e->QueryFloatAttribute("color_r", &x) != tinyxml2::XML_SUCCESS) {
} x = 1.0;
if(e->QueryFloatAttribute("color_g", &y) != tinyxml2::XML_SUCCESS) { }
y = 1.0; if (e->QueryFloatAttribute("color_g", &y) != tinyxml2::XML_SUCCESS) {
} y = 1.0;
if(e->QueryFloatAttribute("color_b", &z) != tinyxml2::XML_SUCCESS) { }
z = 1.0; if (e->QueryFloatAttribute("color_b", &z) != tinyxml2::XML_SUCCESS) {
} z = 1.0;
m_color = Vector3::Create(x,y,z); }
m_color = Vector3::Create(x, y, z);
if(e->QueryFloatAttribute("intensity", &m_intensity) != tinyxml2::XML_SUCCESS) {
m_intensity = 100.0; if (e->QueryFloatAttribute("intensity", &m_intensity) != tinyxml2::XML_SUCCESS) {
} m_intensity = 100.0;
}
if(e->QueryFloatAttribute("decay_start", &m_decayStart) != tinyxml2::XML_SUCCESS) {
m_decayStart = 0.0; if (e->QueryFloatAttribute("decay_start", &m_decayStart) != tinyxml2::XML_SUCCESS) {
} m_decayStart = 0.0;
}
if(e->QueryFloatAttribute("flare_size", &m_flareSize) != tinyxml2::XML_SUCCESS) {
m_flareSize = 0.0; if (e->QueryFloatAttribute("flare_size", &m_flareSize) != tinyxml2::XML_SUCCESS) {
} m_flareSize = 0.0;
}
if(e->QueryFloatAttribute("flare_occlusion_size", &m_flareOcclusionSize) != tinyxml2::XML_SUCCESS) {
m_flareOcclusionSize = 0.05f; if (e->QueryFloatAttribute("flare_occlusion_size", &m_flareOcclusionSize) != tinyxml2::XML_SUCCESS) {
} m_flareOcclusionSize = 0.05f;
}
if(e->QueryBoolAttribute("casts_shadow", &m_casts_shadow) != tinyxml2::XML_SUCCESS) {
m_casts_shadow = true; if (e->QueryBoolAttribute("casts_shadow", &m_casts_shadow) != tinyxml2::XML_SUCCESS) {
} m_casts_shadow = true;
}
if(e->QueryBoolAttribute("light_shafts", &m_light_shafts) != tinyxml2::XML_SUCCESS) {
m_light_shafts = true; if (e->QueryBoolAttribute("light_shafts", &m_light_shafts) != tinyxml2::XML_SUCCESS) {
} m_light_shafts = true;
}
m_dust_particle_density = 0.1f;
if (e->QueryFloatAttribute("dust_particle_density", &m_dust_particle_density) != tinyxml2::XML_SUCCESS) {
m_dust_particle_density = 0.1f; m_dust_particle_density = 0.1f;
if(e->QueryFloatAttribute("dust_particle_density", &m_dust_particle_density) != tinyxml2::XML_SUCCESS) { }
m_dust_particle_density = 0.1f;
} m_dust_particle_size = 1.0f;
if (e->QueryFloatAttribute("dust_particle_size", &m_dust_particle_size) != tinyxml2::XML_SUCCESS) {
m_dust_particle_size = 1.0f; m_dust_particle_size = 1.0f;
if(e->QueryFloatAttribute("dust_particle_size", &m_dust_particle_size) != tinyxml2::XML_SUCCESS) { }
m_dust_particle_size = 1.0f;
} m_dust_particle_intensity = 1.0f;
if (e->QueryFloatAttribute("dust_particle_intensity", &m_dust_particle_intensity) != tinyxml2::XML_SUCCESS) {
m_dust_particle_intensity = 1.0f; m_dust_particle_intensity = 1.0f;
if(e->QueryFloatAttribute("dust_particle_intensity", &m_dust_particle_intensity) != tinyxml2::XML_SUCCESS) { }
m_dust_particle_intensity = 1.0f;
} const char* szFlareTexture = e->Attribute("flare_texture");
if (szFlareTexture) {
const char *szFlareTexture = e->Attribute("flare_texture"); m_flareTexture = szFlareTexture;
if(szFlareTexture) { } else {
m_flareTexture = szFlareTexture; m_flareTexture = "";
} else { }
m_flareTexture = ""; m_pFlareTexture = NULL;
}
m_pFlareTexture = NULL;
} }
void KRLight::setFlareTexture(std::string flare_texture) { void KRLight::setFlareTexture(std::string flare_texture)
m_flareTexture = flare_texture; {
m_pFlareTexture = NULL; m_flareTexture = flare_texture;
m_pFlareTexture = NULL;
} }
void KRLight::setFlareSize(float flare_size) { void KRLight::setFlareSize(float flare_size)
m_flareSize = flare_size; {
m_flareSize = flare_size;
} }
void KRLight::setFlareOcclusionSize(float occlusion_size) { void KRLight::setFlareOcclusionSize(float occlusion_size)
m_flareOcclusionSize = occlusion_size; {
m_flareOcclusionSize = occlusion_size;
} }
void KRLight::setIntensity(float intensity) { void KRLight::setIntensity(float intensity)
m_intensity = intensity; {
m_intensity = intensity;
} }
float KRLight::getIntensity() { float KRLight::getIntensity()
return m_intensity; {
return m_intensity;
} }
const Vector3 &KRLight::getColor() { const Vector3& KRLight::getColor()
return m_color; {
return m_color;
} }
void KRLight::setColor(const Vector3 &color) { void KRLight::setColor(const Vector3& color)
m_color = color; {
m_color = color;
} }
void KRLight::setDecayStart(float decayStart) { void KRLight::setDecayStart(float decayStart)
m_decayStart = decayStart; {
m_decayStart = decayStart;
} }
float KRLight::getDecayStart() { float KRLight::getDecayStart()
return m_decayStart; {
return m_decayStart;
} }
void KRLight::render(RenderInfo& ri) { void KRLight::render(RenderInfo& ri)
{
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if (m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(ri);
if(ri.renderPass == KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && (ri.camera->settings.volumetric_environment_enable || ri.camera->settings.dust_particle_enable || (ri.camera->settings.m_cShadowBuffers > 0 && m_casts_shadow))) {
allocateShadowBuffers(configureShadowBufferViewports(ri.viewport));
renderShadowBuffers(ri);
}
if(ri.renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES && ri.camera->settings.dust_particle_enable) {
// Render brownian particles for dust floating in air
if(m_cShadowBuffers >= 1 && shadowValid[0] && m_dust_particle_density > 0.0f && m_dust_particle_size > 0.0f && m_dust_particle_intensity > 0.0f) {
if(ri.viewport.visible(getBounds()) || true) { // FINDME, HACK need to remove "|| true"?
float particle_range = 600.0f;
int particle_count = (int)(m_dust_particle_density * pow(particle_range, 3));
if (particle_count > KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES) {
particle_count = KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES;
}
Matrix4 particleModelMatrix; KRNode::render(ri);
particleModelMatrix.scale(particle_range); // Scale the box symetrically to ensure that we don't have an uneven distribution of particles for different angles of the view frustrum
particleModelMatrix.translate(ri.viewport.getCameraPosition());
std::vector<KRDirectionalLight *> this_directional_light;
std::vector<KRSpotLight *> this_spot_light;
std::vector<KRPointLight *> this_point_light;
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
if(directional_light) {
this_directional_light.push_back(directional_light);
}
if(spot_light) {
this_spot_light.push_back(spot_light);
}
if(point_light) {
this_point_light.push_back(point_light);
}
PipelineInfo info{};
std::string shader_name("dust_particle");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &this_point_light;
info.directional_lights = &this_directional_light;
info.spot_lights = &this_spot_light;
info.renderPass = ri.renderPass;
info.rasterMode = RasterMode::kAdditive;
info.cullMode = CullMode::kCullNone;
info.vertexAttributes = (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA);
info.modelFormat = ModelFormat::KRENGINE_MODEL_FORMAT_TRIANGLES;
KRPipeline *pParticleShader = m_pContext->getPipelineManager()->getPipeline(*ri.surface, info);
pParticleShader->setUniform(KRPipeline::Uniform::light_color, m_color * ri.camera->settings.dust_particle_intensity * m_dust_particle_intensity * m_intensity); if (ri.renderPass == KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && (ri.camera->settings.volumetric_environment_enable || ri.camera->settings.dust_particle_enable || (ri.camera->settings.m_cShadowBuffers > 0 && m_casts_shadow))) {
pParticleShader->setUniform(KRPipeline::Uniform::particle_origin, Matrix4::DotWDiv(Matrix4::Invert(particleModelMatrix), Vector3::Zero())); allocateShadowBuffers(configureShadowBufferViewports(ri.viewport));
pParticleShader->setUniform(KRPipeline::Uniform::flare_size, m_dust_particle_size); renderShadowBuffers(ri);
pParticleShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, particleModelMatrix, &this_point_light, &this_directional_light, &this_spot_light, ri.renderPass); }
m_pContext->getMeshManager()->bindVBO(ri.commandBuffer, &m_pContext->getMeshManager()->KRENGINE_VBO_DATA_RANDOM_PARTICLES, 1.0f);
vkCmdDraw(ri.commandBuffer, particle_count * 3, 1, 0, 0); if (ri.renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES && ri.camera->settings.dust_particle_enable) {
} // Render brownian particles for dust floating in air
if (m_cShadowBuffers >= 1 && shadowValid[0] && m_dust_particle_density > 0.0f && m_dust_particle_size > 0.0f && m_dust_particle_intensity > 0.0f) {
if (ri.viewport.visible(getBounds()) || true) { // FINDME, HACK need to remove "|| true"?
float particle_range = 600.0f;
int particle_count = (int)(m_dust_particle_density * pow(particle_range, 3));
if (particle_count > KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES) {
particle_count = KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES;
} }
}
Matrix4 particleModelMatrix;
if(ri.renderPass == KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && ri.camera->settings.volumetric_environment_enable && m_light_shafts) { particleModelMatrix.scale(particle_range); // Scale the box symetrically to ensure that we don't have an uneven distribution of particles for different angles of the view frustrum
std::string shader_name = ri.camera->settings.volumetric_environment_downsample != 0 ? "volumetric_fog_downsampled" : "volumetric_fog"; particleModelMatrix.translate(ri.viewport.getCameraPosition());
std::vector<KRDirectionalLight *> this_directional_light; std::vector<KRDirectionalLight*> this_directional_light;
std::vector<KRSpotLight *> this_spot_light; std::vector<KRSpotLight*> this_spot_light;
std::vector<KRPointLight *> this_point_light; std::vector<KRPointLight*> this_point_light;
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this); KRDirectionalLight* directional_light = dynamic_cast<KRDirectionalLight*>(this);
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this); KRSpotLight* spot_light = dynamic_cast<KRSpotLight*>(this);
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this); KRPointLight* point_light = dynamic_cast<KRPointLight*>(this);
if(directional_light) { if (directional_light) {
this_directional_light.push_back(directional_light); this_directional_light.push_back(directional_light);
} }
if(spot_light) { if (spot_light) {
this_spot_light.push_back(spot_light); this_spot_light.push_back(spot_light);
} }
if(point_light) { if (point_light) {
this_point_light.push_back(point_light); this_point_light.push_back(point_light);
} }
PipelineInfo info{}; PipelineInfo info{};
std::string shader_name("dust_particle");
info.shader_name = &shader_name; info.shader_name = &shader_name;
info.pCamera = ri.camera; info.pCamera = ri.camera;
info.point_lights = &this_point_light; info.point_lights = &this_point_light;
info.directional_lights = &this_directional_light; info.directional_lights = &this_directional_light;
info.spot_lights = &this_spot_light; info.spot_lights = &this_spot_light;
info.renderPass = KRNode::RENDER_PASS_ADDITIVE_PARTICLES; info.renderPass = ri.renderPass;
info.rasterMode = RasterMode::kAdditive; info.rasterMode = RasterMode::kAdditive;
info.cullMode = CullMode::kCullNone; info.cullMode = CullMode::kCullNone;
info.vertexAttributes = (1 << KRMesh::KRENGINE_ATTRIB_VERTEX); info.vertexAttributes = (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA);
info.modelFormat = ModelFormat::KRENGINE_MODEL_FORMAT_TRIANGLES; info.modelFormat = ModelFormat::KRENGINE_MODEL_FORMAT_TRIANGLES;
KRPipeline* pParticleShader = m_pContext->getPipelineManager()->getPipeline(*ri.surface, info);
KRPipeline *pFogShader = m_pContext->getPipelineManager()->getPipeline(*ri.surface, info);
int slice_count = (int)(ri.camera->settings.volumetric_environment_quality * 495.0) + 5; pParticleShader->setUniform(KRPipeline::Uniform::light_color, m_color * ri.camera->settings.dust_particle_intensity * m_dust_particle_intensity * m_intensity);
pParticleShader->setUniform(KRPipeline::Uniform::particle_origin, Matrix4::DotWDiv(Matrix4::Invert(particleModelMatrix), Vector3::Zero()));
float slice_near = -ri.camera->settings.getPerspectiveNearZ(); pParticleShader->setUniform(KRPipeline::Uniform::flare_size, m_dust_particle_size);
float slice_far = -ri.camera->settings.volumetric_environment_max_distance; pParticleShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, particleModelMatrix, &this_point_light, &this_directional_light, &this_spot_light, ri.renderPass);
float slice_spacing = (slice_far - slice_near) / slice_count;
pFogShader->setUniform(KRPipeline::Uniform::slice_depth_scale, Vector2::Create(slice_near, slice_spacing));
pFogShader->setUniform(KRPipeline::Uniform::light_color, (m_color * ri.camera->settings.volumetric_environment_intensity * m_intensity * -slice_spacing / 1000.0f));
pFogShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, Matrix4(), &this_point_light, &this_directional_light, &this_spot_light, KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE);
m_pContext->getMeshManager()->bindVBO(ri.commandBuffer, &m_pContext->getMeshManager()->KRENGINE_VBO_DATA_VOLUMETRIC_LIGHTING, 1.0f);
vkCmdDraw(ri.commandBuffer, slice_count * 6, 1, 0, 0);
m_pContext->getMeshManager()->bindVBO(ri.commandBuffer, &m_pContext->getMeshManager()->KRENGINE_VBO_DATA_RANDOM_PARTICLES, 1.0f);
vkCmdDraw(ri.commandBuffer, particle_count * 3, 1, 0, 0);
}
} }
}
if(ri.renderPass == KRNode::RENDER_PASS_PARTICLE_OCCLUSION) {
if(m_flareTexture.size() && m_flareSize > 0.0f) {
KRMesh* sphereModel = getContext().getMeshManager()->getMaxLODModel("__sphere");
if (sphereModel) {
Matrix4 occlusion_test_sphere_matrix = Matrix4();
occlusion_test_sphere_matrix.scale(m_localScale * m_flareOcclusionSize);
occlusion_test_sphere_matrix.translate(m_localTranslation);
if(m_parentNode) {
occlusion_test_sphere_matrix *= m_parentNode->getModelMatrix();
}
PipelineInfo info{};
std::string shader_name("occlusion_test");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &ri.point_lights;
info.directional_lights = &ri.directional_lights;
info.spot_lights = &ri.spot_lights;
info.renderPass = ri.renderPass;
info.rasterMode = RasterMode::kAdditive;
info.cullMode = CullMode::kCullNone;
info.modelFormat = sphereModel->getModelFormat();
info.vertexAttributes = sphereModel->getVertexAttributes();
KRPipeline* pPipeline = getContext().getPipelineManager()->getPipeline(*ri.surface, info); if (ri.renderPass == KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && ri.camera->settings.volumetric_environment_enable && m_light_shafts) {
pPipeline->bind(ri.commandBuffer, *info.pCamera, ri.viewport, occlusion_test_sphere_matrix, info.point_lights, info.directional_lights, info.spot_lights, info.renderPass); std::string shader_name = ri.camera->settings.volumetric_environment_downsample != 0 ? "volumetric_fog_downsampled" : "volumetric_fog";
GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery)); std::vector<KRDirectionalLight*> this_directional_light;
#if TARGET_OS_IPHONE || defined(ANDROID) std::vector<KRSpotLight*> this_spot_light;
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery)); std::vector<KRPointLight*> this_point_light;
#else KRDirectionalLight* directional_light = dynamic_cast<KRDirectionalLight*>(this);
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery)); KRSpotLight* spot_light = dynamic_cast<KRSpotLight*>(this);
#endif KRPointLight* point_light = dynamic_cast<KRPointLight*>(this);
if (directional_light) {
this_directional_light.push_back(directional_light);
}
if (spot_light) {
this_spot_light.push_back(spot_light);
}
if (point_light) {
this_point_light.push_back(point_light);
}
sphereModel->renderNoMaterials(ri.commandBuffer, ri.renderPass, getName(), "occlusion_test", 1.0f); PipelineInfo info{};
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &this_point_light;
info.directional_lights = &this_directional_light;
info.spot_lights = &this_spot_light;
info.renderPass = KRNode::RENDER_PASS_ADDITIVE_PARTICLES;
info.rasterMode = RasterMode::kAdditive;
info.cullMode = CullMode::kCullNone;
info.vertexAttributes = (1 << KRMesh::KRENGINE_ATTRIB_VERTEX);
info.modelFormat = ModelFormat::KRENGINE_MODEL_FORMAT_TRIANGLES;
KRPipeline* pFogShader = m_pContext->getPipelineManager()->getPipeline(*ri.surface, info);
int slice_count = (int)(ri.camera->settings.volumetric_environment_quality * 495.0) + 5;
float slice_near = -ri.camera->settings.getPerspectiveNearZ();
float slice_far = -ri.camera->settings.volumetric_environment_max_distance;
float slice_spacing = (slice_far - slice_near) / slice_count;
pFogShader->setUniform(KRPipeline::Uniform::slice_depth_scale, Vector2::Create(slice_near, slice_spacing));
pFogShader->setUniform(KRPipeline::Uniform::light_color, (m_color * ri.camera->settings.volumetric_environment_intensity * m_intensity * -slice_spacing / 1000.0f));
pFogShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, Matrix4(), &this_point_light, &this_directional_light, &this_spot_light, KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE);
m_pContext->getMeshManager()->bindVBO(ri.commandBuffer, &m_pContext->getMeshManager()->KRENGINE_VBO_DATA_VOLUMETRIC_LIGHTING, 1.0f);
vkCmdDraw(ri.commandBuffer, slice_count * 6, 1, 0, 0);
}
if (ri.renderPass == KRNode::RENDER_PASS_PARTICLE_OCCLUSION) {
if (m_flareTexture.size() && m_flareSize > 0.0f) {
KRMesh* sphereModel = getContext().getMeshManager()->getMaxLODModel("__sphere");
if (sphereModel) {
Matrix4 occlusion_test_sphere_matrix = Matrix4();
occlusion_test_sphere_matrix.scale(m_localScale * m_flareOcclusionSize);
occlusion_test_sphere_matrix.translate(m_localTranslation);
if (m_parentNode) {
occlusion_test_sphere_matrix *= m_parentNode->getModelMatrix();
}
PipelineInfo info{};
std::string shader_name("occlusion_test");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &ri.point_lights;
info.directional_lights = &ri.directional_lights;
info.spot_lights = &ri.spot_lights;
info.renderPass = ri.renderPass;
info.rasterMode = RasterMode::kAdditive;
info.cullMode = CullMode::kCullNone;
info.modelFormat = sphereModel->getModelFormat();
info.vertexAttributes = sphereModel->getVertexAttributes();
KRPipeline* pPipeline = getContext().getPipelineManager()->getPipeline(*ri.surface, info);
pPipeline->bind(ri.commandBuffer, *info.pCamera, ri.viewport, occlusion_test_sphere_matrix, info.point_lights, info.directional_lights, info.spot_lights, info.renderPass);
GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery));
#if TARGET_OS_IPHONE || defined(ANDROID)
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
#else
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
#endif
sphereModel->renderNoMaterials(ri.commandBuffer, ri.renderPass, getName(), "occlusion_test", 1.0f);
#if TARGET_OS_IPHONE || defined(ANDROID) #if TARGET_OS_IPHONE || defined(ANDROID)
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT)); GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
#else #else
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED)); GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
#endif #endif
} }
}
} }
}
if(ri.renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
if(m_flareTexture.size() && m_flareSize > 0.0f) {
if(m_occlusionQuery) {
GLuint params = 0;
GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, &params));
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
if(params) {
if(!m_pFlareTexture && m_flareTexture.size()) {
m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture);
}
if(m_pFlareTexture) {
KRMeshManager::KRVBOData& vertices = getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES;
// Render light flare on transparency pass if (ri.renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
PipelineInfo info{}; if (m_flareTexture.size() && m_flareSize > 0.0f) {
std::string shader_name("flare");
info.shader_name = &shader_name; if (m_occlusionQuery) {
info.pCamera = ri.camera; GLuint params = 0;
info.point_lights = &ri.point_lights; GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, &params));
info.directional_lights = &ri.directional_lights; GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
info.spot_lights = &ri.spot_lights;
info.renderPass = ri.renderPass; if (params) {
info.rasterMode = RasterMode::kAdditiveNoTest;
info.cullMode = CullMode::kCullNone; if (!m_pFlareTexture && m_flareTexture.size()) {
info.vertexAttributes = vertices.getVertexAttributes(); m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture);
info.modelFormat = ModelFormat::KRENGINE_MODEL_FORMAT_STRIP; }
if (m_pFlareTexture) {
KRMeshManager::KRVBOData& vertices = getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES;
// Render light flare on transparency pass
PipelineInfo info{};
std::string shader_name("flare");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &ri.point_lights;
info.directional_lights = &ri.directional_lights;
info.spot_lights = &ri.spot_lights;
info.renderPass = ri.renderPass;
info.rasterMode = RasterMode::kAdditiveNoTest;
info.cullMode = CullMode::kCullNone;
info.vertexAttributes = vertices.getVertexAttributes();
info.modelFormat = ModelFormat::KRENGINE_MODEL_FORMAT_STRIP;
KRPipeline *pShader = getContext().getPipelineManager()->getPipeline(*ri.surface, info); KRPipeline* pShader = getContext().getPipelineManager()->getPipeline(*ri.surface, info);
pShader->setUniform(KRPipeline::Uniform::material_alpha, 1.0f); pShader->setUniform(KRPipeline::Uniform::material_alpha, 1.0f);
pShader->setUniform(KRPipeline::Uniform::flare_size, m_flareSize); pShader->setUniform(KRPipeline::Uniform::flare_size, m_flareSize);
pShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, getModelMatrix(), &ri.point_lights, &ri.directional_lights, &ri.spot_lights, ri.renderPass); pShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, getModelMatrix(), &ri.point_lights, &ri.directional_lights, &ri.spot_lights, ri.renderPass);
m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture, 0.0f, KRTexture::TEXTURE_USAGE_LIGHT_FLARE); m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture, 0.0f, KRTexture::TEXTURE_USAGE_LIGHT_FLARE);
m_pContext->getMeshManager()->bindVBO(ri.commandBuffer, &vertices, 1.0f); m_pContext->getMeshManager()->bindVBO(ri.commandBuffer, &vertices, 1.0f);
vkCmdDraw(ri.commandBuffer, 4, 1, 0, 0); vkCmdDraw(ri.commandBuffer, 4, 1, 0, 0);
} }
}
}
} }
}
} }
}
} }
void KRLight::allocateShadowBuffers(int cBuffers) { void KRLight::allocateShadowBuffers(int cBuffers)
// First deallocate buffers no longer needed {
for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) { // First deallocate buffers no longer needed
if (shadowDepthTexture[iShadow]) { for (int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) {
GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow)); if (shadowDepthTexture[iShadow]) {
shadowDepthTexture[iShadow] = 0; GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow));
} shadowDepthTexture[iShadow] = 0;
if (shadowFramebuffer[iShadow]) {
GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow));
shadowFramebuffer[iShadow] = 0;
}
} }
// Allocate newly required buffers if (shadowFramebuffer[iShadow]) {
for(int iShadow = 0; iShadow < cBuffers; iShadow++) { GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow));
Vector2 viewportSize = m_shadowViewports[iShadow].getSize(); shadowFramebuffer[iShadow] = 0;
}
if(!shadowDepthTexture[iShadow]) { }
shadowValid[iShadow] = false;
// Allocate newly required buffers
GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow)); for (int iShadow = 0; iShadow < cBuffers; iShadow++) {
GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow)); Vector2 viewportSize = m_shadowViewports[iShadow].getSize();
// ===== Create offscreen shadow framebuffer object =====
if (!shadowDepthTexture[iShadow]) {
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow])); shadowValid[iShadow] = false;
// ----- Create Depth Texture for shadowFramebuffer ----- GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow));
GLDEBUG( glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow])); GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); // ===== Create offscreen shadow framebuffer object =====
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
m_pContext->getTextureManager()->_setWrapModeS(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE); GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
m_pContext->getTextureManager()->_setWrapModeT(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
// ----- Create Depth Texture for shadowFramebuffer -----
GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow]));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
m_pContext->getTextureManager()->_setWrapModeS(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
m_pContext->getTextureManager()->_setWrapModeT(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
#if GL_EXT_shadow_samplers #if GL_EXT_shadow_samplers
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_COMPARE_REF_TO_TEXTURE_EXT)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_COMPARE_REF_TO_TEXTURE_EXT)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_EXT, GL_LEQUAL)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_EXT, GL_LEQUAL)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
#endif #endif
GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, (GLsizei)viewportSize.x, (GLsizei)viewportSize.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL)); GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, (GLsizei)viewportSize.x, (GLsizei)viewportSize.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0)); GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
}
} }
}
m_cShadowBuffers = cBuffers;
m_cShadowBuffers = cBuffers;
} }
void KRLight::deleteBuffers() void KRLight::deleteBuffers()
{ {
// Called when this light wasn't used in the last frame, so we can free the resources for use by other lights // Called when this light wasn't used in the last frame, so we can free the resources for use by other lights
allocateShadowBuffers(0); allocateShadowBuffers(0);
} }
void KRLight::invalidateShadowBuffers() void KRLight::invalidateShadowBuffers()
{ {
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) { for (int iShadow = 0; iShadow < m_cShadowBuffers; iShadow++) {
shadowValid[iShadow] = false; shadowValid[iShadow] = false;
} }
} }
int KRLight::configureShadowBufferViewports(const KRViewport &viewport) int KRLight::configureShadowBufferViewports(const KRViewport& viewport)
{ {
return 0; return 0;
} }
void KRLight::renderShadowBuffers(RenderInfo& ri) void KRLight::renderShadowBuffers(RenderInfo& ri)
{ {
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) { for (int iShadow = 0; iShadow < m_cShadowBuffers; iShadow++) {
if(!shadowValid[iShadow]) { if (!shadowValid[iShadow]) {
shadowValid[iShadow] = true; shadowValid[iShadow] = true;
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
GLDEBUG(glViewport(0, 0, (GLsizei)m_shadowViewports[iShadow].getSize().x, (GLsizei)m_shadowViewports[iShadow].getSize().y));
GLDEBUG(glClearDepthf(0.0f));
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
GLDEBUG(glViewport(1, 1, (GLsizei)m_shadowViewports[iShadow].getSize().x - 2, (GLsizei)m_shadowViewports[iShadow].getSize().y - 2));
GLDEBUG(glClearDepthf(1.0f)); GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
GLDEBUG(glDisable(GL_DITHER));
// Use shader program
PipelineInfo info{};
std::string shader_name("ShadowShader");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.renderPass = KRNode::RENDER_PASS_FORWARD_TRANSPARENT;
info.rasterMode = RasterMode::kOpaqueLessTest; // TODO - This is sub-optimal. Evaluate increasing depth buffer resolution instead of disabling depth test.
info.cullMode = CullMode::kCullNone; // Disabling culling, which eliminates some self-cast shadow artifacts
KRPipeline *shadowShader = m_pContext->getPipelineManager()->getPipeline(*ri.surface, info);
shadowShader->bind(ri.commandBuffer, *ri.camera, m_shadowViewports[iShadow], Matrix4(), nullptr, nullptr, nullptr, KRNode::RENDER_PASS_SHADOWMAP); GLDEBUG(glViewport(0, 0, (GLsizei)m_shadowViewports[iShadow].getSize().x, (GLsizei)m_shadowViewports[iShadow].getSize().y));
getScene().render(ri.commandBuffer, *ri.surface, ri.camera, m_shadowViewports[iShadow].getVisibleBounds(), m_shadowViewports[iShadow], KRNode::RENDER_PASS_SHADOWMAP, true); GLDEBUG(glClearDepthf(0.0f));
} GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
GLDEBUG(glViewport(1, 1, (GLsizei)m_shadowViewports[iShadow].getSize().x - 2, (GLsizei)m_shadowViewports[iShadow].getSize().y - 2));
GLDEBUG(glClearDepthf(1.0f));
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
GLDEBUG(glDisable(GL_DITHER));
// Use shader program
PipelineInfo info{};
std::string shader_name("ShadowShader");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.renderPass = KRNode::RENDER_PASS_FORWARD_TRANSPARENT;
info.rasterMode = RasterMode::kOpaqueLessTest; // TODO - This is sub-optimal. Evaluate increasing depth buffer resolution instead of disabling depth test.
info.cullMode = CullMode::kCullNone; // Disabling culling, which eliminates some self-cast shadow artifacts
KRPipeline* shadowShader = m_pContext->getPipelineManager()->getPipeline(*ri.surface, info);
shadowShader->bind(ri.commandBuffer, *ri.camera, m_shadowViewports[iShadow], Matrix4(), nullptr, nullptr, nullptr, KRNode::RENDER_PASS_SHADOWMAP);
getScene().render(ri.commandBuffer, *ri.surface, ri.camera, m_shadowViewports[iShadow].getVisibleBounds(), m_shadowViewports[iShadow], KRNode::RENDER_PASS_SHADOWMAP, true);
} }
}
} }
int KRLight::getShadowBufferCount() int KRLight::getShadowBufferCount()
{ {
int cBuffers=0; int cBuffers = 0;
for(int iBuffer=0; iBuffer < m_cShadowBuffers; iBuffer++) { for (int iBuffer = 0; iBuffer < m_cShadowBuffers; iBuffer++) {
if(shadowValid[iBuffer]) { if (shadowValid[iBuffer]) {
cBuffers++; cBuffers++;
} else { } else {
break; break;
}
} }
return cBuffers; }
return cBuffers;
} }
GLuint *KRLight::getShadowTextures() GLuint* KRLight::getShadowTextures()
{ {
return shadowDepthTexture; return shadowDepthTexture;
} }
KRViewport *KRLight::getShadowViewports() KRViewport* KRLight::getShadowViewports()
{ {
return m_shadowViewports; return m_shadowViewports;
} }

View File

@@ -42,64 +42,65 @@ static const float KRLIGHT_MIN_INFLUENCE = 0.15f; // 0.05f
#define KRENGINE_SHADOW_MAP_WIDTH 1024 #define KRENGINE_SHADOW_MAP_WIDTH 1024
#define KRENGINE_SHADOW_MAP_HEIGHT 1024 #define KRENGINE_SHADOW_MAP_HEIGHT 1024
class KRLight : public KRNode { class KRLight : public KRNode
{
public: public:
static void InitNodeInfo(KrNodeInfo* nodeInfo); static void InitNodeInfo(KrNodeInfo* nodeInfo);
virtual ~KRLight(); virtual ~KRLight();
virtual std::string getElementName() = 0; virtual std::string getElementName() = 0;
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
virtual void loadXML(tinyxml2::XMLElement *e); virtual void loadXML(tinyxml2::XMLElement* e);
void setIntensity(float intensity); void setIntensity(float intensity);
float getIntensity(); float getIntensity();
void setDecayStart(float decayStart); void setDecayStart(float decayStart);
float getDecayStart(); float getDecayStart();
const Vector3 &getColor(); const Vector3& getColor();
void setColor(const Vector3 &color); void setColor(const Vector3& color);
void setFlareTexture(std::string flare_texture); void setFlareTexture(std::string flare_texture);
void setFlareSize(float flare_size); void setFlareSize(float flare_size);
void setFlareOcclusionSize(float occlusion_size); void setFlareOcclusionSize(float occlusion_size);
void deleteBuffers(); void deleteBuffers();
virtual void render(RenderInfo& ri);
int getShadowBufferCount();
GLuint* getShadowTextures();
KRViewport* getShadowViewports();
virtual void render(RenderInfo& ri);
int getShadowBufferCount();
GLuint *getShadowTextures();
KRViewport *getShadowViewports();
protected: protected:
KRLight(KRScene &scene, std::string name); KRLight(KRScene& scene, std::string name);
float m_intensity; float m_intensity;
float m_decayStart; float m_decayStart;
Vector3 m_color; Vector3 m_color;
std::string m_flareTexture; std::string m_flareTexture;
KRTexture *m_pFlareTexture; KRTexture* m_pFlareTexture;
float m_flareSize; float m_flareSize;
float m_flareOcclusionSize; float m_flareOcclusionSize;
bool m_casts_shadow; bool m_casts_shadow;
bool m_light_shafts; bool m_light_shafts;
float m_dust_particle_density; float m_dust_particle_density;
float m_dust_particle_size; float m_dust_particle_size;
float m_dust_particle_intensity; float m_dust_particle_intensity;
GLuint m_occlusionQuery; // Occlusion query for attenuating occluded flares GLuint m_occlusionQuery; // Occlusion query for attenuating occluded flares
// Shadow Maps // Shadow Maps
int m_cShadowBuffers; int m_cShadowBuffers;
GLuint shadowFramebuffer[KRENGINE_MAX_SHADOW_BUFFERS], shadowDepthTexture[KRENGINE_MAX_SHADOW_BUFFERS]; GLuint shadowFramebuffer[KRENGINE_MAX_SHADOW_BUFFERS], shadowDepthTexture[KRENGINE_MAX_SHADOW_BUFFERS];
bool shadowValid[KRENGINE_MAX_SHADOW_BUFFERS]; bool shadowValid[KRENGINE_MAX_SHADOW_BUFFERS];
KRViewport m_shadowViewports[KRENGINE_MAX_SHADOW_BUFFERS]; KRViewport m_shadowViewports[KRENGINE_MAX_SHADOW_BUFFERS];
void allocateShadowBuffers(int cBuffers); void allocateShadowBuffers(int cBuffers);
void invalidateShadowBuffers(); void invalidateShadowBuffers();
virtual int configureShadowBufferViewports(const KRViewport &viewport); virtual int configureShadowBufferViewports(const KRViewport& viewport);
void renderShadowBuffers(RenderInfo& ri); void renderShadowBuffers(RenderInfo& ri);
}; };

View File

@@ -39,47 +39,47 @@ void KRLocator::InitNodeInfo(KrNodeInfo* nodeInfo)
// No additional members // No additional members
} }
KRLocator::KRLocator(KRScene &scene, std::string name) : KRNode(scene, name) KRLocator::KRLocator(KRScene& scene, std::string name) : KRNode(scene, name)
{ {
} }
KRLocator::~KRLocator() KRLocator::~KRLocator()
{}
std::string KRLocator::getElementName()
{ {
return "locator";
} }
std::string KRLocator::getElementName() { tinyxml2::XMLElement* KRLocator::saveXML(tinyxml2::XMLNode* parent)
return "locator"; {
tinyxml2::XMLElement* e = KRNode::saveXML(parent);
return e;
} }
tinyxml2::XMLElement *KRLocator::saveXML( tinyxml2::XMLNode *parent) void KRLocator::loadXML(tinyxml2::XMLElement* e)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); KRNode::loadXML(e);
return e;
} }
void KRLocator::loadXML(tinyxml2::XMLElement *e) unordered_map<std::string, int>& KRLocator::getUserIntAttributes()
{ {
KRNode::loadXML(e); return m_userIntAttributes;
} }
unordered_map<std::string, int> &KRLocator::getUserIntAttributes() unordered_map<std::string, double>& KRLocator::getUserDoubleAttributes()
{ {
return m_userIntAttributes; return m_userDoubleAttributes;
} }
unordered_map<std::string, double> &KRLocator::getUserDoubleAttributes() unordered_map<std::string, bool>& KRLocator::getUserBoolAttributes()
{ {
return m_userDoubleAttributes; return m_userBoolAttributes;
} }
unordered_map<std::string, bool> &KRLocator::getUserBoolAttributes() unordered_map<std::string, std::string>& KRLocator::getUserStringAttributes()
{ {
return m_userBoolAttributes; return m_userStringAttributes;
}
unordered_map<std::string, std::string> &KRLocator::getUserStringAttributes()
{
return m_userStringAttributes;
} }

View File

@@ -35,23 +35,24 @@
#include "KRNode.h" #include "KRNode.h"
#include "KRTexture.h" #include "KRTexture.h"
class KRLocator : public KRNode { class KRLocator : public KRNode
{
public: public:
static void InitNodeInfo(KrNodeInfo* nodeInfo); static void InitNodeInfo(KrNodeInfo* nodeInfo);
KRLocator(KRScene& scene, std::string name);
virtual ~KRLocator();
virtual std::string getElementName();
virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
virtual void loadXML(tinyxml2::XMLElement* e);
unordered_map<std::string, int>& getUserIntAttributes();
unordered_map<std::string, double>& getUserDoubleAttributes();
unordered_map<std::string, bool>& getUserBoolAttributes();
unordered_map<std::string, std::string>& getUserStringAttributes();
KRLocator(KRScene &scene, std::string name);
virtual ~KRLocator();
virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
virtual void loadXML(tinyxml2::XMLElement *e);
unordered_map<std::string, int> &getUserIntAttributes();
unordered_map<std::string, double> &getUserDoubleAttributes();
unordered_map<std::string, bool> &getUserBoolAttributes();
unordered_map<std::string, std::string> &getUserStringAttributes();
private: private:
unordered_map<std::string, int> m_userIntAttributes; unordered_map<std::string, int> m_userIntAttributes;
unordered_map<std::string, double> m_userDoubleAttributes; unordered_map<std::string, double> m_userDoubleAttributes;
unordered_map<std::string, bool> m_userBoolAttributes; unordered_map<std::string, bool> m_userBoolAttributes;
unordered_map<std::string, std::string> m_userStringAttributes; unordered_map<std::string, std::string> m_userStringAttributes;
}; };

View File

@@ -36,415 +36,434 @@
#include "KRContext.h" #include "KRContext.h"
KRMaterial::KRMaterial(KRContext &context, const char *szName) : KRResource(context, szName) { KRMaterial::KRMaterial(KRContext& context, const char* szName) : KRResource(context, szName)
m_name = szName; {
m_pAmbientMap = NULL; m_name = szName;
m_pDiffuseMap = NULL; m_pAmbientMap = NULL;
m_pSpecularMap = NULL; m_pDiffuseMap = NULL;
m_pNormalMap = NULL; m_pSpecularMap = NULL;
m_pReflectionMap = NULL; m_pNormalMap = NULL;
m_pReflectionCube = NULL; m_pReflectionMap = NULL;
m_ambientColor = Vector3::Zero(); m_pReflectionCube = NULL;
m_diffuseColor = Vector3::One(); m_ambientColor = Vector3::Zero();
m_specularColor = Vector3::One(); m_diffuseColor = Vector3::One();
m_reflectionColor = Vector3::Zero(); m_specularColor = Vector3::One();
m_tr = 1.0f; m_reflectionColor = Vector3::Zero();
m_ns = 0.0f; m_tr = 1.0f;
m_ambientMap = ""; m_ns = 0.0f;
m_diffuseMap = ""; m_ambientMap = "";
m_specularMap = ""; m_diffuseMap = "";
m_normalMap = ""; m_specularMap = "";
m_reflectionMap = ""; m_normalMap = "";
m_reflectionCube = ""; m_reflectionMap = "";
m_ambientMapOffset = Vector2::Create(0.0f, 0.0f); m_reflectionCube = "";
m_specularMapOffset = Vector2::Create(0.0f, 0.0f); m_ambientMapOffset = Vector2::Create(0.0f, 0.0f);
m_diffuseMapOffset = Vector2::Create(0.0f, 0.0f); m_specularMapOffset = Vector2::Create(0.0f, 0.0f);
m_ambientMapScale = Vector2::Create(1.0f, 1.0f); m_diffuseMapOffset = Vector2::Create(0.0f, 0.0f);
m_specularMapScale = Vector2::Create(1.0f, 1.0f); m_ambientMapScale = Vector2::Create(1.0f, 1.0f);
m_diffuseMapScale = Vector2::Create(1.0f, 1.0f); m_specularMapScale = Vector2::Create(1.0f, 1.0f);
m_reflectionMapOffset = Vector2::Create(0.0f, 0.0f); m_diffuseMapScale = Vector2::Create(1.0f, 1.0f);
m_reflectionMapScale = Vector2::Create(1.0f, 1.0f); m_reflectionMapOffset = Vector2::Create(0.0f, 0.0f);
m_alpha_mode = KRMATERIAL_ALPHA_MODE_OPAQUE; m_reflectionMapScale = Vector2::Create(1.0f, 1.0f);
m_alpha_mode = KRMATERIAL_ALPHA_MODE_OPAQUE;
} }
KRMaterial::~KRMaterial() { KRMaterial::~KRMaterial()
{
} }
std::string KRMaterial::getExtension() { std::string KRMaterial::getExtension()
return "mtl"; {
return "mtl";
} }
bool KRMaterial::needsVertexTangents() bool KRMaterial::needsVertexTangents()
{ {
return m_normalMap.size() > 0; return m_normalMap.size() > 0;
} }
bool KRMaterial::save(KRDataBlock &data) { bool KRMaterial::save(KRDataBlock& data)
std::stringstream stream; {
stream.precision(std::numeric_limits<long double>::digits10); std::stringstream stream;
stream.setf(std::ios::fixed,std::ios::floatfield); stream.precision(std::numeric_limits<long double>::digits10);
stream.setf(std::ios::fixed, std::ios::floatfield);
stream << "newmtl " << m_name;
stream << "\nka " << m_ambientColor.x << " " << m_ambientColor.y << " " << m_ambientColor.z;
stream << "\nkd " << m_diffuseColor.x << " " << m_diffuseColor.y << " " << m_diffuseColor.z;
stream << "\nks " << m_specularColor.x << " " << m_specularColor.y << " " << m_specularColor.z;
stream << "\nkr " << m_reflectionColor.x << " " << m_reflectionColor.y << " " << m_reflectionColor.z;
stream << "\nTr " << m_tr;
stream << "\nNs " << m_ns;
if(m_ambientMap.size()) {
stream << "\nmap_Ka " << m_ambientMap << ".pvr -s " << m_ambientMapScale.x << " " << m_ambientMapScale.y << " -o " << m_ambientMapOffset.x << " " << m_ambientMapOffset.y;
} else {
stream << "\n# map_Ka filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if(m_diffuseMap.size()) {
stream << "\nmap_Kd " << m_diffuseMap << ".pvr -s " << m_diffuseMapScale.x << " " << m_diffuseMapScale.y << " -o " << m_diffuseMapOffset.x << " " << m_diffuseMapOffset.y;
} else {
stream << "\n# map_Kd filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if(m_specularMap.size()) {
stream << "\nmap_Ks " << m_specularMap << ".pvr -s " << m_specularMapScale.x << " " << m_specularMapScale.y << " -o " << m_specularMapOffset.x << " " << m_specularMapOffset.y << "\n";
} else {
stream << "\n# map_Ks filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if(m_normalMap.size()) {
stream << "\nmap_Normal " << m_normalMap << ".pvr -s " << m_normalMapScale.x << " " << m_normalMapScale.y << " -o " << m_normalMapOffset.x << " " << m_normalMapOffset.y;
} else {
stream << "\n# map_Normal filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if(m_reflectionMap.size()) {
stream << "\nmap_Reflection " << m_reflectionMap << ".pvr -s " << m_reflectionMapScale.x << " " << m_reflectionMapScale.y << " -o " << m_reflectionMapOffset.x << " " << m_reflectionMapOffset.y;
} else {
stream << "\n# map_Reflection filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if(m_reflectionCube.size()) {
stream << "\nmap_ReflectionCube " << m_reflectionCube << ".pvr";
} else {
stream << "\n# map_ReflectionCube cubemapname";
}
switch(m_alpha_mode) {
case KRMATERIAL_ALPHA_MODE_OPAQUE:
stream << "\nalpha_mode opaque";
break;
case KRMATERIAL_ALPHA_MODE_TEST:
stream << "\nalpha_mode test";
break;
case KRMATERIAL_ALPHA_MODE_BLENDONESIDE:
stream << "\nalpha_mode blendoneside";
break;
case KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE:
stream << "\nalpha_mode blendtwoside";
break;
}
stream << "\n# alpha_mode opaque, test, blendoneside, or blendtwoside";
stream << "\n";
data.append(stream.str());
return true; stream << "newmtl " << m_name;
stream << "\nka " << m_ambientColor.x << " " << m_ambientColor.y << " " << m_ambientColor.z;
stream << "\nkd " << m_diffuseColor.x << " " << m_diffuseColor.y << " " << m_diffuseColor.z;
stream << "\nks " << m_specularColor.x << " " << m_specularColor.y << " " << m_specularColor.z;
stream << "\nkr " << m_reflectionColor.x << " " << m_reflectionColor.y << " " << m_reflectionColor.z;
stream << "\nTr " << m_tr;
stream << "\nNs " << m_ns;
if (m_ambientMap.size()) {
stream << "\nmap_Ka " << m_ambientMap << ".pvr -s " << m_ambientMapScale.x << " " << m_ambientMapScale.y << " -o " << m_ambientMapOffset.x << " " << m_ambientMapOffset.y;
} else {
stream << "\n# map_Ka filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if (m_diffuseMap.size()) {
stream << "\nmap_Kd " << m_diffuseMap << ".pvr -s " << m_diffuseMapScale.x << " " << m_diffuseMapScale.y << " -o " << m_diffuseMapOffset.x << " " << m_diffuseMapOffset.y;
} else {
stream << "\n# map_Kd filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if (m_specularMap.size()) {
stream << "\nmap_Ks " << m_specularMap << ".pvr -s " << m_specularMapScale.x << " " << m_specularMapScale.y << " -o " << m_specularMapOffset.x << " " << m_specularMapOffset.y << "\n";
} else {
stream << "\n# map_Ks filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if (m_normalMap.size()) {
stream << "\nmap_Normal " << m_normalMap << ".pvr -s " << m_normalMapScale.x << " " << m_normalMapScale.y << " -o " << m_normalMapOffset.x << " " << m_normalMapOffset.y;
} else {
stream << "\n# map_Normal filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if (m_reflectionMap.size()) {
stream << "\nmap_Reflection " << m_reflectionMap << ".pvr -s " << m_reflectionMapScale.x << " " << m_reflectionMapScale.y << " -o " << m_reflectionMapOffset.x << " " << m_reflectionMapOffset.y;
} else {
stream << "\n# map_Reflection filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if (m_reflectionCube.size()) {
stream << "\nmap_ReflectionCube " << m_reflectionCube << ".pvr";
} else {
stream << "\n# map_ReflectionCube cubemapname";
}
switch (m_alpha_mode) {
case KRMATERIAL_ALPHA_MODE_OPAQUE:
stream << "\nalpha_mode opaque";
break;
case KRMATERIAL_ALPHA_MODE_TEST:
stream << "\nalpha_mode test";
break;
case KRMATERIAL_ALPHA_MODE_BLENDONESIDE:
stream << "\nalpha_mode blendoneside";
break;
case KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE:
stream << "\nalpha_mode blendtwoside";
break;
}
stream << "\n# alpha_mode opaque, test, blendoneside, or blendtwoside";
stream << "\n";
data.append(stream.str());
return true;
} }
void KRMaterial::setAmbientMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) { void KRMaterial::setAmbientMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset)
m_ambientMap = texture_name; {
m_ambientMapScale = texture_scale; m_ambientMap = texture_name;
m_ambientMapOffset = texture_offset; m_ambientMapScale = texture_scale;
m_ambientMapOffset = texture_offset;
} }
void KRMaterial::setDiffuseMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) { void KRMaterial::setDiffuseMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset)
m_diffuseMap = texture_name; {
m_diffuseMapScale = texture_scale; m_diffuseMap = texture_name;
m_diffuseMapOffset = texture_offset; m_diffuseMapScale = texture_scale;
m_diffuseMapOffset = texture_offset;
} }
void KRMaterial::setSpecularMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) { void KRMaterial::setSpecularMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset)
m_specularMap = texture_name; {
m_specularMapScale = texture_scale; m_specularMap = texture_name;
m_specularMapOffset = texture_offset; m_specularMapScale = texture_scale;
m_specularMapOffset = texture_offset;
} }
void KRMaterial::setNormalMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) { void KRMaterial::setNormalMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset)
m_normalMap = texture_name; {
m_normalMapScale = texture_scale; m_normalMap = texture_name;
m_normalMapOffset = texture_offset; m_normalMapScale = texture_scale;
m_normalMapOffset = texture_offset;
} }
void KRMaterial::setReflectionMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) { void KRMaterial::setReflectionMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset)
m_reflectionMap = texture_name; {
m_reflectionMapScale = texture_scale; m_reflectionMap = texture_name;
m_reflectionMapOffset = texture_offset; m_reflectionMapScale = texture_scale;
m_reflectionMapOffset = texture_offset;
} }
void KRMaterial::setReflectionCube(std::string texture_name) { void KRMaterial::setReflectionCube(std::string texture_name)
m_reflectionCube = texture_name; {
m_reflectionCube = texture_name;
} }
void KRMaterial::setAlphaMode(KRMaterial::alpha_mode_type alpha_mode) { void KRMaterial::setAlphaMode(KRMaterial::alpha_mode_type alpha_mode)
m_alpha_mode = alpha_mode; {
m_alpha_mode = alpha_mode;
} }
KRMaterial::alpha_mode_type KRMaterial::getAlphaMode() { KRMaterial::alpha_mode_type KRMaterial::getAlphaMode()
return m_alpha_mode; {
return m_alpha_mode;
} }
void KRMaterial::setAmbient(const Vector3 &c) { void KRMaterial::setAmbient(const Vector3& c)
m_ambientColor = c; {
m_ambientColor = c;
} }
void KRMaterial::setDiffuse(const Vector3 &c) { void KRMaterial::setDiffuse(const Vector3& c)
m_diffuseColor = c; {
m_diffuseColor = c;
} }
void KRMaterial::setSpecular(const Vector3 &c) { void KRMaterial::setSpecular(const Vector3& c)
m_specularColor = c; {
m_specularColor = c;
} }
void KRMaterial::setReflection(const Vector3 &c) { void KRMaterial::setReflection(const Vector3& c)
m_reflectionColor = c; {
m_reflectionColor = c;
} }
void KRMaterial::setTransparency(float a) { void KRMaterial::setTransparency(float a)
if(a < 1.0f && m_alpha_mode == KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE) { {
setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE); if (a < 1.0f && m_alpha_mode == KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE) {
} setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
m_tr = a; }
m_tr = a;
} }
void KRMaterial::setShininess(float s) { void KRMaterial::setShininess(float s)
m_ns = s; {
m_ns = s;
} }
bool KRMaterial::isTransparent() { bool KRMaterial::isTransparent()
return m_tr < 1.0 || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE; {
return m_tr < 1.0 || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE;
} }
void KRMaterial::preStream(float lodCoverage) void KRMaterial::preStream(float lodCoverage)
{ {
getTextures(); getTextures();
if(m_pAmbientMap) { if (m_pAmbientMap) {
m_pAmbientMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_AMBIENT_MAP); m_pAmbientMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_AMBIENT_MAP);
} }
if(m_pDiffuseMap) { if (m_pDiffuseMap) {
m_pDiffuseMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP); m_pDiffuseMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
} }
if(m_pNormalMap) { if (m_pNormalMap) {
m_pNormalMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP); m_pNormalMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
} }
if(m_pSpecularMap) { if (m_pSpecularMap) {
m_pSpecularMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP); m_pSpecularMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
} }
if(m_pReflectionMap) { if (m_pReflectionMap) {
m_pReflectionMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP); m_pReflectionMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
} }
if(m_pReflectionCube) { if (m_pReflectionCube) {
m_pReflectionCube->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE); m_pReflectionCube->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
} }
} }
kraken_stream_level KRMaterial::getStreamLevel() kraken_stream_level KRMaterial::getStreamLevel()
{ {
kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ; kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ;
getTextures();
if(m_pAmbientMap) {
stream_level = KRMIN(stream_level, m_pAmbientMap->getStreamLevel(KRTexture::TEXTURE_USAGE_AMBIENT_MAP));
}
if(m_pDiffuseMap) { getTextures();
stream_level = KRMIN(stream_level, m_pDiffuseMap->getStreamLevel(KRTexture::TEXTURE_USAGE_DIFFUSE_MAP));
}
if(m_pNormalMap) { if (m_pAmbientMap) {
stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(KRTexture::TEXTURE_USAGE_NORMAL_MAP)); stream_level = KRMIN(stream_level, m_pAmbientMap->getStreamLevel(KRTexture::TEXTURE_USAGE_AMBIENT_MAP));
} }
if(m_pSpecularMap) { if (m_pDiffuseMap) {
stream_level = KRMIN(stream_level, m_pSpecularMap->getStreamLevel(KRTexture::TEXTURE_USAGE_SPECULAR_MAP)); stream_level = KRMIN(stream_level, m_pDiffuseMap->getStreamLevel(KRTexture::TEXTURE_USAGE_DIFFUSE_MAP));
} }
if(m_pReflectionMap) { if (m_pNormalMap) {
stream_level = KRMIN(stream_level, m_pReflectionMap->getStreamLevel(KRTexture::TEXTURE_USAGE_REFLECTION_MAP)); stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(KRTexture::TEXTURE_USAGE_NORMAL_MAP));
} }
if(m_pReflectionCube) { if (m_pSpecularMap) {
stream_level = KRMIN(stream_level, m_pReflectionCube->getStreamLevel(KRTexture::TEXTURE_USAGE_REFECTION_CUBE)); stream_level = KRMIN(stream_level, m_pSpecularMap->getStreamLevel(KRTexture::TEXTURE_USAGE_SPECULAR_MAP));
} }
return stream_level; if (m_pReflectionMap) {
stream_level = KRMIN(stream_level, m_pReflectionMap->getStreamLevel(KRTexture::TEXTURE_USAGE_REFLECTION_MAP));
}
if (m_pReflectionCube) {
stream_level = KRMIN(stream_level, m_pReflectionCube->getStreamLevel(KRTexture::TEXTURE_USAGE_REFECTION_CUBE));
}
return stream_level;
} }
void KRMaterial::getTextures() void KRMaterial::getTextures()
{ {
if(!m_pAmbientMap && m_ambientMap.size()) { if (!m_pAmbientMap && m_ambientMap.size()) {
m_pAmbientMap = getContext().getTextureManager()->getTexture(m_ambientMap); m_pAmbientMap = getContext().getTextureManager()->getTexture(m_ambientMap);
} }
if(!m_pDiffuseMap && m_diffuseMap.size()) { if (!m_pDiffuseMap && m_diffuseMap.size()) {
m_pDiffuseMap = getContext().getTextureManager()->getTexture(m_diffuseMap); m_pDiffuseMap = getContext().getTextureManager()->getTexture(m_diffuseMap);
} }
if(!m_pNormalMap && m_normalMap.size()) { if (!m_pNormalMap && m_normalMap.size()) {
m_pNormalMap = getContext().getTextureManager()->getTexture(m_normalMap); m_pNormalMap = getContext().getTextureManager()->getTexture(m_normalMap);
} }
if(!m_pSpecularMap && m_specularMap.size()) { if (!m_pSpecularMap && m_specularMap.size()) {
m_pSpecularMap = getContext().getTextureManager()->getTexture(m_specularMap); m_pSpecularMap = getContext().getTextureManager()->getTexture(m_specularMap);
} }
if(!m_pReflectionMap && m_reflectionMap.size()) { if (!m_pReflectionMap && m_reflectionMap.size()) {
m_pReflectionMap = getContext().getTextureManager()->getTexture(m_reflectionMap); m_pReflectionMap = getContext().getTextureManager()->getTexture(m_reflectionMap);
} }
if(!m_pReflectionCube && m_reflectionCube.size()) { if (!m_pReflectionCube && m_reflectionCube.size()) {
m_pReflectionCube = getContext().getTextureManager()->getTextureCube(m_reflectionCube.c_str()); m_pReflectionCube = getContext().getTextureManager()->getTextureCube(m_reflectionCube.c_str());
} }
} }
void KRMaterial::bind(const KRNode::RenderInfo& ri, ModelFormat modelFormat, __uint32_t vertexAttributes, CullMode cullMode, const std::vector<KRBone *> &bones, const std::vector<Matrix4> &bind_poses, const Matrix4 &matModel, KRTexture *pLightMap, const Vector3 &rim_color, float rim_power, float lod_coverage) void KRMaterial::bind(const KRNode::RenderInfo& ri, ModelFormat modelFormat, __uint32_t vertexAttributes, CullMode cullMode, const std::vector<KRBone*>& bones, const std::vector<Matrix4>& bind_poses, const Matrix4& matModel, KRTexture* pLightMap, const Vector3& rim_color, float rim_power, float lod_coverage)
{ {
bool bLightMap = pLightMap && ri.camera->settings.bEnableLightMap; bool bLightMap = pLightMap && ri.camera->settings.bEnableLightMap;
getTextures();
Vector2 default_scale = Vector2::One();
Vector2 default_offset = Vector2::Zero();
bool bHasReflection = m_reflectionColor != Vector3::Zero();
bool bDiffuseMap = m_pDiffuseMap != NULL && ri.camera->settings.bEnableDiffuseMap;
bool bNormalMap = m_pNormalMap != NULL && ri.camera->settings.bEnableNormalMap;
bool bSpecMap = m_pSpecularMap != NULL && ri.camera->settings.bEnableSpecMap;
bool bReflectionMap = m_pReflectionMap != NULL && ri.camera->settings.bEnableReflectionMap && ri.camera->settings.bEnableReflection && bHasReflection;
bool bReflectionCubeMap = m_pReflectionCube != NULL && ri.camera->settings.bEnableReflection && bHasReflection;
bool bAlphaTest = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_TEST) && bDiffuseMap;
bool bAlphaBlend = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE) || (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
PipelineInfo info{};
std::string shader_name("ObjectShader");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &ri.point_lights;
info.directional_lights = &ri.directional_lights;
info.spot_lights = &ri.spot_lights;
info.bone_count = (int)bones.size();
info.renderPass = ri.renderPass;
info.bDiffuseMap = bDiffuseMap;
info.bNormalMap = bNormalMap;
info.bSpecMap = bSpecMap;
info.bReflectionMap = bReflectionMap;
info.bReflectionCubeMap = bReflectionCubeMap;
info.bLightMap = bLightMap;
info.bDiffuseMapScale = m_diffuseMapScale != default_scale && bDiffuseMap;
info.bSpecMapScale = m_specularMapScale != default_scale && bSpecMap;
info.bNormalMapScale = m_normalMapScale != default_scale && bNormalMap;
info.bReflectionMapScale = m_reflectionMapScale != default_scale && bReflectionMap;
info.bDiffuseMapOffset = m_diffuseMapOffset != default_offset && bDiffuseMap;
info.bSpecMapOffset = m_specularMapOffset != default_offset && bSpecMap;
info.bNormalMapOffset = m_normalMapOffset != default_offset && bNormalMap;
info.bReflectionMapOffset = m_reflectionMapOffset != default_offset && bReflectionMap;
info.bAlphaTest = bAlphaTest;
info.rasterMode = bAlphaBlend ? RasterMode::kAlphaBlend : RasterMode::kOpaque;
info.bRimColor = rim_power != 0.0f;
info.renderPass = ri.renderPass;
info.modelFormat = modelFormat;
info.vertexAttributes = vertexAttributes;
info.cullMode = cullMode;
KRPipeline *pShader = getContext().getPipelineManager()->getPipeline(*ri.surface, info);
// Rim highlighting parameters getTextures();
pShader->setUniform(KRPipeline::Uniform::rim_color, rim_color);
pShader->setUniform(KRPipeline::Uniform::rim_power, rim_power);
// Bind bones
if(pShader->hasUniform(KRPipeline::Uniform::bone_transforms)) {
float bone_mats[256 * 16];
float *bone_mat_component = bone_mats;
for(int bone_index=0; bone_index < bones.size(); bone_index++) {
KRBone *bone = bones[bone_index];
// Vector3 initialRotation = bone->getInitialLocalRotation();
// Vector3 rotation = bone->getLocalRotation();
// Vector3 initialTranslation = bone->getInitialLocalTranslation();
// Vector3 translation = bone->getLocalTranslation();
// Vector3 initialScale = bone->getInitialLocalScale();
// Vector3 scale = bone->getLocalScale();
//
//printf("%s - delta rotation: %.4f %.4f %.4f\n", bone->getName().c_str(), (rotation.x - initialRotation.x) * 180.0 / M_PI, (rotation.y - initialRotation.y) * 180.0 / M_PI, (rotation.z - initialRotation.z) * 180.0 / M_PI);
//printf("%s - delta translation: %.4f %.4f %.4f\n", bone->getName().c_str(), translation.x - initialTranslation.x, translation.y - initialTranslation.y, translation.z - initialTranslation.z);
// printf("%s - delta scale: %.4f %.4f %.4f\n", bone->getName().c_str(), scale.x - initialScale.x, scale.y - initialScale.y, scale.z - initialScale.z);
Matrix4 skin_bone_bind_pose = bind_poses[bone_index];
Matrix4 active_mat = bone->getActivePoseMatrix();
Matrix4 inv_bind_mat = bone->getInverseBindPoseMatrix();
Matrix4 inv_bind_mat2 = Matrix4::Invert(bind_poses[bone_index]);
Matrix4 t = (inv_bind_mat * active_mat);
Matrix4 t2 = inv_bind_mat2 * bone->getModelMatrix();
for(int i=0; i < 16; i++) {
*bone_mat_component++ = t[i];
}
}
if(pShader->hasUniform(KRPipeline::Uniform::bone_transforms)) {
pShader->setUniform(KRPipeline::Uniform::bone_transforms, (Matrix4*)bone_mats, bones.size());
}
}
Vector2 default_scale = Vector2::One();
pShader->setUniform(KRPipeline::Uniform::material_ambient, m_ambientColor + ri.camera->settings.ambient_intensity); Vector2 default_offset = Vector2::Zero();
if(ri.renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
// We pre-multiply the light color with the material color in the forward renderer
pShader->setUniform(KRPipeline::Uniform::material_diffuse, Vector3::Create(m_diffuseColor.x * ri.camera->settings.light_intensity.x, m_diffuseColor.y * ri.camera->settings.light_intensity.y, m_diffuseColor.z * ri.camera->settings.light_intensity.z));
} else {
pShader->setUniform(KRPipeline::Uniform::material_diffuse, m_diffuseColor);
}
if(ri.renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
// We pre-multiply the light color with the material color in the forward renderer
pShader->setUniform(KRPipeline::Uniform::material_specular, Vector3::Create(m_specularColor.x * ri.camera->settings.light_intensity.x, m_specularColor.y * ri.camera->settings.light_intensity.y, m_specularColor.z * ri.camera->settings.light_intensity.z));
} else {
pShader->setUniform(KRPipeline::Uniform::material_specular, m_specularColor);
}
pShader->setUniform(KRPipeline::Uniform::material_shininess, m_ns);
pShader->setUniform(KRPipeline::Uniform::material_reflection, m_reflectionColor);
pShader->setUniform(KRPipeline::Uniform::diffusetexture_scale, m_diffuseMapScale);
pShader->setUniform(KRPipeline::Uniform::speculartexture_scale, m_specularMapScale);
pShader->setUniform(KRPipeline::Uniform::reflectiontexture_scale, m_reflectionMapScale);
pShader->setUniform(KRPipeline::Uniform::normaltexture_scale, m_normalMapScale);
pShader->setUniform(KRPipeline::Uniform::diffusetexture_offset, m_diffuseMapOffset);
pShader->setUniform(KRPipeline::Uniform::speculartexture_offset, m_specularMapOffset);
pShader->setUniform(KRPipeline::Uniform::reflectiontexture_offset, m_reflectionMapOffset);
pShader->setUniform(KRPipeline::Uniform::normaltexture_offset, m_normalMapOffset);
pShader->setUniform(KRPipeline::Uniform::material_alpha, m_tr); bool bHasReflection = m_reflectionColor != Vector3::Zero();
bool bDiffuseMap = m_pDiffuseMap != NULL && ri.camera->settings.bEnableDiffuseMap;
if(bDiffuseMap) { bool bNormalMap = m_pNormalMap != NULL && ri.camera->settings.bEnableNormalMap;
m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap, lod_coverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP); bool bSpecMap = m_pSpecularMap != NULL && ri.camera->settings.bEnableSpecMap;
} bool bReflectionMap = m_pReflectionMap != NULL && ri.camera->settings.bEnableReflectionMap && ri.camera->settings.bEnableReflection && bHasReflection;
bool bReflectionCubeMap = m_pReflectionCube != NULL && ri.camera->settings.bEnableReflection && bHasReflection;
if(bSpecMap) { bool bAlphaTest = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_TEST) && bDiffuseMap;
m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap, lod_coverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP); bool bAlphaBlend = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE) || (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
}
if(bNormalMap) { PipelineInfo info{};
m_pContext->getTextureManager()->selectTexture(2, m_pNormalMap, lod_coverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP); std::string shader_name("ObjectShader");
} info.shader_name = &shader_name;
info.pCamera = ri.camera;
if(bReflectionCubeMap && (ri.renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || ri.renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || ri.renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) { info.point_lights = &ri.point_lights;
m_pContext->getTextureManager()->selectTexture(4, m_pReflectionCube, lod_coverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE); info.directional_lights = &ri.directional_lights;
} info.spot_lights = &ri.spot_lights;
info.bone_count = (int)bones.size();
if(bReflectionMap && (ri.renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || ri.renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || ri.renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) { info.renderPass = ri.renderPass;
// GL_TEXTURE7 is used for reading the depth buffer in gBuffer pass 2 and re-used for the reflection map in gBuffer Pass 3 and in forward rendering info.bDiffuseMap = bDiffuseMap;
m_pContext->getTextureManager()->selectTexture(7, m_pReflectionMap, lod_coverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP); info.bNormalMap = bNormalMap;
} info.bSpecMap = bSpecMap;
info.bReflectionMap = bReflectionMap;
info.bReflectionCubeMap = bReflectionCubeMap;
info.bLightMap = bLightMap;
info.bDiffuseMapScale = m_diffuseMapScale != default_scale && bDiffuseMap;
info.bSpecMapScale = m_specularMapScale != default_scale && bSpecMap;
info.bNormalMapScale = m_normalMapScale != default_scale && bNormalMap;
info.bReflectionMapScale = m_reflectionMapScale != default_scale && bReflectionMap;
info.bDiffuseMapOffset = m_diffuseMapOffset != default_offset && bDiffuseMap;
info.bSpecMapOffset = m_specularMapOffset != default_offset && bSpecMap;
info.bNormalMapOffset = m_normalMapOffset != default_offset && bNormalMap;
info.bReflectionMapOffset = m_reflectionMapOffset != default_offset && bReflectionMap;
info.bAlphaTest = bAlphaTest;
info.rasterMode = bAlphaBlend ? RasterMode::kAlphaBlend : RasterMode::kOpaque;
info.bRimColor = rim_power != 0.0f;
info.renderPass = ri.renderPass;
info.modelFormat = modelFormat;
info.vertexAttributes = vertexAttributes;
info.cullMode = cullMode;
KRPipeline* pShader = getContext().getPipelineManager()->getPipeline(*ri.surface, info);
pShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, matModel, &ri.point_lights, &ri.directional_lights, &ri.spot_lights, ri.renderPass); // Rim highlighting parameters
pShader->setUniform(KRPipeline::Uniform::rim_color, rim_color);
pShader->setUniform(KRPipeline::Uniform::rim_power, rim_power);
// Bind bones
if (pShader->hasUniform(KRPipeline::Uniform::bone_transforms)) {
float bone_mats[256 * 16];
float* bone_mat_component = bone_mats;
for (int bone_index = 0; bone_index < bones.size(); bone_index++) {
KRBone* bone = bones[bone_index];
// Vector3 initialRotation = bone->getInitialLocalRotation();
// Vector3 rotation = bone->getLocalRotation();
// Vector3 initialTranslation = bone->getInitialLocalTranslation();
// Vector3 translation = bone->getLocalTranslation();
// Vector3 initialScale = bone->getInitialLocalScale();
// Vector3 scale = bone->getLocalScale();
//
//printf("%s - delta rotation: %.4f %.4f %.4f\n", bone->getName().c_str(), (rotation.x - initialRotation.x) * 180.0 / M_PI, (rotation.y - initialRotation.y) * 180.0 / M_PI, (rotation.z - initialRotation.z) * 180.0 / M_PI);
//printf("%s - delta translation: %.4f %.4f %.4f\n", bone->getName().c_str(), translation.x - initialTranslation.x, translation.y - initialTranslation.y, translation.z - initialTranslation.z);
// printf("%s - delta scale: %.4f %.4f %.4f\n", bone->getName().c_str(), scale.x - initialScale.x, scale.y - initialScale.y, scale.z - initialScale.z);
Matrix4 skin_bone_bind_pose = bind_poses[bone_index];
Matrix4 active_mat = bone->getActivePoseMatrix();
Matrix4 inv_bind_mat = bone->getInverseBindPoseMatrix();
Matrix4 inv_bind_mat2 = Matrix4::Invert(bind_poses[bone_index]);
Matrix4 t = (inv_bind_mat * active_mat);
Matrix4 t2 = inv_bind_mat2 * bone->getModelMatrix();
for (int i = 0; i < 16; i++) {
*bone_mat_component++ = t[i];
}
}
if (pShader->hasUniform(KRPipeline::Uniform::bone_transforms)) {
pShader->setUniform(KRPipeline::Uniform::bone_transforms, (Matrix4*)bone_mats, bones.size());
}
}
pShader->setUniform(KRPipeline::Uniform::material_ambient, m_ambientColor + ri.camera->settings.ambient_intensity);
if (ri.renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
// We pre-multiply the light color with the material color in the forward renderer
pShader->setUniform(KRPipeline::Uniform::material_diffuse, Vector3::Create(m_diffuseColor.x * ri.camera->settings.light_intensity.x, m_diffuseColor.y * ri.camera->settings.light_intensity.y, m_diffuseColor.z * ri.camera->settings.light_intensity.z));
} else {
pShader->setUniform(KRPipeline::Uniform::material_diffuse, m_diffuseColor);
}
if (ri.renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
// We pre-multiply the light color with the material color in the forward renderer
pShader->setUniform(KRPipeline::Uniform::material_specular, Vector3::Create(m_specularColor.x * ri.camera->settings.light_intensity.x, m_specularColor.y * ri.camera->settings.light_intensity.y, m_specularColor.z * ri.camera->settings.light_intensity.z));
} else {
pShader->setUniform(KRPipeline::Uniform::material_specular, m_specularColor);
}
pShader->setUniform(KRPipeline::Uniform::material_shininess, m_ns);
pShader->setUniform(KRPipeline::Uniform::material_reflection, m_reflectionColor);
pShader->setUniform(KRPipeline::Uniform::diffusetexture_scale, m_diffuseMapScale);
pShader->setUniform(KRPipeline::Uniform::speculartexture_scale, m_specularMapScale);
pShader->setUniform(KRPipeline::Uniform::reflectiontexture_scale, m_reflectionMapScale);
pShader->setUniform(KRPipeline::Uniform::normaltexture_scale, m_normalMapScale);
pShader->setUniform(KRPipeline::Uniform::diffusetexture_offset, m_diffuseMapOffset);
pShader->setUniform(KRPipeline::Uniform::speculartexture_offset, m_specularMapOffset);
pShader->setUniform(KRPipeline::Uniform::reflectiontexture_offset, m_reflectionMapOffset);
pShader->setUniform(KRPipeline::Uniform::normaltexture_offset, m_normalMapOffset);
pShader->setUniform(KRPipeline::Uniform::material_alpha, m_tr);
if (bDiffuseMap) {
m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap, lod_coverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
}
if (bSpecMap) {
m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap, lod_coverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
}
if (bNormalMap) {
m_pContext->getTextureManager()->selectTexture(2, m_pNormalMap, lod_coverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
}
if (bReflectionCubeMap && (ri.renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || ri.renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || ri.renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) {
m_pContext->getTextureManager()->selectTexture(4, m_pReflectionCube, lod_coverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
}
if (bReflectionMap && (ri.renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || ri.renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || ri.renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) {
// GL_TEXTURE7 is used for reading the depth buffer in gBuffer pass 2 and re-used for the reflection map in gBuffer Pass 3 and in forward rendering
m_pContext->getTextureManager()->selectTexture(7, m_pReflectionMap, lod_coverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
}
pShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, matModel, &ri.point_lights, &ri.directional_lights, &ri.spot_lights, ri.renderPass);
} }
const std::string &KRMaterial::getName() const const std::string& KRMaterial::getName() const
{ {
return m_name; return m_name;
} }

View File

@@ -50,89 +50,91 @@ class KRTextureManager;
class KRContext; class KRContext;
class KRSurface; class KRSurface;
class KRMaterial : public KRResource { class KRMaterial : public KRResource
{
public: public:
typedef enum { typedef enum
KRMATERIAL_ALPHA_MODE_OPAQUE, // Non-transparent materials {
KRMATERIAL_ALPHA_MODE_TEST, // Alpha in diffuse texture is interpreted as punch-through when < 0.5 KRMATERIAL_ALPHA_MODE_OPAQUE, // Non-transparent materials
KRMATERIAL_ALPHA_MODE_BLENDONESIDE, // Blended alpha with backface culling KRMATERIAL_ALPHA_MODE_TEST, // Alpha in diffuse texture is interpreted as punch-through when < 0.5
KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE // Blended alpha rendered in two passes. First pass renders backfaces; second pass renders frontfaces. KRMATERIAL_ALPHA_MODE_BLENDONESIDE, // Blended alpha with backface culling
} alpha_mode_type; KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE // Blended alpha rendered in two passes. First pass renders backfaces; second pass renders frontfaces.
} alpha_mode_type;
KRMaterial(KRContext &context, const char *szName);
virtual ~KRMaterial(); KRMaterial(KRContext& context, const char* szName);
virtual ~KRMaterial();
virtual std::string getExtension();
virtual bool save(KRDataBlock &data); virtual std::string getExtension();
virtual bool save(KRDataBlock& data);
void setAmbientMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset);
void setDiffuseMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset); void setAmbientMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset);
void setSpecularMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset); void setDiffuseMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset);
void setReflectionMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset); void setSpecularMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset);
void setReflectionCube(std::string texture_name); void setReflectionMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset);
void setNormalMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset); void setReflectionCube(std::string texture_name);
void setAmbient(const Vector3 &c); void setNormalMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset);
void setDiffuse(const Vector3 &c); void setAmbient(const Vector3& c);
void setSpecular(const Vector3 &c); void setDiffuse(const Vector3& c);
void setReflection(const Vector3 &c); void setSpecular(const Vector3& c);
void setTransparency(float a); void setReflection(const Vector3& c);
void setShininess(float s); void setTransparency(float a);
void setAlphaMode(alpha_mode_type blend_mode); void setShininess(float s);
alpha_mode_type getAlphaMode(); void setAlphaMode(alpha_mode_type blend_mode);
alpha_mode_type getAlphaMode();
bool isTransparent();
const std::string& getName() const;
void bind(const KRNode::RenderInfo& ri, ModelFormat modelFormat, __uint32_t vertexAttributes, CullMode cullMode, const std::vector<KRBone*>& bones, const std::vector<Matrix4>& bind_poses, const Matrix4& matModel, KRTexture* pLightMap, const Vector3& rim_color, float rim_power, float lod_coverage = 0.0f);
bool needsVertexTangents();
kraken_stream_level getStreamLevel();
void preStream(float lodCoverage);
bool isTransparent();
const std::string &getName() const;
void bind(const KRNode::RenderInfo& ri, ModelFormat modelFormat, __uint32_t vertexAttributes, CullMode cullMode, const std::vector<KRBone*>& bones, const std::vector<Matrix4>& bind_poses, const Matrix4& matModel, KRTexture* pLightMap, const Vector3& rim_color, float rim_power, float lod_coverage = 0.0f);
bool needsVertexTangents();
kraken_stream_level getStreamLevel();
void preStream(float lodCoverage);
private: private:
std::string m_name; std::string m_name;
KRTexture *m_pAmbientMap; // mtl map_Ka value KRTexture* m_pAmbientMap; // mtl map_Ka value
KRTexture *m_pDiffuseMap; // mtl map_Kd value KRTexture* m_pDiffuseMap; // mtl map_Kd value
KRTexture *m_pSpecularMap; // mtl map_Ks value KRTexture* m_pSpecularMap; // mtl map_Ks value
KRTexture *m_pReflectionMap; // mtl refl value KRTexture* m_pReflectionMap; // mtl refl value
KRTexture *m_pReflectionCube; KRTexture* m_pReflectionCube;
KRTexture *m_pNormalMap; // mtl map_Normal value KRTexture* m_pNormalMap; // mtl map_Normal value
std::string m_ambientMap; std::string m_ambientMap;
std::string m_diffuseMap; std::string m_diffuseMap;
std::string m_specularMap; std::string m_specularMap;
std::string m_reflectionMap; std::string m_reflectionMap;
std::string m_reflectionCube; std::string m_reflectionCube;
std::string m_normalMap; std::string m_normalMap;
Vector2 m_ambientMapScale; Vector2 m_ambientMapScale;
Vector2 m_ambientMapOffset; Vector2 m_ambientMapOffset;
Vector2 m_diffuseMapScale; Vector2 m_diffuseMapScale;
Vector2 m_diffuseMapOffset; Vector2 m_diffuseMapOffset;
Vector2 m_specularMapScale; Vector2 m_specularMapScale;
Vector2 m_specularMapOffset; Vector2 m_specularMapOffset;
Vector2 m_reflectionMapScale; Vector2 m_reflectionMapScale;
Vector2 m_reflectionMapOffset; Vector2 m_reflectionMapOffset;
Vector2 m_normalMapScale; Vector2 m_normalMapScale;
Vector2 m_normalMapOffset; Vector2 m_normalMapOffset;
Vector3 m_ambientColor; // Ambient rgb Vector3 m_ambientColor; // Ambient rgb
Vector3 m_diffuseColor; // Diffuse rgb Vector3 m_diffuseColor; // Diffuse rgb
Vector3 m_specularColor; // Specular rgb Vector3 m_specularColor; // Specular rgb
Vector3 m_reflectionColor; // Reflection rgb Vector3 m_reflectionColor; // Reflection rgb
//float m_ka_r, m_ka_g, m_ka_b; // Ambient rgb //float m_ka_r, m_ka_g, m_ka_b; // Ambient rgb
//float m_kd_r, m_kd_g, m_kd_b; // Diffuse rgb //float m_kd_r, m_kd_g, m_kd_b; // Diffuse rgb
//float m_ks_r, m_ks_g, m_ks_b; // Specular rgb //float m_ks_r, m_ks_g, m_ks_b; // Specular rgb
//float m_kr_r, m_kr_g, m_kr_b; // Reflection rgb //float m_kr_r, m_kr_g, m_kr_b; // Reflection rgb
float m_tr; // Transparency float m_tr; // Transparency
float m_ns; // Shininess float m_ns; // Shininess
alpha_mode_type m_alpha_mode; alpha_mode_type m_alpha_mode;
void getTextures(); void getTextures();
}; };

View File

@@ -33,13 +33,14 @@
#include "KRMaterialManager.h" #include "KRMaterialManager.h"
KRMaterialManager::KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRPipelineManager *pPipelineManager) : KRResourceManager(context) KRMaterialManager::KRMaterialManager(KRContext& context, KRTextureManager* pTextureManager, KRPipelineManager* pPipelineManager) : KRResourceManager(context)
{ {
m_pTextureManager = pTextureManager; m_pTextureManager = pTextureManager;
m_pPipelineManager = pPipelineManager; m_pPipelineManager = pPipelineManager;
} }
KRMaterialManager::~KRMaterialManager() { KRMaterialManager::~KRMaterialManager()
{
} }
@@ -62,222 +63,225 @@ KRResource* KRMaterialManager::getResource(const std::string& name, const std::s
return nullptr; return nullptr;
} }
unordered_map<std::string, KRMaterial *> &KRMaterialManager::getMaterials() unordered_map<std::string, KRMaterial*>& KRMaterialManager::getMaterials()
{ {
return m_materials; return m_materials;
} }
KRMaterial *KRMaterialManager::getMaterial(const std::string &name) { KRMaterial* KRMaterialManager::getMaterial(const std::string& name)
std::string lowerName = name; {
std::transform(lowerName.begin(), lowerName.end(), std::string lowerName = name;
lowerName.begin(), ::tolower); std::transform(lowerName.begin(), lowerName.end(),
lowerName.begin(), ::tolower);
unordered_map<std::string, KRMaterial *>::iterator itr = m_materials.find(lowerName);
if(itr == m_materials.end()) { unordered_map<std::string, KRMaterial*>::iterator itr = m_materials.find(lowerName);
KRContext::Log(KRContext::LOG_LEVEL_WARNING, "Material not found: %s", name.c_str()); if (itr == m_materials.end()) {
// Not found KRContext::Log(KRContext::LOG_LEVEL_WARNING, "Material not found: %s", name.c_str());
return NULL; // Not found
return NULL;
} else {
return (*itr).second;
}
}
void KRMaterialManager::add(KRMaterial* new_material)
{
// FINDME, TODO - Potential memory leak if multiple materials with the same name are added
std::string lowerName = new_material->getName();
std::transform(lowerName.begin(), lowerName.end(),
lowerName.begin(), ::tolower);
m_materials[lowerName] = new_material;
}
KRMaterial* KRMaterialManager::load(const char* szName, KRDataBlock* data)
{
KRMaterial* pMaterial = NULL;
char szSymbol[16][256];
data->lock();
char* pScan = (char*)data->getStart();
char* pEnd = (char*)data->getEnd();
while (pScan < pEnd) {
// Scan through whitespace
while (pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
pScan++;
}
if (*pScan == '#') {
// Line is a comment line
// Scan to the end of the line
while (pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
pScan++;
}
} else { } else {
return (*itr).second; int cSymbols = 0;
} while (pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
}
void KRMaterialManager::add(KRMaterial *new_material) { char* pDest = szSymbol[cSymbols++];
// FINDME, TODO - Potential memory leak if multiple materials with the same name are added while (pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
std::string lowerName = new_material->getName(); if (*pScan >= 'A' && *pScan <= 'Z') {
std::transform(lowerName.begin(), lowerName.end(), *pDest++ = *pScan++ + 'a' - 'A'; // convert to lower case for case sensitve comparison later
lowerName.begin(), ::tolower); } else {
*pDest++ = *pScan++;
m_materials[lowerName] = new_material; }
}
KRMaterial* KRMaterialManager::load(const char *szName, KRDataBlock *data) {
KRMaterial *pMaterial = NULL;
char szSymbol[16][256];
data->lock();
char *pScan = (char *)data->getStart();
char *pEnd = (char *)data->getEnd();
while(pScan < pEnd) {
// Scan through whitespace
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
pScan++;
} }
*pDest = '\0';
if(*pScan == '#') {
// Line is a comment line
// Scan to the end of the line
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
pScan++;
}
} else {
int cSymbols = 0;
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
char *pDest = szSymbol[cSymbols++];
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
if(*pScan >= 'A' && *pScan <= 'Z') {
*pDest++ = *pScan++ + 'a' - 'A'; // convert to lower case for case sensitve comparison later
} else {
*pDest++ = *pScan++;
}
}
*pDest = '\0';
// Scan through whitespace, but don't advance to next line
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
pScan++;
}
}
if(cSymbols > 0) {
if(strcmp(szSymbol[0], "newmtl") == 0 && cSymbols >= 2) {
pMaterial = new KRMaterial(*m_pContext, szSymbol[1]);
m_materials[szSymbol[1]] = pMaterial;
}
if(pMaterial != NULL) {
if(strcmp(szSymbol[0], "alpha_mode") == 0) {
if(cSymbols == 2) {
if(strcmp(szSymbol[1], "test") == 0) {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_TEST);
} else if(strcmp(szSymbol[1], "blendoneside") == 0) {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
} else if(strcmp(szSymbol[1], "blendtwoside") == 0) {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
} else {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE);
}
}
} else if(strcmp(szSymbol[0], "ka") == 0) {
char *pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2);
if(cSymbols == 2) {
pMaterial->setAmbient(Vector3::Create(r, r, r));
} else if(cSymbols == 4) {
pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2);
pMaterial->setAmbient(Vector3::Create(r, g, b));
}
} else if(strcmp(szSymbol[0], "kd") == 0) {
char *pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2);
if(cSymbols == 2) {
pMaterial->setDiffuse(Vector3::Create(r, r, r));
} else if(cSymbols == 4) {
pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2);
pMaterial->setDiffuse(Vector3::Create(r, g, b));
}
} else if(strcmp(szSymbol[0], "ks") == 0) {
char *pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2);
if(cSymbols == 2) {
pMaterial->setSpecular(Vector3::Create(r, r, r));
} else if(cSymbols == 4) {
pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2);
pMaterial->setSpecular(Vector3::Create(r, g, b));
}
} else if(strcmp(szSymbol[0], "kr") == 0) {
char *pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2);
if(cSymbols == 2) {
pMaterial->setReflection(Vector3::Create(r, r, r));
} else if(cSymbols == 4) {
pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2);
pMaterial->setReflection(Vector3::Create(r, g, b));
}
} else if(strcmp(szSymbol[0], "tr") == 0) {
char *pScan2 = szSymbol[1];
float a = strtof(pScan2, &pScan2);
pMaterial->setTransparency(a);
} else if(strcmp(szSymbol[0], "ns") == 0) {
char *pScan2 = szSymbol[1];
float a = strtof(pScan2, &pScan2);
pMaterial->setShininess(a);
} else if(strncmp(szSymbol[0], "map", 3) == 0) {
// Truncate file extension
char *pScan2 = szSymbol[1];
char *pLastPeriod = NULL;
while(*pScan2 != '\0') {
if(*pScan2 == '.') {
pLastPeriod = pScan2;
}
pScan2++;
}
if(pLastPeriod) {
*pLastPeriod = '\0';
}
Vector2 texture_scale = Vector2::Create(1.0f, 1.0f); // Scan through whitespace, but don't advance to next line
Vector2 texture_offset = Vector2::Create(0.0f, 0.0f); while (pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
pScan++;
int iScanSymbol = 2;
int iScaleParam = -1;
int iOffsetParam = -1;
while(iScanSymbol < cSymbols) {
if(strcmp(szSymbol[iScanSymbol], "-s") == 0) {
// Scale
iScaleParam = 0;
iOffsetParam = -1;
} else if(strcmp(szSymbol[iScanSymbol], "-o") == 0) {
// Offset
iOffsetParam = 0;
iScaleParam = -1;
} else {
char *pScan3 = szSymbol[iScanSymbol];
float v = strtof(pScan3, &pScan3);
if(iScaleParam == 0) {
texture_scale.x = v;
iScaleParam++;
} else if(iScaleParam == 1) {
texture_scale.y = v;
iScaleParam++;
} else if(iOffsetParam == 0) {
texture_offset.x = v;
iOffsetParam++;
} else if(iOffsetParam == 1) {
texture_offset.y = v;
iOffsetParam++;
}
}
iScanSymbol++;
}
if(strcmp(szSymbol[0], "map_ka") == 0) {
pMaterial->setAmbientMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_kd") == 0) {
pMaterial->setDiffuseMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_ks") == 0) {
pMaterial->setSpecularMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_normal") == 0) {
pMaterial->setNormalMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_reflection") == 0) {
pMaterial->setReflectionMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_reflectioncube") == 0) {
pMaterial->setReflectionCube(szSymbol[1]);
}
}
}
}
} }
}
if (cSymbols > 0) {
if (strcmp(szSymbol[0], "newmtl") == 0 && cSymbols >= 2) {
pMaterial = new KRMaterial(*m_pContext, szSymbol[1]);
m_materials[szSymbol[1]] = pMaterial;
}
if (pMaterial != NULL) {
if (strcmp(szSymbol[0], "alpha_mode") == 0) {
if (cSymbols == 2) {
if (strcmp(szSymbol[1], "test") == 0) {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_TEST);
} else if (strcmp(szSymbol[1], "blendoneside") == 0) {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
} else if (strcmp(szSymbol[1], "blendtwoside") == 0) {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
} else {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE);
}
}
} else if (strcmp(szSymbol[0], "ka") == 0) {
char* pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2);
if (cSymbols == 2) {
pMaterial->setAmbient(Vector3::Create(r, r, r));
} else if (cSymbols == 4) {
pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2);
pMaterial->setAmbient(Vector3::Create(r, g, b));
}
} else if (strcmp(szSymbol[0], "kd") == 0) {
char* pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2);
if (cSymbols == 2) {
pMaterial->setDiffuse(Vector3::Create(r, r, r));
} else if (cSymbols == 4) {
pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2);
pMaterial->setDiffuse(Vector3::Create(r, g, b));
}
} else if (strcmp(szSymbol[0], "ks") == 0) {
char* pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2);
if (cSymbols == 2) {
pMaterial->setSpecular(Vector3::Create(r, r, r));
} else if (cSymbols == 4) {
pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2);
pMaterial->setSpecular(Vector3::Create(r, g, b));
}
} else if (strcmp(szSymbol[0], "kr") == 0) {
char* pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2);
if (cSymbols == 2) {
pMaterial->setReflection(Vector3::Create(r, r, r));
} else if (cSymbols == 4) {
pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2);
pMaterial->setReflection(Vector3::Create(r, g, b));
}
} else if (strcmp(szSymbol[0], "tr") == 0) {
char* pScan2 = szSymbol[1];
float a = strtof(pScan2, &pScan2);
pMaterial->setTransparency(a);
} else if (strcmp(szSymbol[0], "ns") == 0) {
char* pScan2 = szSymbol[1];
float a = strtof(pScan2, &pScan2);
pMaterial->setShininess(a);
} else if (strncmp(szSymbol[0], "map", 3) == 0) {
// Truncate file extension
char* pScan2 = szSymbol[1];
char* pLastPeriod = NULL;
while (*pScan2 != '\0') {
if (*pScan2 == '.') {
pLastPeriod = pScan2;
}
pScan2++;
}
if (pLastPeriod) {
*pLastPeriod = '\0';
}
Vector2 texture_scale = Vector2::Create(1.0f, 1.0f);
Vector2 texture_offset = Vector2::Create(0.0f, 0.0f);
int iScanSymbol = 2;
int iScaleParam = -1;
int iOffsetParam = -1;
while (iScanSymbol < cSymbols) {
if (strcmp(szSymbol[iScanSymbol], "-s") == 0) {
// Scale
iScaleParam = 0;
iOffsetParam = -1;
} else if (strcmp(szSymbol[iScanSymbol], "-o") == 0) {
// Offset
iOffsetParam = 0;
iScaleParam = -1;
} else {
char* pScan3 = szSymbol[iScanSymbol];
float v = strtof(pScan3, &pScan3);
if (iScaleParam == 0) {
texture_scale.x = v;
iScaleParam++;
} else if (iScaleParam == 1) {
texture_scale.y = v;
iScaleParam++;
} else if (iOffsetParam == 0) {
texture_offset.x = v;
iOffsetParam++;
} else if (iOffsetParam == 1) {
texture_offset.y = v;
iOffsetParam++;
}
}
iScanSymbol++;
}
if (strcmp(szSymbol[0], "map_ka") == 0) {
pMaterial->setAmbientMap(szSymbol[1], texture_scale, texture_offset);
} else if (strcmp(szSymbol[0], "map_kd") == 0) {
pMaterial->setDiffuseMap(szSymbol[1], texture_scale, texture_offset);
} else if (strcmp(szSymbol[0], "map_ks") == 0) {
pMaterial->setSpecularMap(szSymbol[1], texture_scale, texture_offset);
} else if (strcmp(szSymbol[0], "map_normal") == 0) {
pMaterial->setNormalMap(szSymbol[1], texture_scale, texture_offset);
} else if (strcmp(szSymbol[0], "map_reflection") == 0) {
pMaterial->setReflectionMap(szSymbol[1], texture_scale, texture_offset);
} else if (strcmp(szSymbol[0], "map_reflectioncube") == 0) {
pMaterial->setReflectionCube(szSymbol[1]);
}
}
}
}
} }
data->unlock();
delete data; }
return pMaterial; data->unlock();
delete data;
return pMaterial;
} }

View File

@@ -43,23 +43,24 @@ class KRMaterial;
using std::map; using std::map;
class KRMaterialManager : public KRResourceManager { class KRMaterialManager : public KRResourceManager
{
public: public:
KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRPipelineManager *pPipelineManager); KRMaterialManager(KRContext& context, KRTextureManager* pTextureManager, KRPipelineManager* pPipelineManager);
virtual ~KRMaterialManager(); virtual ~KRMaterialManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
KRMaterial* load(const char* szName, KRDataBlock* data);
void add(KRMaterial* new_material);
KRMaterial* getMaterial(const std::string& name);
unordered_map<std::string, KRMaterial*>& getMaterials();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
KRMaterial* load(const char *szName, KRDataBlock *data);
void add(KRMaterial *new_material);
KRMaterial *getMaterial(const std::string &name);
unordered_map<std::string, KRMaterial *> &getMaterials();
private: private:
unordered_map<std::string, KRMaterial *> m_materials; unordered_map<std::string, KRMaterial*> m_materials;
KRTextureManager *m_pTextureManager; KRTextureManager* m_pTextureManager;
KRPipelineManager *m_pPipelineManager; KRPipelineManager* m_pPipelineManager;
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -65,230 +65,241 @@ enum class ModelFormat : __uint8_t
KRENGINE_MODEL_FORMAT_INDEXED_STRIP KRENGINE_MODEL_FORMAT_INDEXED_STRIP
}; };
class KRMesh : public KRResource { class KRMesh : public KRResource
{
public: public:
static void parseName(const std::string& name, std::string& lodBaseName, int& lodCoverage); static void parseName(const std::string& name, std::string& lodBaseName, int& lodCoverage);
KRMesh(KRContext &context, std::string name, KRDataBlock *data); KRMesh(KRContext& context, std::string name, KRDataBlock* data);
KRMesh(KRContext &context, std::string name); KRMesh(KRContext& context, std::string name);
virtual ~KRMesh(); virtual ~KRMesh();
kraken_stream_level getStreamLevel(); kraken_stream_level getStreamLevel();
void preStream(float lodCoverage); void preStream(float lodCoverage);
bool hasTransparency(); bool hasTransparency();
typedef enum { typedef enum
KRENGINE_ATTRIB_VERTEX = 0, {
KRENGINE_ATTRIB_NORMAL, KRENGINE_ATTRIB_VERTEX = 0,
KRENGINE_ATTRIB_TANGENT, KRENGINE_ATTRIB_NORMAL,
KRENGINE_ATTRIB_TEXUVA, KRENGINE_ATTRIB_TANGENT,
KRENGINE_ATTRIB_TEXUVB, KRENGINE_ATTRIB_TEXUVA,
KRENGINE_ATTRIB_BONEINDEXES, KRENGINE_ATTRIB_TEXUVB,
KRENGINE_ATTRIB_BONEWEIGHTS, KRENGINE_ATTRIB_BONEINDEXES,
KRENGINE_ATTRIB_VERTEX_SHORT, KRENGINE_ATTRIB_BONEWEIGHTS,
KRENGINE_ATTRIB_NORMAL_SHORT, KRENGINE_ATTRIB_VERTEX_SHORT,
KRENGINE_ATTRIB_TANGENT_SHORT, KRENGINE_ATTRIB_NORMAL_SHORT,
KRENGINE_ATTRIB_TEXUVA_SHORT, KRENGINE_ATTRIB_TANGENT_SHORT,
KRENGINE_ATTRIB_TEXUVB_SHORT, KRENGINE_ATTRIB_TEXUVA_SHORT,
KRENGINE_NUM_ATTRIBUTES KRENGINE_ATTRIB_TEXUVB_SHORT,
} vertex_attrib_t; KRENGINE_NUM_ATTRIBUTES
} vertex_attrib_t;
typedef struct { typedef struct
ModelFormat format; {
std::vector<Vector3> vertices; ModelFormat format;
std::vector<__uint16_t> vertex_indexes; std::vector<Vector3> vertices;
std::vector<std::pair<int, int> > vertex_index_bases; std::vector<__uint16_t> vertex_indexes;
std::vector<Vector2> uva; std::vector<std::pair<int, int> > vertex_index_bases;
std::vector<Vector2> uvb; std::vector<Vector2> uva;
std::vector<Vector3> normals; std::vector<Vector2> uvb;
std::vector<Vector3> tangents; std::vector<Vector3> normals;
std::vector<int> submesh_starts; std::vector<Vector3> tangents;
std::vector<int> submesh_lengths; std::vector<int> submesh_starts;
std::vector<std::string> material_names; std::vector<int> submesh_lengths;
std::vector<std::string> bone_names; std::vector<std::string> material_names;
std::vector<std::vector<int> > bone_indexes; std::vector<std::string> bone_names;
std::vector<Matrix4> bone_bind_poses; std::vector<std::vector<int> > bone_indexes;
std::vector<std::vector<float> > bone_weights; std::vector<Matrix4> bone_bind_poses;
} mesh_info; std::vector<std::vector<float> > bone_weights;
} mesh_info;
void render(const KRNode::RenderInfo& ri, const std::string &object_name, const Matrix4 &matModel, KRTexture *pLightMap, const std::vector<KRBone *> &bones, const Vector3 &rim_color, float rim_power, float lod_coverage = 0.0f); void render(const KRNode::RenderInfo& ri, const std::string& object_name, const Matrix4& matModel, KRTexture* pLightMap, const std::vector<KRBone*>& bones, const Vector3& rim_color, float rim_power, float lod_coverage = 0.0f);
std::string m_lodBaseName; std::string m_lodBaseName;
virtual std::string getExtension(); virtual std::string getExtension();
virtual bool save(const std::string& path); virtual bool save(const std::string& path);
virtual bool save(KRDataBlock &data); virtual bool save(KRDataBlock& data);
void LoadData(const mesh_info &mi, bool calculate_normals, bool calculate_tangents); void LoadData(const mesh_info& mi, bool calculate_normals, bool calculate_tangents);
void loadPack(KRDataBlock *data); void loadPack(KRDataBlock* data);
void convertToIndexed(); void convertToIndexed();
void optimize(); void optimize();
void optimizeIndexes(); void optimizeIndexes();
void renderNoMaterials(VkCommandBuffer& commandBuffer, KRNode::RenderPass renderPass, const std::string& object_name, const std::string& material_name, float lodCoverage); void renderNoMaterials(VkCommandBuffer& commandBuffer, KRNode::RenderPass renderPass, const std::string& object_name, const std::string& material_name, float lodCoverage);
bool isReady() const; bool isReady() const;
float getMaxDimension(); float getMaxDimension();
Vector3 getMinPoint() const; Vector3 getMinPoint() const;
Vector3 getMaxPoint() const; Vector3 getMaxPoint() const;
class Submesh { class Submesh
public: {
Submesh() {}; public:
~Submesh() { Submesh()
for(auto itr = vbo_data_blocks.begin(); itr != vbo_data_blocks.end(); itr++) { {};
delete (*itr); ~Submesh()
} {
for(auto itr = vertex_data_blocks.begin(); itr != vertex_data_blocks.end(); itr++) { for (auto itr = vbo_data_blocks.begin(); itr != vbo_data_blocks.end(); itr++) {
delete (*itr); delete (*itr);
} }
for(auto itr = index_data_blocks.begin(); itr != index_data_blocks.end(); itr++) { for (auto itr = vertex_data_blocks.begin(); itr != vertex_data_blocks.end(); itr++) {
delete (*itr); delete (*itr);
} }
}; for (auto itr = index_data_blocks.begin(); itr != index_data_blocks.end(); itr++) {
delete (*itr);
GLint start_vertex; }
GLsizei vertex_count;
char szMaterialName[KRENGINE_MAX_NAME_LENGTH];
vector<KRDataBlock *> vertex_data_blocks;
vector<KRDataBlock *> index_data_blocks;
vector<KRMeshManager::KRVBOData *> vbo_data_blocks;
}; };
typedef struct { GLint start_vertex;
union { GLsizei vertex_count;
struct { // For Indexed triangles / strips char szMaterialName[KRENGINE_MAX_NAME_LENGTH];
uint16_t index_group; vector<KRDataBlock*> vertex_data_blocks;
uint16_t index_group_offset; vector<KRDataBlock*> index_data_blocks;
}; vector<KRMeshManager::KRVBOData*> vbo_data_blocks;
int32_t start_vertex; // For non-indexed trigangles / strips };
};
int32_t vertex_count;
char szName[KRENGINE_MAX_NAME_LENGTH];
} pack_material;
typedef struct { typedef struct
char szName[KRENGINE_MAX_NAME_LENGTH]; {
float bind_pose[16]; union
} pack_bone; {
struct
{ // For Indexed triangles / strips
uint16_t index_group;
uint16_t index_group_offset;
};
int32_t start_vertex; // For non-indexed trigangles / strips
};
int32_t vertex_count;
char szName[KRENGINE_MAX_NAME_LENGTH];
} pack_material;
int getLODCoverage() const; typedef struct
std::string getLODBaseName() const; {
char szName[KRENGINE_MAX_NAME_LENGTH];
float bind_pose[16];
} pack_bone;
int getLODCoverage() const;
std::string getLODBaseName() const;
static bool lod_sort_predicate(const KRMesh *m1, const KRMesh *m2); static bool lod_sort_predicate(const KRMesh* m1, const KRMesh* m2);
bool has_vertex_attribute(vertex_attrib_t attribute_type) const; bool has_vertex_attribute(vertex_attrib_t attribute_type) const;
static bool has_vertex_attribute(int vertex_attrib_flags, vertex_attrib_t attribute_type); static bool has_vertex_attribute(int vertex_attrib_flags, vertex_attrib_t attribute_type);
int getSubmeshCount() const; int getSubmeshCount() const;
int getVertexCount(int submesh) const; int getVertexCount(int submesh) const;
__uint32_t getVertexAttributes() const; __uint32_t getVertexAttributes() const;
int getTriangleVertexIndex(int submesh, int index) const;
Vector3 getVertexPosition(int index) const;
Vector3 getVertexNormal(int index) const;
Vector3 getVertexTangent(int index) const;
Vector2 getVertexUVA(int index) const;
Vector2 getVertexUVB(int index) const;
int getBoneIndex(int index, int weight_index) const;
float getBoneWeight(int index, int weight_index) const;
void setVertexPosition(int index, const Vector3 &v); int getTriangleVertexIndex(int submesh, int index) const;
void setVertexNormal(int index, const Vector3 &v); Vector3 getVertexPosition(int index) const;
void setVertexTangent(int index, const Vector3 & v); Vector3 getVertexNormal(int index) const;
void setVertexUVA(int index, const Vector2 &v); Vector3 getVertexTangent(int index) const;
void setVertexUVB(int index, const Vector2 &v); Vector2 getVertexUVA(int index) const;
void setBoneIndex(int index, int weight_index, int bone_index); Vector2 getVertexUVB(int index) const;
void setBoneWeight(int index, int weight_index, float bone_weight); int getBoneIndex(int index, int weight_index) const;
float getBoneWeight(int index, int weight_index) const;
static size_t VertexSizeForAttributes(__int32_t vertex_attrib_flags); void setVertexPosition(int index, const Vector3& v);
static size_t AttributeOffset(__int32_t vertex_attrib, __int32_t vertex_attrib_flags); void setVertexNormal(int index, const Vector3& v);
static VkFormat AttributeVulkanFormat(__int32 vertex_attrib); void setVertexTangent(int index, const Vector3& v);
void setVertexUVA(int index, const Vector2& v);
void setVertexUVB(int index, const Vector2& v);
void setBoneIndex(int index, int weight_index, int bone_index);
void setBoneWeight(int index, int weight_index, float bone_weight);
int getBoneCount(); static size_t VertexSizeForAttributes(__int32_t vertex_attrib_flags);
char *getBoneName(int bone_index); static size_t AttributeOffset(__int32_t vertex_attrib, __int32_t vertex_attrib_flags);
Matrix4 getBoneBindPose(int bone_index); static VkFormat AttributeVulkanFormat(__int32 vertex_attrib);
int getBoneCount();
char* getBoneName(int bone_index);
Matrix4 getBoneBindPose(int bone_index);
ModelFormat getModelFormat() const; ModelFormat getModelFormat() const;
bool lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo) const; bool lineCast(const Vector3& v0, const Vector3& v1, HitInfo& hitinfo) const;
bool rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo) const; bool rayCast(const Vector3& v0, const Vector3& dir, HitInfo& hitinfo) const;
bool sphereCast(const Matrix4 &model_to_world, const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo) const; bool sphereCast(const Matrix4& model_to_world, const Vector3& v0, const Vector3& v1, float radius, HitInfo& hitinfo) const;
static int GetLODCoverage(const std::string &name); static int GetLODCoverage(const std::string& name);
protected: protected:
bool m_constant; // TRUE if this should be always loaded and should not be passed through the streamer bool m_constant; // TRUE if this should be always loaded and should not be passed through the streamer
private: private:
KRDataBlock *m_pData; KRDataBlock* m_pData;
KRDataBlock *m_pMetaData; KRDataBlock* m_pMetaData;
KRDataBlock *m_pIndexBaseData; KRDataBlock* m_pIndexBaseData;
void getSubmeshes(); void getSubmeshes();
void getMaterials(); void getMaterials();
void renderSubmesh(VkCommandBuffer& commandBuffer, int iSubmesh, KRNode::RenderPass renderPass, const std::string& object_name, const std::string& material_name, float lodCoverage); void renderSubmesh(VkCommandBuffer& commandBuffer, int iSubmesh, KRNode::RenderPass renderPass, const std::string& object_name, const std::string& material_name, float lodCoverage);
static bool rayCast(const Vector3 &start, const Vector3 &dir, const Triangle3 &tri, const Vector3 &tri_n0, const Vector3 &tri_n1, const Vector3 &tri_n2, HitInfo &hitinfo); static bool rayCast(const Vector3& start, const Vector3& dir, const Triangle3& tri, const Vector3& tri_n0, const Vector3& tri_n1, const Vector3& tri_n2, HitInfo& hitinfo);
static bool sphereCast(const Matrix4 &model_to_world, const Vector3 &v0, const Vector3 &v1, float radius, const Triangle3 &tri, HitInfo &hitinfo); static bool sphereCast(const Matrix4& model_to_world, const Vector3& v0, const Vector3& v1, float radius, const Triangle3& tri, HitInfo& hitinfo);
int m_lodCoverage; // This LOD level is activated when the bounding box of the model will cover less than this percent of the screen (100 = highest detail model) int m_lodCoverage; // This LOD level is activated when the bounding box of the model will cover less than this percent of the screen (100 = highest detail model)
vector<KRMaterial *> m_materials; vector<KRMaterial*> m_materials;
set<KRMaterial *> m_uniqueMaterials; set<KRMaterial*> m_uniqueMaterials;
bool m_hasTransparency; bool m_hasTransparency;
Vector3 m_minPoint, m_maxPoint; Vector3 m_minPoint, m_maxPoint;
typedef struct { typedef struct
char szTag[16]; {
int32_t model_format; // 0 == Triangle list, 1 == Triangle strips, 2 == Indexed triangle list, 3 == Indexed triangle strips, rest are reserved (model_format_t enum) char szTag[16];
int32_t vertex_attrib_flags; int32_t model_format; // 0 == Triangle list, 1 == Triangle strips, 2 == Indexed triangle list, 3 == Indexed triangle strips, rest are reserved (model_format_t enum)
int32_t vertex_count; int32_t vertex_attrib_flags;
int32_t submesh_count; int32_t vertex_count;
int32_t bone_count; int32_t submesh_count;
float minx, miny, minz, maxx, maxy, maxz; // Axis aligned bounding box, in model's coordinate space int32_t bone_count;
int32_t index_count; float minx, miny, minz, maxx, maxy, maxz; // Axis aligned bounding box, in model's coordinate space
int32_t index_base_count; int32_t index_count;
unsigned char reserved[444]; // Pad out to 512 bytes int32_t index_base_count;
} pack_header; unsigned char reserved[444]; // Pad out to 512 bytes
} pack_header;
vector<Submesh *> m_submeshes; vector<Submesh*> m_submeshes;
int m_vertex_attribute_offset[KRENGINE_NUM_ATTRIBUTES]; int m_vertex_attribute_offset[KRENGINE_NUM_ATTRIBUTES];
int m_vertex_size; int m_vertex_size;
void updateAttributeOffsets(); void updateAttributeOffsets();
void setName(const std::string name); void setName(const std::string name);
pack_material *getSubmesh(int mesh_index) const; pack_material* getSubmesh(int mesh_index) const;
unsigned char *getVertexData() const; unsigned char* getVertexData() const;
size_t getVertexDataOffset() const; size_t getVertexDataOffset() const;
unsigned char *getVertexData(int index) const; unsigned char* getVertexData(int index) const;
__uint16_t *getIndexData() const; __uint16_t* getIndexData() const;
size_t getIndexDataOffset() const; size_t getIndexDataOffset() const;
__uint32_t *getIndexBaseData() const; __uint32_t* getIndexBaseData() const;
pack_header *getHeader() const; pack_header* getHeader() const;
pack_bone *getBone(int index); pack_bone* getBone(int index);
void getIndexedRange(int index_group, int &start_index_offset, int &start_vertex_offset, int &index_count, int &vertex_count) const; void getIndexedRange(int index_group, int& start_index_offset, int& start_vertex_offset, int& index_count, int& vertex_count) const;
void releaseData(); void releaseData();
void createDataBlocks(KRMeshManager::KRVBOData::vbo_type t); void createDataBlocks(KRMeshManager::KRVBOData::vbo_type t);
}; };

View File

@@ -32,38 +32,38 @@
#include "KRMeshCube.h" #include "KRMeshCube.h"
KRMeshCube::KRMeshCube(KRContext &context) : KRMesh(context, "__cube") KRMeshCube::KRMeshCube(KRContext& context) : KRMesh(context, "__cube")
{ {
m_constant = true; m_constant = true;
KRMesh::mesh_info mi;
mi.vertices.push_back(Vector3::Create(1.0, 1.0, 1.0));
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, 1.0));
mi.vertices.push_back(Vector3::Create(1.0,-1.0, 1.0));
mi.vertices.push_back(Vector3::Create(-1.0,-1.0, 1.0));
mi.vertices.push_back(Vector3::Create(-1.0,-1.0,-1.0));
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, 1.0));
mi.vertices.push_back(Vector3::Create(-1.0, 1.0,-1.0));
mi.vertices.push_back(Vector3::Create(1.0, 1.0, 1.0));
mi.vertices.push_back(Vector3::Create(1.0, 1.0,-1.0));
mi.vertices.push_back(Vector3::Create(1.0,-1.0, 1.0));
mi.vertices.push_back(Vector3::Create(1.0,-1.0,-1.0));
mi.vertices.push_back(Vector3::Create(-1.0,-1.0,-1.0));
mi.vertices.push_back(Vector3::Create(1.0, 1.0,-1.0));
mi.vertices.push_back(Vector3::Create(-1.0, 1.0,-1.0));
mi.submesh_starts.push_back(0);
mi.submesh_lengths.push_back((int)mi.vertices.size());
mi.material_names.push_back("");
mi.format = ModelFormat::KRENGINE_MODEL_FORMAT_STRIP;
KRMesh::mesh_info mi;
LoadData(mi, true, true);
mi.vertices.push_back(Vector3::Create(1.0, 1.0, 1.0));
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, 1.0));
mi.vertices.push_back(Vector3::Create(1.0, -1.0, 1.0));
mi.vertices.push_back(Vector3::Create(-1.0, -1.0, 1.0));
mi.vertices.push_back(Vector3::Create(-1.0, -1.0, -1.0));
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, 1.0));
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, -1.0));
mi.vertices.push_back(Vector3::Create(1.0, 1.0, 1.0));
mi.vertices.push_back(Vector3::Create(1.0, 1.0, -1.0));
mi.vertices.push_back(Vector3::Create(1.0, -1.0, 1.0));
mi.vertices.push_back(Vector3::Create(1.0, -1.0, -1.0));
mi.vertices.push_back(Vector3::Create(-1.0, -1.0, -1.0));
mi.vertices.push_back(Vector3::Create(1.0, 1.0, -1.0));
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, -1.0));
mi.submesh_starts.push_back(0);
mi.submesh_lengths.push_back((int)mi.vertices.size());
mi.material_names.push_back("");
mi.format = ModelFormat::KRENGINE_MODEL_FORMAT_STRIP;
LoadData(mi, true, true);
} }
KRMeshCube::~KRMeshCube() KRMeshCube::~KRMeshCube()
{ {
} }

View File

@@ -33,10 +33,11 @@
#include "KRMesh.h" #include "KRMesh.h"
class KRMeshCube : public KRMesh { class KRMeshCube : public KRMesh
{
public: public:
KRMeshCube(KRContext &context); KRMeshCube(KRContext& context);
virtual ~KRMeshCube(); virtual ~KRMeshCube();
private: private:
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -41,184 +41,206 @@
class KRContext; class KRContext;
class KRMesh; class KRMesh;
class KRMeshManager : public KRResourceManager { class KRMeshManager : public KRResourceManager
{
public: public:
static const int KRENGINE_MAX_VOLUMETRIC_PLANES=500; static const int KRENGINE_MAX_VOLUMETRIC_PLANES = 500;
static const int KRENGINE_MAX_RANDOM_PARTICLES=150000; static const int KRENGINE_MAX_RANDOM_PARTICLES = 150000;
KRMeshManager(KRContext &context);
void init();
virtual ~KRMeshManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override; KRMeshManager(KRContext& context);
virtual KRResource* getResource(const std::string& name, const std::string& extension) override; void init();
virtual ~KRMeshManager();
void startFrame(float deltaTime);
void endFrame(float deltaTime);
KRMesh *loadModel(const char *szName, KRDataBlock *pData);
std::vector<KRMesh *> getModel(const char *szName);
KRMesh* KRMeshManager::getMaxLODModel(const char* szName);
void addModel(KRMesh *model);
std::vector<std::string> getModelNames();
unordered_multimap<std::string, KRMesh *> &getModels();
class KRVBOData {
public:
typedef enum {
STREAMING,
// STREAMING data is loaded asynchronously, with transfer queues in the streamer thread.
CONSTANT,
// CONSTANT data is loaded asyncrhronously, with transfer queues in the streamer thread, but is not unloaded.
IMMEDIATE virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
// IMMEDIATE data is loaded synchronously, with graphics queues in the presentation threads. virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
// IMMEDIATE data is available for use immediately on the same frame it is generated.
} vbo_type; void startFrame(float deltaTime);
void endFrame(float deltaTime);
KRVBOData();
KRVBOData(KRMeshManager *manager, KRDataBlock *data, KRDataBlock *index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t KRMesh* loadModel(const char* szName, KRDataBlock* pData);
std::vector<KRMesh*> getModel(const char* szName);
KRMesh* KRMeshManager::getMaxLODModel(const char* szName);
void addModel(KRMesh* model);
std::vector<std::string> getModelNames();
unordered_multimap<std::string, KRMesh*>& getModels();
class KRVBOData
{
public:
typedef enum
{
STREAMING,
// STREAMING data is loaded asynchronously, with transfer queues in the streamer thread.
CONSTANT,
// CONSTANT data is loaded asyncrhronously, with transfer queues in the streamer thread, but is not unloaded.
IMMEDIATE
// IMMEDIATE data is loaded synchronously, with graphics queues in the presentation threads.
// IMMEDIATE data is available for use immediately on the same frame it is generated.
} vbo_type;
KRVBOData();
KRVBOData(KRMeshManager* manager, KRDataBlock* data, KRDataBlock* index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t
#if KRENGINE_DEBUG_GPU_LABELS #if KRENGINE_DEBUG_GPU_LABELS
, const char* debug_label , const char* debug_label
#endif #endif
); );
void init(KRMeshManager *manager, KRDataBlock *data, KRDataBlock *index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t void init(KRMeshManager* manager, KRDataBlock* data, KRDataBlock* index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t
#if KRENGINE_DEBUG_GPU_LABELS #if KRENGINE_DEBUG_GPU_LABELS
, const char* debug_label , const char* debug_label
#endif #endif
); );
~KRVBOData(); ~KRVBOData();
KRDataBlock *m_data;
KRDataBlock *m_index_data;
bool isVBOLoaded() { return m_is_vbo_loaded; }
bool isVBOReady() { return m_is_vbo_ready; }
void load();
void load(VkCommandBuffer& commandBuffer);
void unload();
void bind(VkCommandBuffer& commandBuffer);
// Disable copy constructors
KRVBOData(const KRVBOData& o) = delete;
KRVBOData& operator=(const KRVBOData& o) = delete;
long getSize() { return (long)m_size; }
void resetPoolExpiry(float lodCoverage);
long getLastFrameUsed() { return m_last_frame_used; }
vbo_type getType() { return m_type; }
float getStreamPriority();
void _swapHandles();
VkBuffer& getVertexBuffer();
VkBuffer& getIndexBuffer();
uint32_t getVertexAttributes();
private:
KRMeshManager *m_manager;
int m_vertex_attrib_flags;
long m_size;
long m_last_frame_used;
float m_last_frame_max_lod_coverage;
vbo_type m_type;
bool m_static_vbo;
bool m_is_vbo_loaded;
bool m_is_vbo_ready;
typedef struct { KRDataBlock* m_data;
KrDeviceHandle device; KRDataBlock* m_index_data;
VkBuffer vertex_buffer;
VmaAllocation vertex_allocation;
VkBuffer index_buffer;
VmaAllocation index_allocation;
} AllocationInfo;
AllocationInfo m_allocations[KRENGINE_MAX_GPU_COUNT]; bool isVBOLoaded()
{
return m_is_vbo_loaded;
}
bool isVBOReady()
{
return m_is_vbo_ready;
}
void load();
void load(VkCommandBuffer& commandBuffer);
void unload();
void bind(VkCommandBuffer& commandBuffer);
// Disable copy constructors
KRVBOData(const KRVBOData& o) = delete;
KRVBOData& operator=(const KRVBOData& o) = delete;
long getSize()
{
return (long)m_size;
}
void resetPoolExpiry(float lodCoverage);
long getLastFrameUsed()
{
return m_last_frame_used;
}
vbo_type getType()
{
return m_type;
}
float getStreamPriority();
void _swapHandles();
VkBuffer& getVertexBuffer();
VkBuffer& getIndexBuffer();
uint32_t getVertexAttributes();
private:
KRMeshManager* m_manager;
int m_vertex_attrib_flags;
long m_size;
long m_last_frame_used;
float m_last_frame_max_lod_coverage;
vbo_type m_type;
bool m_static_vbo;
bool m_is_vbo_loaded;
bool m_is_vbo_ready;
typedef struct
{
KrDeviceHandle device;
VkBuffer vertex_buffer;
VmaAllocation vertex_allocation;
VkBuffer index_buffer;
VmaAllocation index_allocation;
} AllocationInfo;
AllocationInfo m_allocations[KRENGINE_MAX_GPU_COUNT];
#if KRENGINE_DEBUG_GPU_LABELS #if KRENGINE_DEBUG_GPU_LABELS
char m_debugLabel[KRENGINE_DEBUG_GPU_LABEL_MAX_LEN]; char m_debugLabel[KRENGINE_DEBUG_GPU_LABEL_MAX_LEN];
#endif #endif
}; };
void bindVBO(VkCommandBuffer& commandBuffer, KRVBOData *vbo_data, float lodCoverage);
long getMemUsed();
long getMemActive();
typedef struct {
Vector3 vertex;
Vector2 uva;
} RandomParticleVertexData;
typedef struct {
Vector3 vertex;
} VolumetricLightingVertexData;
long getMemoryTransferedThisFrame();
size_t getActiveVBOCount(); void bindVBO(VkCommandBuffer& commandBuffer, KRVBOData* vbo_data, float lodCoverage);
long getMemUsed();
struct draw_call_info { long getMemActive();
KRNode::RenderPass pass;
char object_name[256];
char material_name[256];
int vertex_count;
};
void log_draw_call(KRNode::RenderPass pass, const std::string &object_name, const std::string &material_name, int vertex_count);
std::vector<draw_call_info> getDrawCalls();
KRVBOData KRENGINE_VBO_DATA_3D_CUBE_VERTICES; typedef struct
KRVBOData KRENGINE_VBO_DATA_2D_SQUARE_VERTICES; {
KRVBOData KRENGINE_VBO_DATA_RANDOM_PARTICLES; Vector3 vertex;
KRVBOData KRENGINE_VBO_DATA_VOLUMETRIC_LIGHTING; Vector2 uva;
} RandomParticleVertexData;
typedef struct
{
Vector3 vertex;
} VolumetricLightingVertexData;
long getMemoryTransferedThisFrame();
size_t getActiveVBOCount();
struct draw_call_info
{
KRNode::RenderPass pass;
char object_name[256];
char material_name[256];
int vertex_count;
};
void log_draw_call(KRNode::RenderPass pass, const std::string& object_name, const std::string& material_name, int vertex_count);
std::vector<draw_call_info> getDrawCalls();
KRVBOData KRENGINE_VBO_DATA_3D_CUBE_VERTICES;
KRVBOData KRENGINE_VBO_DATA_2D_SQUARE_VERTICES;
KRVBOData KRENGINE_VBO_DATA_RANDOM_PARTICLES;
KRVBOData KRENGINE_VBO_DATA_VOLUMETRIC_LIGHTING;
void doStreaming(long& memoryRemaining, long& memoryRemainingThisFrame);
void doStreaming(long &memoryRemaining, long &memoryRemainingThisFrame);
private: private:
KRDataBlock KRENGINE_VBO_3D_CUBE_VERTICES; KRDataBlock KRENGINE_VBO_3D_CUBE_VERTICES;
__int32_t KRENGINE_VBO_3D_CUBE_ATTRIBS; __int32_t KRENGINE_VBO_3D_CUBE_ATTRIBS;
KRDataBlock KRENGINE_VBO_2D_SQUARE_VERTICES; KRDataBlock KRENGINE_VBO_2D_SQUARE_VERTICES;
__int32_t KRENGINE_VBO_2D_SQUARE_ATTRIBS; __int32_t KRENGINE_VBO_2D_SQUARE_ATTRIBS;
unordered_multimap<std::string, KRMesh *> m_models; // Multiple models with the same name/key may be inserted, representing multiple LOD levels of the model
long m_vboMemUsed;
KRVBOData *m_currentVBO;
unordered_map<KRDataBlock *, KRVBOData *> m_vbosActive;
std::vector<std::pair<float, KRVBOData *> > m_activeVBOs_streamer;
std::vector<std::pair<float, KRVBOData *> > m_activeVBOs_streamer_copy;
KRDataBlock m_randomParticleVertexData;
KRDataBlock m_volumetricLightingVertexData;
long m_memoryTransferredThisFrame;
std::vector<draw_call_info> m_draw_calls;
bool m_draw_call_logging_enabled;
bool m_draw_call_log_used;
std::mutex m_streamerFenceMutex;
bool m_streamerComplete;
void balanceVBOMemory(long &memoryRemaining, long &memoryRemainingThisFrame);
void primeVBO(KRVBOData *vbo_data);
void initRandomParticles(); unordered_multimap<std::string, KRMesh*> m_models; // Multiple models with the same name/key may be inserted, representing multiple LOD levels of the model
void initVolumetricLightingVertexes();
long m_vboMemUsed;
KRVBOData* m_currentVBO;
unordered_map<KRDataBlock*, KRVBOData*> m_vbosActive;
std::vector<std::pair<float, KRVBOData*> > m_activeVBOs_streamer;
std::vector<std::pair<float, KRVBOData*> > m_activeVBOs_streamer_copy;
KRDataBlock m_randomParticleVertexData;
KRDataBlock m_volumetricLightingVertexData;
long m_memoryTransferredThisFrame;
std::vector<draw_call_info> m_draw_calls;
bool m_draw_call_logging_enabled;
bool m_draw_call_log_used;
std::mutex m_streamerFenceMutex;
bool m_streamerComplete;
void balanceVBOMemory(long& memoryRemaining, long& memoryRemainingThisFrame);
void primeVBO(KRVBOData* vbo_data);
void initRandomParticles();
void initVolumetricLightingVertexes();
}; };

View File

@@ -32,32 +32,32 @@
#include "KRMeshQuad.h" #include "KRMeshQuad.h"
KRMeshQuad::KRMeshQuad(KRContext &context) : KRMesh(context, "__quad") KRMeshQuad::KRMeshQuad(KRContext& context) : KRMesh(context, "__quad")
{ {
m_constant = true; m_constant = true;
KRMesh::mesh_info mi; KRMesh::mesh_info mi;
mi.vertices.push_back(Vector3::Create(-1.0f, -1.0f, 0.0f)); mi.vertices.push_back(Vector3::Create(-1.0f, -1.0f, 0.0f));
mi.vertices.push_back(Vector3::Create(1.0f, -1.0f, 0.0f)); mi.vertices.push_back(Vector3::Create(1.0f, -1.0f, 0.0f));
mi.vertices.push_back(Vector3::Create(-1.0f, 1.0f, 0.0f)); mi.vertices.push_back(Vector3::Create(-1.0f, 1.0f, 0.0f));
mi.vertices.push_back(Vector3::Create(1.0f, 1.0f, 0.0f)); mi.vertices.push_back(Vector3::Create(1.0f, 1.0f, 0.0f));
mi.uva.push_back(Vector2::Create(0.0f, 0.0f)); mi.uva.push_back(Vector2::Create(0.0f, 0.0f));
mi.uva.push_back(Vector2::Create(1.0f, 0.0f)); mi.uva.push_back(Vector2::Create(1.0f, 0.0f));
mi.uva.push_back(Vector2::Create(0.0f, 1.0f)); mi.uva.push_back(Vector2::Create(0.0f, 1.0f));
mi.uva.push_back(Vector2::Create(1.0f, 1.0f)); mi.uva.push_back(Vector2::Create(1.0f, 1.0f));
mi.submesh_starts.push_back(0); mi.submesh_starts.push_back(0);
mi.submesh_lengths.push_back((int)mi.vertices.size()); mi.submesh_lengths.push_back((int)mi.vertices.size());
mi.material_names.push_back(""); mi.material_names.push_back("");
mi.format = ModelFormat::KRENGINE_MODEL_FORMAT_STRIP; mi.format = ModelFormat::KRENGINE_MODEL_FORMAT_STRIP;
LoadData(mi, true, true); LoadData(mi, true, true);
} }
KRMeshQuad::~KRMeshQuad() KRMeshQuad::~KRMeshQuad()
{ {
} }

View File

@@ -33,9 +33,10 @@
#include "KRMesh.h" #include "KRMesh.h"
class KRMeshQuad : public KRMesh { class KRMeshQuad : public KRMesh
{
public: public:
KRMeshQuad(KRContext &context); KRMeshQuad(KRContext& context);
virtual ~KRMeshQuad(); virtual ~KRMeshQuad();
private: private:
}; };

View File

@@ -32,97 +32,97 @@
#include "KRMeshSphere.h" #include "KRMeshSphere.h"
KRMeshSphere::KRMeshSphere(KRContext &context) : KRMesh(context, "__sphere") KRMeshSphere::KRMeshSphere(KRContext& context) : KRMesh(context, "__sphere")
{ {
m_constant = true; m_constant = true;
KRMesh::mesh_info mi;
// Create a triangular facet approximation to a sphere
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
int iterations = 3;
int facet_count = (int)(pow(4, iterations) * 8.0f);
std::vector<Triangle3> f = std::vector<Triangle3>(facet_count);
int i,it;
float a;
Vector3 p[6] = {
Vector3::Create(0,0,1),
Vector3::Create(0,0,-1),
Vector3::Create(-1,-1,0),
Vector3::Create(1,-1,0),
Vector3::Create(1,1,0),
Vector3::Create(-1,1,0)
};
Vector3 pa,pb,pc;
int nt = 0,ntold;
/* Create the level 0 object */
a = 1.0f / sqrtf(2.0f);
for (i=0;i<6;i++) {
p[i].x *= a;
p[i].y *= a;
}
f[0][0] = p[0]; f[0][1] = p[3]; f[0][2] = p[4];
f[1][0] = p[0]; f[1][1] = p[4]; f[1][2] = p[5];
f[2][0] = p[0]; f[2][1] = p[5]; f[2][2] = p[2];
f[3][0] = p[0]; f[3][1] = p[2]; f[3][2] = p[3];
f[4][0] = p[1]; f[4][1] = p[4]; f[4][2] = p[3];
f[5][0] = p[1]; f[5][1] = p[5]; f[5][2] = p[4];
f[6][0] = p[1]; f[6][1] = p[2]; f[6][2] = p[5];
f[7][0] = p[1]; f[7][1] = p[3]; f[7][2] = p[2];
nt = 8;
/* Bisect each edge and move to the surface of a unit sphere */
for (it=0;it<iterations;it++) {
ntold = nt;
for (i=0;i<ntold;i++) {
pa.x = (f[i][0].x + f[i][1].x) / 2;
pa.y = (f[i][0].y + f[i][1].y) / 2;
pa.z = (f[i][0].z + f[i][1].z) / 2;
pb.x = (f[i][1].x + f[i][2].x) / 2;
pb.y = (f[i][1].y + f[i][2].y) / 2;
pb.z = (f[i][1].z + f[i][2].z) / 2;
pc.x = (f[i][2].x + f[i][0].x) / 2;
pc.y = (f[i][2].y + f[i][0].y) / 2;
pc.z = (f[i][2].z + f[i][0].z) / 2;
pa.normalize();
pb.normalize();
pc.normalize();
f[nt][0] = f[i][0]; f[nt][1] = pa; f[nt][2] = pc; nt++;
f[nt][0] = pa; f[nt][1] = f[i][1]; f[nt][2] = pb; nt++;
f[nt][0] = pb; f[nt][1] = f[i][2]; f[nt][2] = pc; nt++;
f[i][0] = pa;
f[i][1] = pb;
f[i][2] = pc;
}
}
for(int facet_index=0; facet_index < facet_count; facet_index++) {
mi.vertices.push_back(f[facet_index][0]);
mi.vertices.push_back(f[facet_index][1]);
mi.vertices.push_back(f[facet_index][2]);
}
mi.submesh_starts.push_back(0);
mi.submesh_lengths.push_back((int)mi.vertices.size());
mi.material_names.push_back("");
mi.format = ModelFormat::KRENGINE_MODEL_FORMAT_TRIANGLES; KRMesh::mesh_info mi;
// Generate normals pointing away from center of sphere.
for (int vertex_index = 0; vertex_index < mi.vertices.size(); vertex_index++) {
mi.normals.push_back(Vector3::Normalize(mi.vertices[vertex_index] - Vector3::Zero()));
}
LoadData(mi, true, true); // Create a triangular facet approximation to a sphere
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
int iterations = 3;
int facet_count = (int)(pow(4, iterations) * 8.0f);
std::vector<Triangle3> f = std::vector<Triangle3>(facet_count);
int i, it;
float a;
Vector3 p[6] = {
Vector3::Create(0,0,1),
Vector3::Create(0,0,-1),
Vector3::Create(-1,-1,0),
Vector3::Create(1,-1,0),
Vector3::Create(1,1,0),
Vector3::Create(-1,1,0)
};
Vector3 pa, pb, pc;
int nt = 0, ntold;
/* Create the level 0 object */
a = 1.0f / sqrtf(2.0f);
for (i = 0; i < 6; i++) {
p[i].x *= a;
p[i].y *= a;
}
f[0][0] = p[0]; f[0][1] = p[3]; f[0][2] = p[4];
f[1][0] = p[0]; f[1][1] = p[4]; f[1][2] = p[5];
f[2][0] = p[0]; f[2][1] = p[5]; f[2][2] = p[2];
f[3][0] = p[0]; f[3][1] = p[2]; f[3][2] = p[3];
f[4][0] = p[1]; f[4][1] = p[4]; f[4][2] = p[3];
f[5][0] = p[1]; f[5][1] = p[5]; f[5][2] = p[4];
f[6][0] = p[1]; f[6][1] = p[2]; f[6][2] = p[5];
f[7][0] = p[1]; f[7][1] = p[3]; f[7][2] = p[2];
nt = 8;
/* Bisect each edge and move to the surface of a unit sphere */
for (it = 0; it < iterations; it++) {
ntold = nt;
for (i = 0; i < ntold; i++) {
pa.x = (f[i][0].x + f[i][1].x) / 2;
pa.y = (f[i][0].y + f[i][1].y) / 2;
pa.z = (f[i][0].z + f[i][1].z) / 2;
pb.x = (f[i][1].x + f[i][2].x) / 2;
pb.y = (f[i][1].y + f[i][2].y) / 2;
pb.z = (f[i][1].z + f[i][2].z) / 2;
pc.x = (f[i][2].x + f[i][0].x) / 2;
pc.y = (f[i][2].y + f[i][0].y) / 2;
pc.z = (f[i][2].z + f[i][0].z) / 2;
pa.normalize();
pb.normalize();
pc.normalize();
f[nt][0] = f[i][0]; f[nt][1] = pa; f[nt][2] = pc; nt++;
f[nt][0] = pa; f[nt][1] = f[i][1]; f[nt][2] = pb; nt++;
f[nt][0] = pb; f[nt][1] = f[i][2]; f[nt][2] = pc; nt++;
f[i][0] = pa;
f[i][1] = pb;
f[i][2] = pc;
}
}
for (int facet_index = 0; facet_index < facet_count; facet_index++) {
mi.vertices.push_back(f[facet_index][0]);
mi.vertices.push_back(f[facet_index][1]);
mi.vertices.push_back(f[facet_index][2]);
}
mi.submesh_starts.push_back(0);
mi.submesh_lengths.push_back((int)mi.vertices.size());
mi.material_names.push_back("");
mi.format = ModelFormat::KRENGINE_MODEL_FORMAT_TRIANGLES;
// Generate normals pointing away from center of sphere.
for (int vertex_index = 0; vertex_index < mi.vertices.size(); vertex_index++) {
mi.normals.push_back(Vector3::Normalize(mi.vertices[vertex_index] - Vector3::Zero()));
}
LoadData(mi, true, true);
} }
KRMeshSphere::~KRMeshSphere() KRMeshSphere::~KRMeshSphere()
{ {
} }

View File

@@ -33,9 +33,10 @@
#include "KRMesh.h" #include "KRMesh.h"
class KRMeshSphere : public KRMesh { class KRMeshSphere : public KRMesh
{
public: public:
KRMeshSphere(KRContext &context); KRMeshSphere(KRContext& context);
virtual ~KRMeshSphere(); virtual ~KRMeshSphere();
private: private:
}; };

View File

@@ -49,234 +49,240 @@ void KRModel::InitNodeInfo(KrNodeInfo* nodeInfo)
nodeInfo->model.rim_power = 0.0f; nodeInfo->model.rim_power = 0.0f;
} }
KRModel::KRModel(KRScene &scene, std::string instance_name, std::string model_name, std::string light_map, float lod_min_coverage, bool receives_shadow, bool faces_camera, Vector3 rim_color, float rim_power) : KRNode(scene, instance_name) { KRModel::KRModel(KRScene& scene, std::string instance_name, std::string model_name, std::string light_map, float lod_min_coverage, bool receives_shadow, bool faces_camera, Vector3 rim_color, float rim_power) : KRNode(scene, instance_name)
m_lightMap = light_map;
m_pLightMap = NULL;
m_model_name = model_name;
m_min_lod_coverage = lod_min_coverage;
m_receivesShadow = receives_shadow;
m_faces_camera = faces_camera;
m_rim_color = rim_color;
m_rim_power = rim_power;
m_boundsCachedMat.c[0] = -1.0f;
m_boundsCachedMat.c[1] = -1.0f;
m_boundsCachedMat.c[2] = -1.0f;
m_boundsCachedMat.c[3] = -1.0f;
m_boundsCachedMat.c[4] = -1.0f;
m_boundsCachedMat.c[5] = -1.0f;
m_boundsCachedMat.c[6] = -1.0f;
m_boundsCachedMat.c[7] = -1.0f;
m_boundsCachedMat.c[8] = -1.0f;
m_boundsCachedMat.c[9] = -1.0f;
m_boundsCachedMat.c[10] = -1.0f;
m_boundsCachedMat.c[11] = -1.0f;
m_boundsCachedMat.c[12] = -1.0f;
m_boundsCachedMat.c[13] = -1.0f;
m_boundsCachedMat.c[14] = -1.0f;
m_boundsCachedMat.c[15] = -1.0f;
}
KRModel::~KRModel() {
}
std::string KRModel::getElementName() {
return "model";
}
tinyxml2::XMLElement *KRModel::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); m_lightMap = light_map;
e->SetAttribute("mesh", m_model_name.c_str()); m_pLightMap = NULL;
e->SetAttribute("light_map", m_lightMap.c_str()); m_model_name = model_name;
e->SetAttribute("lod_min_coverage", m_min_lod_coverage); m_min_lod_coverage = lod_min_coverage;
e->SetAttribute("receives_shadow", m_receivesShadow ? "true" : "false"); m_receivesShadow = receives_shadow;
e->SetAttribute("faces_camera", m_faces_camera ? "true" : "false"); m_faces_camera = faces_camera;
kraken::setXMLAttribute("rim_color", e, m_rim_color, Vector3::Zero()); m_rim_color = rim_color;
e->SetAttribute("rim_power", m_rim_power); m_rim_power = rim_power;
return e;
m_boundsCachedMat.c[0] = -1.0f;
m_boundsCachedMat.c[1] = -1.0f;
m_boundsCachedMat.c[2] = -1.0f;
m_boundsCachedMat.c[3] = -1.0f;
m_boundsCachedMat.c[4] = -1.0f;
m_boundsCachedMat.c[5] = -1.0f;
m_boundsCachedMat.c[6] = -1.0f;
m_boundsCachedMat.c[7] = -1.0f;
m_boundsCachedMat.c[8] = -1.0f;
m_boundsCachedMat.c[9] = -1.0f;
m_boundsCachedMat.c[10] = -1.0f;
m_boundsCachedMat.c[11] = -1.0f;
m_boundsCachedMat.c[12] = -1.0f;
m_boundsCachedMat.c[13] = -1.0f;
m_boundsCachedMat.c[14] = -1.0f;
m_boundsCachedMat.c[15] = -1.0f;
} }
void KRModel::setRimColor(const Vector3 &rim_color) KRModel::~KRModel()
{ {
m_rim_color = rim_color;
}
std::string KRModel::getElementName()
{
return "model";
}
tinyxml2::XMLElement* KRModel::saveXML(tinyxml2::XMLNode* parent)
{
tinyxml2::XMLElement* e = KRNode::saveXML(parent);
e->SetAttribute("mesh", m_model_name.c_str());
e->SetAttribute("light_map", m_lightMap.c_str());
e->SetAttribute("lod_min_coverage", m_min_lod_coverage);
e->SetAttribute("receives_shadow", m_receivesShadow ? "true" : "false");
e->SetAttribute("faces_camera", m_faces_camera ? "true" : "false");
kraken::setXMLAttribute("rim_color", e, m_rim_color, Vector3::Zero());
e->SetAttribute("rim_power", m_rim_power);
return e;
}
void KRModel::setRimColor(const Vector3& rim_color)
{
m_rim_color = rim_color;
} }
void KRModel::setRimPower(float rim_power) void KRModel::setRimPower(float rim_power)
{ {
m_rim_power = rim_power; m_rim_power = rim_power;
} }
Vector3 KRModel::getRimColor() Vector3 KRModel::getRimColor()
{ {
return m_rim_color; return m_rim_color;
} }
float KRModel::getRimPower() float KRModel::getRimPower()
{ {
return m_rim_power; return m_rim_power;
} }
void KRModel::setLightMap(const std::string &name) void KRModel::setLightMap(const std::string& name)
{ {
m_lightMap = name; m_lightMap = name;
m_pLightMap = NULL; m_pLightMap = NULL;
} }
std::string KRModel::getLightMap() std::string KRModel::getLightMap()
{ {
return m_lightMap; return m_lightMap;
} }
void KRModel::loadModel() { void KRModel::loadModel()
if(m_models.size() == 0) {
std::vector<KRMesh *> models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first
unordered_map<KRMesh *, std::vector<KRBone *> > bones;
if(models.size() > 0) {
bool all_bones_found = true;
for(std::vector<KRMesh *>::iterator model_itr = models.begin(); model_itr != models.end(); model_itr++) {
KRMesh *model = *model_itr;
std::vector<KRBone *> model_bones;
int bone_count = model->getBoneCount();
for(int bone_index=0; bone_index < bone_count; bone_index++) {
KRBone *matching_bone = dynamic_cast<KRBone *>(getScene().getRootNode()->find<KRNode>(model->getBoneName(bone_index)));
if(matching_bone) {
model_bones.push_back(matching_bone);
} else {
all_bones_found = false; // Reject when there are any missing bones or multiple matches
}
}
bones[model] = model_bones;
}
if(all_bones_found) {
m_models = models;
m_bones = bones;
getScene().notify_sceneGraphModify(this);
}
invalidateBounds();
}
}
}
void KRModel::render(KRNode::RenderInfo& ri) {
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && ri.renderPass == KRNode::RENDER_PASS_PRESTREAM) {
preStream(ri.viewport);
}
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(ri);
if(ri.renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS
&& ri.renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES
&& ri.renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION
&& ri.renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE
&& ri.renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS
&& ri.renderPass != KRNode::RENDER_PASS_PRESTREAM) {
loadModel();
if(m_models.size() > 0) {
// Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied
/*
float lod_coverage = 0.0f;
if(m_models.size() > 1) {
lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
} else if(viewport.visible(getBounds())) {
lod_coverage = 1.0f;
}
*/
float lod_coverage = ri.viewport.coverage(getBounds()); // This also checks the view frustrum culling
if(lod_coverage > m_min_lod_coverage) {
// ---===--- Select the best LOD model based on screen coverage ---===---
std::vector<KRMesh *>::iterator itr=m_models.begin();
KRMesh *pModel = *itr++;
while(itr != m_models.end()) {
KRMesh *pLODModel = *itr++;
if((float)pLODModel->getLODCoverage() / 100.0f > lod_coverage && pLODModel->getLODCoverage() < pModel->getLODCoverage()) {
pModel = pLODModel;
} else {
break;
}
}
if(m_pLightMap == NULL && m_lightMap.size()) {
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
}
if(m_pLightMap && ri.camera->settings.bEnableLightMap && ri.renderPass != RENDER_PASS_SHADOWMAP && ri.renderPass != RENDER_PASS_GENERATE_SHADOWMAPS) {
m_pContext->getTextureManager()->selectTexture(5, m_pLightMap, lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
}
Matrix4 matModel = getModelMatrix();
if(m_faces_camera) {
Vector3 model_center = Matrix4::Dot(matModel, Vector3::Zero());
Vector3 camera_pos = ri.viewport.getCameraPosition();
matModel = Quaternion::Create(Vector3::Forward(), Vector3::Normalize(camera_pos - model_center)).rotationMatrix() * matModel;
}
pModel->render(ri, getName(), matModel, m_pLightMap, m_bones[pModel], m_rim_color, m_rim_power, lod_coverage);
}
}
}
}
void KRModel::preStream(const KRViewport &viewport)
{ {
loadModel(); if (m_models.size() == 0) {
float lod_coverage = viewport.coverage(getBounds()); std::vector<KRMesh*> models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first
unordered_map<KRMesh*, std::vector<KRBone*> > bones;
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) { if (models.size() > 0) {
(*itr)->preStream(lod_coverage); bool all_bones_found = true;
} for (std::vector<KRMesh*>::iterator model_itr = models.begin(); model_itr != models.end(); model_itr++) {
KRMesh* model = *model_itr;
if(m_pLightMap == NULL && m_lightMap.size()) { std::vector<KRBone*> model_bones;
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap); int bone_count = model->getBoneCount();
} for (int bone_index = 0; bone_index < bone_count; bone_index++) {
KRBone* matching_bone = dynamic_cast<KRBone*>(getScene().getRootNode()->find<KRNode>(model->getBoneName(bone_index)));
if(m_pLightMap) { if (matching_bone) {
m_pLightMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP); model_bones.push_back(matching_bone);
} } else {
} all_bones_found = false; // Reject when there are any missing bones or multiple matches
}
kraken_stream_level KRModel::getStreamLevel(const KRViewport &viewport)
{
kraken_stream_level stream_level = KRNode::getStreamLevel(viewport);
loadModel();
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
stream_level = KRMIN(stream_level, (*itr)->getStreamLevel());
}
return stream_level;
}
AABB KRModel::getBounds() {
loadModel();
if(m_models.size() > 0) {
if(m_faces_camera) {
AABB normal_bounds = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
float max_dimension = normal_bounds.longest_radius();
return AABB::Create(normal_bounds.center()-Vector3::Create(max_dimension), normal_bounds.center() + Vector3::Create(max_dimension));
} else {
if(!(m_boundsCachedMat == getModelMatrix())) {
m_boundsCachedMat = getModelMatrix();
m_boundsCached = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
}
return m_boundsCached;
} }
bones[model] = model_bones;
}
if (all_bones_found) {
m_models = models;
m_bones = bones;
getScene().notify_sceneGraphModify(this);
}
invalidateBounds();
}
}
}
void KRModel::render(KRNode::RenderInfo& ri)
{
if (m_lod_visible >= LOD_VISIBILITY_PRESTREAM && ri.renderPass == KRNode::RENDER_PASS_PRESTREAM) {
preStream(ri.viewport);
}
if (m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(ri);
if (ri.renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS
&& ri.renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES
&& ri.renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION
&& ri.renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE
&& ri.renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS
&& ri.renderPass != KRNode::RENDER_PASS_PRESTREAM) {
loadModel();
if (m_models.size() > 0) {
// Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied
/*
float lod_coverage = 0.0f;
if(m_models.size() > 1) {
lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
} else if(viewport.visible(getBounds())) {
lod_coverage = 1.0f;
}
*/
float lod_coverage = ri.viewport.coverage(getBounds()); // This also checks the view frustrum culling
if (lod_coverage > m_min_lod_coverage) {
// ---===--- Select the best LOD model based on screen coverage ---===---
std::vector<KRMesh*>::iterator itr = m_models.begin();
KRMesh* pModel = *itr++;
while (itr != m_models.end()) {
KRMesh* pLODModel = *itr++;
if ((float)pLODModel->getLODCoverage() / 100.0f > lod_coverage && pLODModel->getLODCoverage() < pModel->getLODCoverage()) {
pModel = pLODModel;
} else {
break;
}
}
if (m_pLightMap == NULL && m_lightMap.size()) {
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
}
if (m_pLightMap && ri.camera->settings.bEnableLightMap && ri.renderPass != RENDER_PASS_SHADOWMAP && ri.renderPass != RENDER_PASS_GENERATE_SHADOWMAPS) {
m_pContext->getTextureManager()->selectTexture(5, m_pLightMap, lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
}
Matrix4 matModel = getModelMatrix();
if (m_faces_camera) {
Vector3 model_center = Matrix4::Dot(matModel, Vector3::Zero());
Vector3 camera_pos = ri.viewport.getCameraPosition();
matModel = Quaternion::Create(Vector3::Forward(), Vector3::Normalize(camera_pos - model_center)).rotationMatrix() * matModel;
}
pModel->render(ri, getName(), matModel, m_pLightMap, m_bones[pModel], m_rim_color, m_rim_power, lod_coverage);
}
}
}
}
void KRModel::preStream(const KRViewport& viewport)
{
loadModel();
float lod_coverage = viewport.coverage(getBounds());
for (auto itr = m_models.begin(); itr != m_models.end(); itr++) {
(*itr)->preStream(lod_coverage);
}
if (m_pLightMap == NULL && m_lightMap.size()) {
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
}
if (m_pLightMap) {
m_pLightMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
}
}
kraken_stream_level KRModel::getStreamLevel(const KRViewport& viewport)
{
kraken_stream_level stream_level = KRNode::getStreamLevel(viewport);
loadModel();
for (auto itr = m_models.begin(); itr != m_models.end(); itr++) {
stream_level = KRMIN(stream_level, (*itr)->getStreamLevel());
}
return stream_level;
}
AABB KRModel::getBounds()
{
loadModel();
if (m_models.size() > 0) {
if (m_faces_camera) {
AABB normal_bounds = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
float max_dimension = normal_bounds.longest_radius();
return AABB::Create(normal_bounds.center() - Vector3::Create(max_dimension), normal_bounds.center() + Vector3::Create(max_dimension));
} else { } else {
return AABB::Infinite();
if (!(m_boundsCachedMat == getModelMatrix())) {
m_boundsCachedMat = getModelMatrix();
m_boundsCached = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
}
return m_boundsCached;
} }
} else {
return AABB::Infinite();
}
} }

View File

@@ -43,52 +43,53 @@
#include "KRTexture.h" #include "KRTexture.h"
#include "KRBone.h" #include "KRBone.h"
class KRModel : public KRNode { class KRModel : public KRNode
{
public: public:
static void InitNodeInfo(KrNodeInfo* nodeInfo); static void InitNodeInfo(KrNodeInfo* nodeInfo);
KRModel(KRScene &scene, std::string instance_name, std::string model_name, std::string light_map, float lod_min_coverage, bool receives_shadow, bool faces_camera, Vector3 rim_color = Vector3::Zero(), float rim_power = 0.0f); KRModel(KRScene& scene, std::string instance_name, std::string model_name, std::string light_map, float lod_min_coverage, bool receives_shadow, bool faces_camera, Vector3 rim_color = Vector3::Zero(), float rim_power = 0.0f);
virtual ~KRModel(); virtual ~KRModel();
virtual std::string getElementName(); virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
virtual void render(KRNode::RenderInfo& ri);
virtual AABB getBounds();
void setRimColor(const Vector3& rim_color);
void setRimPower(float rim_power);
Vector3 getRimColor();
float getRimPower();
void setLightMap(const std::string& name);
std::string getLightMap();
virtual kraken_stream_level getStreamLevel(const KRViewport& viewport);
virtual void render(KRNode::RenderInfo& ri);
virtual AABB getBounds();
void setRimColor(const Vector3 &rim_color);
void setRimPower(float rim_power);
Vector3 getRimColor();
float getRimPower();
void setLightMap(const std::string &name);
std::string getLightMap();
virtual kraken_stream_level getStreamLevel(const KRViewport &viewport);
private: private:
void preStream(const KRViewport &viewport); void preStream(const KRViewport& viewport);
std::vector<KRMesh *> m_models; std::vector<KRMesh*> m_models;
unordered_map<KRMesh *, std::vector<KRBone *> > m_bones; // Outer std::map connects model to set of bones unordered_map<KRMesh*, std::vector<KRBone*> > m_bones; // Outer std::map connects model to set of bones
KRTexture *m_pLightMap; KRTexture* m_pLightMap;
std::string m_lightMap; std::string m_lightMap;
std::string m_model_name; std::string m_model_name;
float m_min_lod_coverage; float m_min_lod_coverage;
void loadModel(); void loadModel();
bool m_receivesShadow; bool m_receivesShadow;
bool m_faces_camera; bool m_faces_camera;
Matrix4 m_boundsCachedMat; Matrix4 m_boundsCachedMat;
AABB m_boundsCached; AABB m_boundsCached;
Vector3 m_rim_color; Vector3 m_rim_color;
float m_rim_power; float m_rim_power;
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -56,291 +56,295 @@ class KRPointLight;
class KRSpotLight; class KRSpotLight;
class KRDirectionalLight; class KRDirectionalLight;
namespace tinyxml2 { namespace tinyxml2 {
class XMLNode; class XMLNode;
class XMLAttribute; class XMLAttribute;
} }
class KRNode : public KRContextObject class KRNode : public KRContextObject
{ {
public: public:
enum RenderPass { enum RenderPass
RENDER_PASS_FORWARD_OPAQUE, {
RENDER_PASS_DEFERRED_GBUFFER, RENDER_PASS_FORWARD_OPAQUE,
RENDER_PASS_DEFERRED_LIGHTS, RENDER_PASS_DEFERRED_GBUFFER,
RENDER_PASS_DEFERRED_OPAQUE, RENDER_PASS_DEFERRED_LIGHTS,
RENDER_PASS_FORWARD_TRANSPARENT, RENDER_PASS_DEFERRED_OPAQUE,
RENDER_PASS_PARTICLE_OCCLUSION, RENDER_PASS_FORWARD_TRANSPARENT,
RENDER_PASS_ADDITIVE_PARTICLES, RENDER_PASS_PARTICLE_OCCLUSION,
RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE, RENDER_PASS_ADDITIVE_PARTICLES,
RENDER_PASS_GENERATE_SHADOWMAPS, RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE,
RENDER_PASS_SHADOWMAP, RENDER_PASS_GENERATE_SHADOWMAPS,
RENDER_PASS_PRESTREAM RENDER_PASS_SHADOWMAP,
}; RENDER_PASS_PRESTREAM
};
enum LodVisibility {
LOD_VISIBILITY_HIDDEN,
LOD_VISIBILITY_PRESTREAM,
LOD_VISIBILITY_VISIBLE
};
class RenderInfo { enum LodVisibility
public: {
RenderInfo(VkCommandBuffer& cb) LOD_VISIBILITY_HIDDEN,
: commandBuffer(cb) LOD_VISIBILITY_PRESTREAM,
{ LOD_VISIBILITY_VISIBLE
};
} class RenderInfo
{
public:
RenderInfo(VkCommandBuffer& cb)
: commandBuffer(cb)
{
RenderInfo(const RenderInfo&) = delete; }
RenderInfo& operator=(const RenderInfo&) = delete;
VkCommandBuffer& commandBuffer; RenderInfo(const RenderInfo&) = delete;
KRCamera* camera; RenderInfo& operator=(const RenderInfo&) = delete;
KRSurface* surface;
std::vector<KRPointLight*> point_lights;
std::vector<KRDirectionalLight*> directional_lights;
std::vector<KRSpotLight*> spot_lights;
KRViewport viewport;
RenderPass renderPass;
};
static void InitNodeInfo(KrNodeInfo* nodeInfo); VkCommandBuffer& commandBuffer;
KRCamera* camera;
KRNode(KRScene &scene, std::string name); KRSurface* surface;
virtual ~KRNode(); std::vector<KRPointLight*> point_lights;
std::vector<KRDirectionalLight*> directional_lights;
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); std::vector<KRSpotLight*> spot_lights;
KRViewport viewport;
RenderPass renderPass;
};
static void InitNodeInfo(KrNodeInfo* nodeInfo);
KRNode(KRScene& scene, std::string name);
virtual ~KRNode();
virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
static KRNode* LoadXML(KRScene& scene, tinyxml2::XMLElement* e);
virtual void loadXML(tinyxml2::XMLElement* e);
virtual std::string getElementName();
const std::string& getName() const;
void addChild(KRNode* child);
const std::set<KRNode*>& getChildren();
KRNode* getParent();
void setLocalTranslation(const Vector3& v, bool set_original = false);
void setLocalScale(const Vector3& v, bool set_original = false);
void setLocalRotation(const Vector3& v, bool set_original = false);
void setRotationOffset(const Vector3& v, bool set_original = false);
void setScalingOffset(const Vector3& v, bool set_original = false);
void setRotationPivot(const Vector3& v, bool set_original = false);
void setScalingPivot(const Vector3& v, bool set_original = false);
void setPreRotation(const Vector3& v, bool set_original = false);
void setPostRotation(const Vector3& v, bool set_original = false);
const Vector3& getRotationOffset();
const Vector3& getScalingOffset();
const Vector3& getRotationPivot();
const Vector3& getScalingPivot();
const Vector3& getPreRotation();
const Vector3& getPostRotation();
const Vector3& getInitialRotationOffset();
const Vector3& getInitialScalingOffset();
const Vector3& getInitialRotationPivot();
const Vector3& getInitialScalingPivot();
const Vector3& getInitialPreRotation();
const Vector3& getInitialPostRotation();
const Vector3& getLocalTranslation();
const Vector3& getLocalScale();
const Vector3& getLocalRotation();
const Vector3& getInitialLocalTranslation();
const Vector3& getInitialLocalScale();
const Vector3& getInitialLocalRotation();
const Vector3 getWorldTranslation();
const Vector3 getWorldScale();
const Quaternion getWorldRotation();
const Quaternion getBindPoseWorldRotation();
const Quaternion getActivePoseWorldRotation();
const Vector3 localToWorld(const Vector3& local_point);
const Vector3 worldToLocal(const Vector3& world_point);
void setWorldTranslation(const Vector3& v);
void setWorldScale(const Vector3& v);
void setWorldRotation(const Vector3& v);
virtual AABB getBounds();
void invalidateBounds() const;
const Matrix4& getModelMatrix();
const Matrix4& getInverseModelMatrix();
const Matrix4& getBindPoseMatrix();
const Matrix4& getActivePoseMatrix();
const Matrix4& getInverseBindPoseMatrix();
enum node_attribute_type
{
KRENGINE_NODE_ATTRIBUTE_NONE,
KRENGINE_NODE_ATTRIBUTE_TRANSLATE_X,
KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y,
KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z,
KRENGINE_NODE_ATTRIBUTE_SCALE_X,
KRENGINE_NODE_ATTRIBUTE_SCALE_Y,
KRENGINE_NODE_ATTRIBUTE_SCALE_Z,
KRENGINE_NODE_ATTRIBUTE_ROTATE_X,
KRENGINE_NODE_ATTRIBUTE_ROTATE_Y,
KRENGINE_NODE_ATTRIBUTE_ROTATE_Z,
KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X,
KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y,
KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z,
KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X,
KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y,
KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z,
KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X,
KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y,
KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z,
KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X,
KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y,
KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z,
KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X,
KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y,
KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z,
KRENGINE_NODE_SCALE_OFFSET_X,
KRENGINE_NODE_SCALE_OFFSET_Y,
KRENGINE_NODE_SCALE_OFFSET_Z,
KRENGINE_NODE_ATTRIBUTE_COUNT
};
void SetAttribute(node_attribute_type attrib, float v);
KRScene& getScene();
virtual void render(const RenderInfo& ri);
virtual void physicsUpdate(float deltaTime);
virtual bool hasPhysics();
virtual void updateLODVisibility(const KRViewport& viewport);
LodVisibility getLODVisibility();
void setScaleCompensation(bool scale_compensation);
bool getScaleCompensation();
void setAnimationEnabled(node_attribute_type attrib, bool enable);
bool getAnimationEnabled(node_attribute_type attrib) const;
virtual kraken_stream_level getStreamLevel(const KRViewport& viewport);
virtual void setLODVisibility(LodVisibility lod_visibility);
static KRNode *LoadXML(KRScene &scene, tinyxml2::XMLElement *e);
virtual void loadXML(tinyxml2::XMLElement *e);
virtual std::string getElementName();
const std::string &getName() const;
void addChild(KRNode *child);
const std::set<KRNode *> &getChildren();
KRNode *getParent();
void setLocalTranslation(const Vector3 &v, bool set_original = false);
void setLocalScale(const Vector3 &v, bool set_original = false);
void setLocalRotation(const Vector3 &v, bool set_original = false);
void setRotationOffset(const Vector3 &v, bool set_original = false);
void setScalingOffset(const Vector3 &v, bool set_original = false);
void setRotationPivot(const Vector3 &v, bool set_original = false);
void setScalingPivot(const Vector3 &v, bool set_original = false);
void setPreRotation(const Vector3 &v, bool set_original = false);
void setPostRotation(const Vector3 &v, bool set_original = false);
const Vector3 &getRotationOffset();
const Vector3 &getScalingOffset();
const Vector3 &getRotationPivot();
const Vector3 &getScalingPivot();
const Vector3 &getPreRotation();
const Vector3 &getPostRotation();
const Vector3 &getInitialRotationOffset();
const Vector3 &getInitialScalingOffset();
const Vector3 &getInitialRotationPivot();
const Vector3 &getInitialScalingPivot();
const Vector3 &getInitialPreRotation();
const Vector3 &getInitialPostRotation();
const Vector3 &getLocalTranslation();
const Vector3 &getLocalScale();
const Vector3 &getLocalRotation();
const Vector3 &getInitialLocalTranslation();
const Vector3 &getInitialLocalScale();
const Vector3 &getInitialLocalRotation();
const Vector3 getWorldTranslation();
const Vector3 getWorldScale();
const Quaternion getWorldRotation();
const Quaternion getBindPoseWorldRotation();
const Quaternion getActivePoseWorldRotation();
const Vector3 localToWorld(const Vector3 &local_point);
const Vector3 worldToLocal(const Vector3 &world_point);
void setWorldTranslation(const Vector3 &v);
void setWorldScale(const Vector3 &v);
void setWorldRotation(const Vector3 &v);
virtual AABB getBounds();
void invalidateBounds() const;
const Matrix4 &getModelMatrix();
const Matrix4 &getInverseModelMatrix();
const Matrix4 &getBindPoseMatrix();
const Matrix4 &getActivePoseMatrix();
const Matrix4 &getInverseBindPoseMatrix();
enum node_attribute_type {
KRENGINE_NODE_ATTRIBUTE_NONE,
KRENGINE_NODE_ATTRIBUTE_TRANSLATE_X,
KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y,
KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z,
KRENGINE_NODE_ATTRIBUTE_SCALE_X,
KRENGINE_NODE_ATTRIBUTE_SCALE_Y,
KRENGINE_NODE_ATTRIBUTE_SCALE_Z,
KRENGINE_NODE_ATTRIBUTE_ROTATE_X,
KRENGINE_NODE_ATTRIBUTE_ROTATE_Y,
KRENGINE_NODE_ATTRIBUTE_ROTATE_Z,
KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X,
KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y,
KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z,
KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X,
KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y,
KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z,
KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X,
KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y,
KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z,
KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X,
KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y,
KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z,
KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X,
KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y,
KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z,
KRENGINE_NODE_SCALE_OFFSET_X,
KRENGINE_NODE_SCALE_OFFSET_Y,
KRENGINE_NODE_SCALE_OFFSET_Z,
KRENGINE_NODE_ATTRIBUTE_COUNT
};
void SetAttribute(node_attribute_type attrib, float v);
KRScene &getScene();
virtual void render(const RenderInfo& ri);
virtual void physicsUpdate(float deltaTime);
virtual bool hasPhysics();
virtual void updateLODVisibility(const KRViewport &viewport);
LodVisibility getLODVisibility();
void setScaleCompensation(bool scale_compensation);
bool getScaleCompensation();
void setAnimationEnabled(node_attribute_type attrib, bool enable);
bool getAnimationEnabled(node_attribute_type attrib) const;
virtual kraken_stream_level getStreamLevel(const KRViewport &viewport);
virtual void setLODVisibility(LodVisibility lod_visibility);
protected: protected:
Vector3 m_localTranslation; Vector3 m_localTranslation;
Vector3 m_localScale; Vector3 m_localScale;
Vector3 m_localRotation; Vector3 m_localRotation;
Vector3 m_rotationOffset; Vector3 m_rotationOffset;
Vector3 m_scalingOffset; Vector3 m_scalingOffset;
Vector3 m_rotationPivot; Vector3 m_rotationPivot;
Vector3 m_scalingPivot; Vector3 m_scalingPivot;
Vector3 m_preRotation; Vector3 m_preRotation;
Vector3 m_postRotation; Vector3 m_postRotation;
Vector3 m_initialLocalTranslation; Vector3 m_initialLocalTranslation;
Vector3 m_initialLocalScale; Vector3 m_initialLocalScale;
Vector3 m_initialLocalRotation; Vector3 m_initialLocalRotation;
Vector3 m_initialRotationOffset; Vector3 m_initialRotationOffset;
Vector3 m_initialScalingOffset; Vector3 m_initialScalingOffset;
Vector3 m_initialRotationPivot; Vector3 m_initialRotationPivot;
Vector3 m_initialScalingPivot; Vector3 m_initialScalingPivot;
Vector3 m_initialPreRotation; Vector3 m_initialPreRotation;
Vector3 m_initialPostRotation; Vector3 m_initialPostRotation;
LodVisibility m_lod_visible; LodVisibility m_lod_visible;
KRNode *m_parentNode; KRNode* m_parentNode;
std::set<KRNode *> m_childNodes; std::set<KRNode*> m_childNodes;
bool m_animation_mask[KRENGINE_NODE_ATTRIBUTE_COUNT]; bool m_animation_mask[KRENGINE_NODE_ATTRIBUTE_COUNT];
private: private:
long m_lastRenderFrame; long m_lastRenderFrame;
void invalidateModelMatrix(); void invalidateModelMatrix();
void invalidateBindPoseMatrix(); void invalidateBindPoseMatrix();
Matrix4 m_modelMatrix; Matrix4 m_modelMatrix;
Matrix4 m_inverseModelMatrix; Matrix4 m_inverseModelMatrix;
Matrix4 m_bindPoseMatrix; Matrix4 m_bindPoseMatrix;
Matrix4 m_activePoseMatrix; Matrix4 m_activePoseMatrix;
Matrix4 m_inverseBindPoseMatrix; Matrix4 m_inverseBindPoseMatrix;
bool m_modelMatrixValid; bool m_modelMatrixValid;
bool m_inverseModelMatrixValid; bool m_inverseModelMatrixValid;
bool m_bindPoseMatrixValid; bool m_bindPoseMatrixValid;
bool m_activePoseMatrixValid; bool m_activePoseMatrixValid;
bool m_inverseBindPoseMatrixValid; bool m_inverseBindPoseMatrixValid;
mutable AABB m_bounds; mutable AABB m_bounds;
mutable bool m_boundsValid; mutable bool m_boundsValid;
std::string m_name; std::string m_name;
KRScene *m_pScene; KRScene* m_pScene;
std::set<KROctreeNode *> m_octree_nodes; std::set<KROctreeNode*> m_octree_nodes;
bool m_scale_compensation; bool m_scale_compensation;
std::set<KRBehavior *> m_behaviors; std::set<KRBehavior*> m_behaviors;
public: public:
void addBehavior(KRBehavior *behavior); void addBehavior(KRBehavior* behavior);
std::set<KRBehavior *> &getBehaviors(); std::set<KRBehavior*>& getBehaviors();
template <class T> T *getBehavior() template <class T> T* getBehavior()
{ {
for(std::set<KRBehavior *>::iterator itr=m_behaviors.begin(); itr != m_behaviors.end(); itr++) { for (std::set<KRBehavior*>::iterator itr = m_behaviors.begin(); itr != m_behaviors.end(); itr++) {
T *behavior = dynamic_cast<T *>(*itr); T* behavior = dynamic_cast<T*>(*itr);
if(behavior) { if (behavior) {
return behavior; return behavior;
} }
}
return NULL;
} }
void removeFromOctreeNodes(); return NULL;
void addToOctreeNode(KROctreeNode *octree_node); }
void childDeleted(KRNode *child_node); void removeFromOctreeNodes();
void addToOctreeNode(KROctreeNode* octree_node);
template <class T> T *find() void childDeleted(KRNode* child_node);
{
T *match = dynamic_cast<T *>(this); template <class T> T* find()
if(match) { {
return match; T* match = dynamic_cast<T*>(this);
} if (match) {
return match;
for(std::set<KRNode *>::const_iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
match = (*itr)->find<T>();
if(match) {
return match;
}
}
return NULL;
} }
template <class T> T *find(const std::string &name) for (std::set<KRNode*>::const_iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
{ match = (*itr)->find<T>();
T *match = dynamic_cast<T *>(this); if (match) {
if(match) { return match;
if(name.compare(match->getName()) == 0) { }
return match;
}
}
for(std::set<KRNode *>::const_iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
match = (*itr)->find<T>(name);
if(match) {
return match;
}
}
return NULL;
} }
return NULL;
}
template <class T> T* find(const std::string& name)
{
T* match = dynamic_cast<T*>(this);
if (match) {
if (name.compare(match->getName()) == 0) {
return match;
}
}
for (std::set<KRNode*>::const_iterator itr = m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
match = (*itr)->find<T>(name);
if (match) {
return match;
}
}
return NULL;
}
}; };

View File

@@ -36,144 +36,144 @@
KROctree::KROctree() KROctree::KROctree()
{ {
m_pRootNode = NULL; m_pRootNode = NULL;
} }
KROctree::~KROctree() KROctree::~KROctree()
{ {
if(m_pRootNode) { if (m_pRootNode) {
delete m_pRootNode; delete m_pRootNode;
} }
} }
void KROctree::add(KRNode *pNode) void KROctree::add(KRNode* pNode)
{ {
AABB nodeBounds = pNode->getBounds(); AABB nodeBounds = pNode->getBounds();
if(nodeBounds == AABB::Zero()) { if (nodeBounds == AABB::Zero()) {
// This item is not visible, don't add it to the octree or outer scene nodes // This item is not visible, don't add it to the octree or outer scene nodes
} else if(nodeBounds == AABB::Infinite()) { } else if (nodeBounds == AABB::Infinite()) {
// This item is infinitely large; we track it separately // This item is infinitely large; we track it separately
m_outerSceneNodes.insert(pNode); m_outerSceneNodes.insert(pNode);
} else { } else {
if(m_pRootNode == NULL) { if (m_pRootNode == NULL) {
// First item inserted, create a node large enough to fit it // First item inserted, create a node large enough to fit it
m_pRootNode = new KROctreeNode(NULL, nodeBounds); m_pRootNode = new KROctreeNode(NULL, nodeBounds);
m_pRootNode->add(pNode); m_pRootNode->add(pNode);
} else {
// Keep encapsulating the root node until the new root contains the inserted node
bool bInsideRoot = false;
while (!bInsideRoot) {
AABB rootBounds = m_pRootNode->getBounds();
Vector3 rootSize = rootBounds.size();
if (nodeBounds.min.x < rootBounds.min.x || nodeBounds.min.y < rootBounds.min.y || nodeBounds.min.z < rootBounds.min.z) {
m_pRootNode = new KROctreeNode(NULL, AABB::Create(rootBounds.min - rootSize, rootBounds.max), 7, m_pRootNode);
} else if (nodeBounds.max.x > rootBounds.max.x || nodeBounds.max.y > rootBounds.max.y || nodeBounds.max.z > rootBounds.max.z) {
m_pRootNode = new KROctreeNode(NULL, AABB::Create(rootBounds.min, rootBounds.max + rootSize), 0, m_pRootNode);
} else { } else {
// Keep encapsulating the root node until the new root contains the inserted node bInsideRoot = true;
bool bInsideRoot = false;
while(!bInsideRoot) {
AABB rootBounds = m_pRootNode->getBounds();
Vector3 rootSize = rootBounds.size();
if(nodeBounds.min.x < rootBounds.min.x || nodeBounds.min.y < rootBounds.min.y || nodeBounds.min.z < rootBounds.min.z) {
m_pRootNode = new KROctreeNode(NULL, AABB::Create(rootBounds.min - rootSize, rootBounds.max), 7, m_pRootNode);
} else if(nodeBounds.max.x > rootBounds.max.x || nodeBounds.max.y > rootBounds.max.y || nodeBounds.max.z > rootBounds.max.z) {
m_pRootNode = new KROctreeNode(NULL, AABB::Create(rootBounds.min, rootBounds.max + rootSize), 0, m_pRootNode);
} else {
bInsideRoot = true;
}
}
m_pRootNode->add(pNode);
} }
}
m_pRootNode->add(pNode);
} }
}
} }
void KROctree::remove(KRNode *pNode) void KROctree::remove(KRNode* pNode)
{ {
if(!m_outerSceneNodes.erase(pNode)) { if (!m_outerSceneNodes.erase(pNode)) {
if(m_pRootNode) { if (m_pRootNode) {
pNode->removeFromOctreeNodes(); pNode->removeFromOctreeNodes();
}
} }
}
shrink();
shrink();
} }
void KROctree::update(KRNode *pNode) void KROctree::update(KRNode* pNode)
{ {
// TODO: This may be more efficient as an incremental operation rather than removing and re-adding the node // TODO: This may be more efficient as an incremental operation rather than removing and re-adding the node
remove(pNode); remove(pNode);
add(pNode); add(pNode);
shrink(); shrink();
} }
void KROctree::shrink() void KROctree::shrink()
{ {
if(m_pRootNode) { if (m_pRootNode) {
while(m_pRootNode->canShrinkRoot()) { while (m_pRootNode->canShrinkRoot()) {
KROctreeNode *newRoot = m_pRootNode->stripChild(); KROctreeNode* newRoot = m_pRootNode->stripChild();
delete m_pRootNode; delete m_pRootNode;
m_pRootNode = newRoot; m_pRootNode = newRoot;
if(m_pRootNode == NULL) return; if (m_pRootNode == NULL) return;
}
} }
}
} }
KROctreeNode *KROctree::getRootNode() KROctreeNode* KROctree::getRootNode()
{ {
return m_pRootNode; return m_pRootNode;
} }
std::set<KRNode *> &KROctree::getOuterSceneNodes() std::set<KRNode*>& KROctree::getOuterSceneNodes()
{ {
return m_outerSceneNodes; return m_outerSceneNodes;
} }
bool KROctree::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask) bool KROctree::lineCast(const Vector3& v0, const Vector3& v1, HitInfo& hitinfo, unsigned int layer_mask)
{ {
bool hit_found = false; bool hit_found = false;
std::vector<KRCollider *> outer_colliders; std::vector<KRCollider*> outer_colliders;
for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) { for (std::set<KRNode*>::iterator outer_nodes_itr = m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) {
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr); KRCollider* collider = dynamic_cast<KRCollider*>(*outer_nodes_itr);
if(collider) { if (collider) {
outer_colliders.push_back(collider); outer_colliders.push_back(collider);
}
} }
for(std::vector<KRCollider *>::iterator itr=outer_colliders.begin(); itr != outer_colliders.end(); itr++) { }
if((*itr)->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true; for (std::vector<KRCollider*>::iterator itr = outer_colliders.begin(); itr != outer_colliders.end(); itr++) {
} if ((*itr)->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
}
if(m_pRootNode) {
if(m_pRootNode->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true; if (m_pRootNode) {
} if (m_pRootNode->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
return hit_found; }
return hit_found;
} }
bool KROctree::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask) bool KROctree::rayCast(const Vector3& v0, const Vector3& dir, HitInfo& hitinfo, unsigned int layer_mask)
{ {
bool hit_found = false; bool hit_found = false;
for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) { for (std::set<KRNode*>::iterator outer_nodes_itr = m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) {
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr); KRCollider* collider = dynamic_cast<KRCollider*>(*outer_nodes_itr);
if(collider) { if (collider) {
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true; if (collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
}
} }
if(m_pRootNode) { }
if(m_pRootNode->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true; if (m_pRootNode) {
} if (m_pRootNode->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
return hit_found; }
return hit_found;
} }
bool KROctree::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask) bool KROctree::sphereCast(const Vector3& v0, const Vector3& v1, float radius, HitInfo& hitinfo, unsigned int layer_mask)
{ {
bool hit_found = false; bool hit_found = false;
std::vector<KRCollider *> outer_colliders; std::vector<KRCollider*> outer_colliders;
for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) { for (std::set<KRNode*>::iterator outer_nodes_itr = m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) {
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr); KRCollider* collider = dynamic_cast<KRCollider*>(*outer_nodes_itr);
if(collider) { if (collider) {
outer_colliders.push_back(collider); outer_colliders.push_back(collider);
}
} }
for(std::vector<KRCollider *>::iterator itr=outer_colliders.begin(); itr != outer_colliders.end(); itr++) { }
if((*itr)->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true; for (std::vector<KRCollider*>::iterator itr = outer_colliders.begin(); itr != outer_colliders.end(); itr++) {
} if ((*itr)->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
}
if(m_pRootNode) {
if(m_pRootNode->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true; if (m_pRootNode) {
} if (m_pRootNode->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
return hit_found; }
return hit_found;
} }

View File

@@ -36,25 +36,26 @@
class KRNode; class KRNode;
class KROctree { class KROctree
{
public: public:
KROctree(); KROctree();
~KROctree(); ~KROctree();
void add(KRNode *pNode); void add(KRNode* pNode);
void remove(KRNode *pNode); void remove(KRNode* pNode);
void update(KRNode *pNode); void update(KRNode* pNode);
KROctreeNode *getRootNode(); KROctreeNode* getRootNode();
std::set<KRNode *> &getOuterSceneNodes(); std::set<KRNode*>& getOuterSceneNodes();
bool lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask); bool lineCast(const Vector3& v0, const Vector3& v1, HitInfo& hitinfo, unsigned int layer_mask);
bool rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask); bool rayCast(const Vector3& v0, const Vector3& dir, HitInfo& hitinfo, unsigned int layer_mask);
bool sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask); bool sphereCast(const Vector3& v0, const Vector3& v1, float radius, HitInfo& hitinfo, unsigned int layer_mask);
private: private:
KROctreeNode *m_pRootNode; KROctreeNode* m_pRootNode;
std::set<KRNode *> m_outerSceneNodes; std::set<KRNode*> m_outerSceneNodes;
void shrink(); void shrink();
}; };

View File

@@ -33,281 +33,285 @@
#include "KRNode.h" #include "KRNode.h"
#include "KRCollider.h" #include "KRCollider.h"
KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds) : m_bounds(bounds) KROctreeNode::KROctreeNode(KROctreeNode* parent, const AABB& bounds) : m_bounds(bounds)
{ {
m_parent = parent; m_parent = parent;
for(int i=0; i<8; i++) m_children[i] = NULL; for (int i = 0; i < 8; i++) {
m_children[i] = NULL;
m_occlusionQuery = 0; }
m_occlusionTested = false;
m_activeQuery = false; m_occlusionQuery = 0;
m_occlusionTested = false;
m_activeQuery = false;
} }
KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds, int iChild, KROctreeNode *pChild) : m_bounds(bounds) KROctreeNode::KROctreeNode(KROctreeNode* parent, const AABB& bounds, int iChild, KROctreeNode* pChild) : m_bounds(bounds)
{ {
// This constructor is used when expanding the octree and replacing the root node with a new root that encapsulates it // This constructor is used when expanding the octree and replacing the root node with a new root that encapsulates it
m_parent = parent; m_parent = parent;
for(int i=0; i<8; i++) m_children[i] = NULL; for (int i = 0; i < 8; i++) {
m_children[iChild] = pChild; m_children[i] = NULL;
pChild->m_parent = this; }
m_children[iChild] = pChild;
m_occlusionQuery = 0; pChild->m_parent = this;
m_occlusionTested = false;
m_activeQuery = false; m_occlusionQuery = 0;
m_occlusionTested = false;
m_activeQuery = false;
} }
KROctreeNode::~KROctreeNode() KROctreeNode::~KROctreeNode()
{ {
for(int i=0; i<8; i++) { for (int i = 0; i < 8; i++) {
if(m_children[i] != NULL) { if (m_children[i] != NULL) {
delete m_children[i]; delete m_children[i];
}
} }
}
if(m_occlusionTested) { if (m_occlusionTested) {
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery)); GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
} }
} }
void KROctreeNode::beginOcclusionQuery() void KROctreeNode::beginOcclusionQuery()
{ {
if(!m_occlusionTested){ if (!m_occlusionTested) {
GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery)); GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery));
#if TARGET_OS_IPHONE || defined(ANDROID) #if TARGET_OS_IPHONE || defined(ANDROID)
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery)); GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
#else #else
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery)); GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
#endif #endif
m_occlusionTested = true; m_occlusionTested = true;
m_activeQuery = true; m_activeQuery = true;
} }
} }
void KROctreeNode::endOcclusionQuery() void KROctreeNode::endOcclusionQuery()
{ {
if(m_activeQuery) { if (m_activeQuery) {
// Only end a query if we started one // Only end a query if we started one
#if TARGET_OS_IPHONE || defined(ANDROID) #if TARGET_OS_IPHONE || defined(ANDROID)
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT)); GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
#else #else
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED)); GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
#endif #endif
} }
} }
AABB KROctreeNode::getBounds() AABB KROctreeNode::getBounds()
{ {
return m_bounds; return m_bounds;
} }
void KROctreeNode::add(KRNode *pNode) void KROctreeNode::add(KRNode* pNode)
{ {
int iChild = getChildIndex(pNode); int iChild = getChildIndex(pNode);
if(iChild == -1) { if (iChild == -1) {
m_sceneNodes.insert(pNode); m_sceneNodes.insert(pNode);
pNode->addToOctreeNode(this); pNode->addToOctreeNode(this);
} else { } else {
if(m_children[iChild] == NULL) { if (m_children[iChild] == NULL) {
m_children[iChild] = new KROctreeNode(this, getChildBounds(iChild)); m_children[iChild] = new KROctreeNode(this, getChildBounds(iChild));
}
m_children[iChild]->add(pNode);
} }
m_children[iChild]->add(pNode);
}
} }
AABB KROctreeNode::getChildBounds(int iChild) AABB KROctreeNode::getChildBounds(int iChild)
{ {
Vector3 center = m_bounds.center(); Vector3 center = m_bounds.center();
return AABB::Create( return AABB::Create(
Vector3::Create( Vector3::Create(
(iChild & 1) == 0 ? m_bounds.min.x : center.x, (iChild & 1) == 0 ? m_bounds.min.x : center.x,
(iChild & 2) == 0 ? m_bounds.min.y : center.y, (iChild & 2) == 0 ? m_bounds.min.y : center.y,
(iChild & 4) == 0 ? m_bounds.min.z : center.z), (iChild & 4) == 0 ? m_bounds.min.z : center.z),
Vector3::Create( Vector3::Create(
(iChild & 1) == 0 ? center.x : m_bounds.max.x, (iChild & 1) == 0 ? center.x : m_bounds.max.x,
(iChild & 2) == 0 ? center.y : m_bounds.max.y, (iChild & 2) == 0 ? center.y : m_bounds.max.y,
(iChild & 4) == 0 ? center.z : m_bounds.max.z) (iChild & 4) == 0 ? center.z : m_bounds.max.z)
); );
} }
int KROctreeNode::getChildIndex(KRNode *pNode) int KROctreeNode::getChildIndex(KRNode* pNode)
{ {
for(int iChild=0; iChild < 8; iChild++) { for (int iChild = 0; iChild < 8; iChild++) {
if(getChildBounds(iChild).contains(pNode->getBounds())) { if (getChildBounds(iChild).contains(pNode->getBounds())) {
return iChild; return iChild;
}
} }
return -1; }
return -1;
} }
void KROctreeNode::trim() void KROctreeNode::trim()
{ {
for(int iChild = 0; iChild < 8; iChild++) { for (int iChild = 0; iChild < 8; iChild++) {
if(m_children[iChild]) { if (m_children[iChild]) {
if(m_children[iChild]->isEmpty()) { if (m_children[iChild]->isEmpty()) {
delete m_children[iChild]; delete m_children[iChild];
m_children[iChild] = NULL; m_children[iChild] = NULL;
} }
}
} }
}
} }
void KROctreeNode::remove(KRNode *pNode) void KROctreeNode::remove(KRNode* pNode)
{ {
m_sceneNodes.erase(pNode); m_sceneNodes.erase(pNode);
} }
void KROctreeNode::update(KRNode *pNode) void KROctreeNode::update(KRNode* pNode)
{ {
} }
bool KROctreeNode::isEmpty() const bool KROctreeNode::isEmpty() const
{ {
for(int i=0; i<8; i++) { for (int i = 0; i < 8; i++) {
if(m_children[i]) { if (m_children[i]) {
return false; return false;
}
} }
return m_sceneNodes.empty(); }
return m_sceneNodes.empty();
} }
bool KROctreeNode::canShrinkRoot() const bool KROctreeNode::canShrinkRoot() const
{ {
int cChildren = 0; int cChildren = 0;
for(int i=0; i<8; i++) { for (int i = 0; i < 8; i++) {
if(m_children[i]) { if (m_children[i]) {
cChildren++; cChildren++;
}
} }
return cChildren <= 1 && m_sceneNodes.empty(); }
return cChildren <= 1 && m_sceneNodes.empty();
} }
KROctreeNode *KROctreeNode::stripChild() KROctreeNode* KROctreeNode::stripChild()
{ {
// Return the first found child and update its reference to NULL so that the destructor will not free it. This is used for shrinking the octree // Return the first found child and update its reference to NULL so that the destructor will not free it. This is used for shrinking the octree
// NOTE: The caller of this function will be responsible for freeing the child object. It is also possible to return a NULL // NOTE: The caller of this function will be responsible for freeing the child object. It is also possible to return a NULL
for(int i=0; i<8; i++) { for (int i = 0; i < 8; i++) {
if(m_children[i]) { if (m_children[i]) {
KROctreeNode *child = m_children[i]; KROctreeNode* child = m_children[i];
child->m_parent = NULL; child->m_parent = NULL;
m_children[i] = NULL; m_children[i] = NULL;
return child; return child;
}
} }
return NULL; }
return NULL;
} }
KROctreeNode *KROctreeNode::getParent() KROctreeNode* KROctreeNode::getParent()
{ {
return m_parent; return m_parent;
} }
KROctreeNode **KROctreeNode::getChildren() KROctreeNode** KROctreeNode::getChildren()
{ {
return m_children; return m_children;
} }
std::set<KRNode *> &KROctreeNode::getSceneNodes() std::set<KRNode*>& KROctreeNode::getSceneNodes()
{ {
return m_sceneNodes; return m_sceneNodes;
} }
bool KROctreeNode::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask) bool KROctreeNode::lineCast(const Vector3& v0, const Vector3& v1, HitInfo& hitinfo, unsigned int layer_mask)
{ {
bool hit_found = false; bool hit_found = false;
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) { if (hitinfo.didHit() && v1 != hitinfo.getPosition()) {
// Optimization: If we already have a hit, only search for hits that are closer // Optimization: If we already have a hit, only search for hits that are closer
hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask); hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask);
} else { } else {
if(getBounds().intersectsLine(v0, v1)) { if (getBounds().intersectsLine(v0, v1)) {
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) { for (std::set<KRNode*>::iterator nodes_itr = m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr); KRCollider* collider = dynamic_cast<KRCollider*>(*nodes_itr);
if(collider) { if (collider) {
if(collider->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true; if (collider->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
}
}
for(int i=0; i<8; i++) {
if(m_children[i]) {
if(m_children[i]->lineCast(v0, v1, hitinfo, layer_mask)) {
hit_found = true;
}
}
}
} }
}
for (int i = 0; i < 8; i++) {
if (m_children[i]) {
if (m_children[i]->lineCast(v0, v1, hitinfo, layer_mask)) {
hit_found = true;
}
}
}
}
}
return hit_found;
}
bool KROctreeNode::rayCast(const Vector3& v0, const Vector3& dir, HitInfo& hitinfo, unsigned int layer_mask)
{
bool hit_found = false;
if (hitinfo.didHit()) {
// Optimization: If we already have a hit, only search for hits that are closer
hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask); // Note: This is purposefully lineCast as opposed to RayCast
} else {
if (getBounds().intersectsRay(v0, dir)) {
for (std::set<KRNode*>::iterator nodes_itr = m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
KRCollider* collider = dynamic_cast<KRCollider*>(*nodes_itr);
if (collider) {
if (collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
}
}
for (int i = 0; i < 8; i++) {
if (m_children[i]) {
if (m_children[i]->rayCast(v0, dir, hitinfo, layer_mask)) {
hit_found = true;
}
}
}
}
}
return hit_found;
}
bool KROctreeNode::sphereCast(const Vector3& v0, const Vector3& v1, float radius, HitInfo& hitinfo, unsigned int layer_mask)
{
bool hit_found = false;
/*
// FINDME, TODO - Adapt this optimization to work with sphereCasts
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
// Optimization: If we already have a hit, only search for hits that are closer
hit_found = sphereCast(v0, hitinfo.getPosition(), radius, hitinfo, layer_mask);
} else {
*/
AABB swept_bounds = AABB::Create(Vector3::Create(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius), Vector3::Create(KRMAX(v0.x, v1.x) + radius, KRMAX(v0.y, v1.y) + radius, KRMAX(v0.z, v1.z) + radius));
// FINDME, TODO - Investigate AABB - swept sphere intersections or OBB - AABB intersections: "if(getBounds().intersectsSweptSphere(v0, v1, radius)) {"
if (getBounds().intersects(swept_bounds)) {
for (std::set<KRNode*>::iterator nodes_itr = m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
KRCollider* collider = dynamic_cast<KRCollider*>(*nodes_itr);
if (collider) {
if (collider->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
}
} }
return hit_found; for (int i = 0; i < 8; i++) {
} if (m_children[i]) {
if (m_children[i]->sphereCast(v0, v1, radius, hitinfo, layer_mask)) {
bool KROctreeNode::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask) hit_found = true;
{
bool hit_found = false;
if(hitinfo.didHit()) {
// Optimization: If we already have a hit, only search for hits that are closer
hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask); // Note: This is purposefully lineCast as opposed to RayCast
} else {
if(getBounds().intersectsRay(v0, dir)) {
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
if(collider) {
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
}
}
for(int i=0; i<8; i++) {
if(m_children[i]) {
if(m_children[i]->rayCast(v0, dir, hitinfo, layer_mask)) {
hit_found = true;
}
}
}
} }
}
} }
}
// }
return hit_found; return hit_found;
}
bool KROctreeNode::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
{
bool hit_found = false;
/*
// FINDME, TODO - Adapt this optimization to work with sphereCasts
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
// Optimization: If we already have a hit, only search for hits that are closer
hit_found = sphereCast(v0, hitinfo.getPosition(), radius, hitinfo, layer_mask);
} else {
*/
AABB swept_bounds = AABB::Create(Vector3::Create(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius), Vector3::Create(KRMAX(v0.x, v1.x) + radius, KRMAX(v0.y, v1.y) + radius, KRMAX(v0.z, v1.z) + radius));
// FINDME, TODO - Investigate AABB - swept sphere intersections or OBB - AABB intersections: "if(getBounds().intersectsSweptSphere(v0, v1, radius)) {"
if(getBounds().intersects(swept_bounds)) {
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
if(collider) {
if(collider->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
}
}
for(int i=0; i<8; i++) {
if(m_children[i]) {
if(m_children[i]->sphereCast(v0, v1, radius, hitinfo, layer_mask)) {
hit_found = true;
}
}
}
}
// }
return hit_found;
} }

View File

@@ -36,49 +36,50 @@
class KRNode; class KRNode;
class KROctreeNode { class KROctreeNode
{
public: public:
KROctreeNode(KROctreeNode *parent, const AABB &bounds); KROctreeNode(KROctreeNode* parent, const AABB& bounds);
KROctreeNode(KROctreeNode *parent, const AABB &bounds, int iChild, KROctreeNode *pChild); KROctreeNode(KROctreeNode* parent, const AABB& bounds, int iChild, KROctreeNode* pChild);
~KROctreeNode(); ~KROctreeNode();
KROctreeNode **getChildren(); KROctreeNode** getChildren();
std::set<KRNode *> &getSceneNodes(); std::set<KRNode*>& getSceneNodes();
void add(KRNode *pNode); void add(KRNode* pNode);
void remove(KRNode *pNode); void remove(KRNode* pNode);
void update(KRNode *pNode); void update(KRNode* pNode);
AABB getBounds(); AABB getBounds();
KROctreeNode *getParent(); KROctreeNode* getParent();
void setChildNode(int iChild, KROctreeNode *pChild); void setChildNode(int iChild, KROctreeNode* pChild);
int getChildIndex(KRNode *pNode); int getChildIndex(KRNode* pNode);
AABB getChildBounds(int iChild); AABB getChildBounds(int iChild);
void trim(); void trim();
bool isEmpty() const; bool isEmpty() const;
bool canShrinkRoot() const; bool canShrinkRoot() const;
KROctreeNode *stripChild(); KROctreeNode* stripChild();
void beginOcclusionQuery(); void beginOcclusionQuery();
void endOcclusionQuery(); void endOcclusionQuery();
GLuint m_occlusionQuery; GLuint m_occlusionQuery;
bool m_occlusionTested; bool m_occlusionTested;
bool m_activeQuery; bool m_activeQuery;
bool lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask); bool lineCast(const Vector3& v0, const Vector3& v1, HitInfo& hitinfo, unsigned int layer_mask);
bool rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask); bool rayCast(const Vector3& v0, const Vector3& dir, HitInfo& hitinfo, unsigned int layer_mask);
bool sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask); bool sphereCast(const Vector3& v0, const Vector3& v1, float radius, HitInfo& hitinfo, unsigned int layer_mask);
private: private:
AABB m_bounds; AABB m_bounds;
KROctreeNode *m_parent; KROctreeNode* m_parent;
KROctreeNode *m_children[8]; KROctreeNode* m_children[8];
std::set<KRNode *>m_sceneNodes; std::set<KRNode*>m_sceneNodes;
}; };

View File

@@ -30,24 +30,24 @@
// //
#include "KRParticleSystem.h" #include "KRParticleSystem.h"
KRParticleSystem::KRParticleSystem(KRScene &scene, std::string name) : KRNode(scene, name) KRParticleSystem::KRParticleSystem(KRScene& scene, std::string name) : KRNode(scene, name)
{ {
} }
KRParticleSystem::~KRParticleSystem() KRParticleSystem::~KRParticleSystem()
{ {
} }
void KRParticleSystem::loadXML(tinyxml2::XMLElement *e) void KRParticleSystem::loadXML(tinyxml2::XMLElement* e)
{ {
} }
tinyxml2::XMLElement *KRParticleSystem::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement* KRParticleSystem::saveXML(tinyxml2::XMLNode* parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement* e = KRNode::saveXML(parent);
return e; return e;
} }

View File

@@ -33,20 +33,21 @@
#include "KRNode.h" #include "KRNode.h"
class KRParticleSystem : public KRNode { class KRParticleSystem : public KRNode
{
public: public:
virtual ~KRParticleSystem(); virtual ~KRParticleSystem();
virtual std::string getElementName() = 0; virtual std::string getElementName() = 0;
virtual void loadXML(tinyxml2::XMLElement *e); virtual void loadXML(tinyxml2::XMLElement* e);
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
virtual AABB getBounds() = 0; virtual AABB getBounds() = 0;
virtual void render(RenderInfo& ri) = 0; virtual void render(RenderInfo& ri) = 0;
protected: protected:
KRParticleSystem(KRScene &scene, std::string name); KRParticleSystem(KRScene& scene, std::string name);
private: private:
}; };

View File

@@ -35,81 +35,82 @@
#include "KRTexture.h" #include "KRTexture.h"
#include "KRContext.h" #include "KRContext.h"
KRParticleSystemNewtonian::KRParticleSystemNewtonian(KRScene &scene, std::string name) : KRParticleSystem(scene, name) KRParticleSystemNewtonian::KRParticleSystemNewtonian(KRScene& scene, std::string name) : KRParticleSystem(scene, name)
{ {
m_particlesAbsoluteTime = 0.0f; m_particlesAbsoluteTime = 0.0f;
} }
KRParticleSystemNewtonian::~KRParticleSystemNewtonian() KRParticleSystemNewtonian::~KRParticleSystemNewtonian()
{ {
} }
std::string KRParticleSystemNewtonian::getElementName() std::string KRParticleSystemNewtonian::getElementName()
{ {
return "newtonian_particles"; return "newtonian_particles";
} }
void KRParticleSystemNewtonian::loadXML(tinyxml2::XMLElement *e) void KRParticleSystemNewtonian::loadXML(tinyxml2::XMLElement* e)
{ {
KRParticleSystem::loadXML(e); KRParticleSystem::loadXML(e);
} }
tinyxml2::XMLElement *KRParticleSystemNewtonian::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement* KRParticleSystemNewtonian::saveXML(tinyxml2::XMLNode* parent)
{ {
tinyxml2::XMLElement *e = KRParticleSystem::saveXML(parent); tinyxml2::XMLElement* e = KRParticleSystem::saveXML(parent);
return e; return e;
} }
AABB KRParticleSystemNewtonian::getBounds() AABB KRParticleSystemNewtonian::getBounds()
{ {
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix()); return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
} }
void KRParticleSystemNewtonian::physicsUpdate(float deltaTime) void KRParticleSystemNewtonian::physicsUpdate(float deltaTime)
{ {
KRParticleSystem::physicsUpdate(deltaTime); KRParticleSystem::physicsUpdate(deltaTime);
m_particlesAbsoluteTime += deltaTime; m_particlesAbsoluteTime += deltaTime;
} }
bool KRParticleSystemNewtonian::hasPhysics() bool KRParticleSystemNewtonian::hasPhysics()
{ {
return true; return true;
} }
void KRParticleSystemNewtonian::render(RenderInfo& ri) { void KRParticleSystemNewtonian::render(RenderInfo& ri)
{
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(ri);
if(ri.renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
if(ri.viewport.visible(getBounds())) {
KRTexture *pParticleTexture = m_pContext->getTextureManager()->getTexture("flare");
m_pContext->getTextureManager()->selectTexture(0, pParticleTexture, 0.0f, KRTexture::TEXTURE_USAGE_PARTICLE);
int particle_count = 10000;
PipelineInfo info{};
std::string shader_name("dust_particle");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &ri.point_lights;
info.directional_lights = &ri.directional_lights;
info.spot_lights = &ri.spot_lights;
info.renderPass = ri.renderPass;
info.rasterMode = RasterMode::kAdditive;
info.cullMode = CullMode::kCullNone;
info.vertexAttributes = (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA);
info.modelFormat = ModelFormat::KRENGINE_MODEL_FORMAT_TRIANGLES;
KRPipeline *pParticleShader = m_pContext->getPipelineManager()->getPipeline(*ri.surface, info); if (m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
pParticleShader->setUniform(KRPipeline::Uniform::flare_size, 1.0f);
pParticleShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, getModelMatrix(), &ri.point_lights, &ri.directional_lights, &ri.spot_lights, ri.renderPass);
m_pContext->getMeshManager()->bindVBO(ri.commandBuffer, &m_pContext->getMeshManager()->KRENGINE_VBO_DATA_RANDOM_PARTICLES, 1.0f); KRNode::render(ri);
vkCmdDraw(ri.commandBuffer, particle_count * 3, 1, 0, 0); if (ri.renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
} if (ri.viewport.visible(getBounds())) {
KRTexture* pParticleTexture = m_pContext->getTextureManager()->getTexture("flare");
m_pContext->getTextureManager()->selectTexture(0, pParticleTexture, 0.0f, KRTexture::TEXTURE_USAGE_PARTICLE);
int particle_count = 10000;
PipelineInfo info{};
std::string shader_name("dust_particle");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &ri.point_lights;
info.directional_lights = &ri.directional_lights;
info.spot_lights = &ri.spot_lights;
info.renderPass = ri.renderPass;
info.rasterMode = RasterMode::kAdditive;
info.cullMode = CullMode::kCullNone;
info.vertexAttributes = (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA);
info.modelFormat = ModelFormat::KRENGINE_MODEL_FORMAT_TRIANGLES;
KRPipeline* pParticleShader = m_pContext->getPipelineManager()->getPipeline(*ri.surface, info);
pParticleShader->setUniform(KRPipeline::Uniform::flare_size, 1.0f);
pParticleShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, getModelMatrix(), &ri.point_lights, &ri.directional_lights, &ri.spot_lights, ri.renderPass);
m_pContext->getMeshManager()->bindVBO(ri.commandBuffer, &m_pContext->getMeshManager()->KRENGINE_VBO_DATA_RANDOM_PARTICLES, 1.0f);
vkCmdDraw(ri.commandBuffer, particle_count * 3, 1, 0, 0);
} }
}
} }

View File

@@ -33,23 +33,24 @@
#include "KRParticleSystem.h" #include "KRParticleSystem.h"
class KRParticleSystemNewtonian : public KRParticleSystem { class KRParticleSystemNewtonian : public KRParticleSystem
{
public: public:
KRParticleSystemNewtonian(KRScene &scene, std::string name); KRParticleSystemNewtonian(KRScene& scene, std::string name);
virtual ~KRParticleSystemNewtonian(); virtual ~KRParticleSystemNewtonian();
virtual std::string getElementName(); virtual std::string getElementName();
virtual void loadXML(tinyxml2::XMLElement *e); virtual void loadXML(tinyxml2::XMLElement* e);
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); virtual tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
virtual AABB getBounds(); virtual AABB getBounds();
virtual void render(RenderInfo& ri); virtual void render(RenderInfo& ri);
virtual void physicsUpdate(float deltaTime); virtual void physicsUpdate(float deltaTime);
virtual bool hasPhysics(); virtual bool hasPhysics();
private: private:
float m_particlesAbsoluteTime; float m_particlesAbsoluteTime;
}; };

View File

@@ -39,7 +39,7 @@
#include "KRRenderPass.h" #include "KRRenderPass.h"
const char *KRPipeline::KRENGINE_UNIFORM_NAMES[] = { const char* KRPipeline::KRENGINE_UNIFORM_NAMES[] = {
"material_ambient", // Uniform::material_ambient "material_ambient", // Uniform::material_ambient
"material_diffuse", // Uniform::material_diffuse "material_diffuse", // Uniform::material_diffuse
"material_specular", // Uniform::material_specular "material_specular", // Uniform::material_specular
@@ -168,35 +168,27 @@ KRPipeline::KRPipeline(KRContext& context, KRSurface& surface, const PipelineInf
SpvReflectInterfaceVariable& input_var = *reflection->input_variables[i]; SpvReflectInterfaceVariable& input_var = *reflection->input_variables[i];
if (strcmp(input_var.name, "vertex_position") == 0) { if (strcmp(input_var.name, "vertex_position") == 0) {
attribute_locations[KRMesh::KRENGINE_ATTRIB_VERTEX] = input_var.location + 1; attribute_locations[KRMesh::KRENGINE_ATTRIB_VERTEX] = input_var.location + 1;
} } else if (strcmp(input_var.name, "vertex_normal") == 0) {
else if (strcmp(input_var.name, "vertex_normal") == 0) {
attribute_locations[KRMesh::KRENGINE_ATTRIB_NORMAL] = input_var.location + 1; attribute_locations[KRMesh::KRENGINE_ATTRIB_NORMAL] = input_var.location + 1;
} } else if (strcmp(input_var.name, "vertex_tangent") == 0) {
else if (strcmp(input_var.name, "vertex_tangent") == 0) {
attribute_locations[KRMesh::KRENGINE_ATTRIB_TANGENT] = input_var.location + 1; attribute_locations[KRMesh::KRENGINE_ATTRIB_TANGENT] = input_var.location + 1;
} } else if (strcmp(input_var.name, "vertex_uv") == 0) {
else if (strcmp(input_var.name, "vertex_uv") == 0) {
attribute_locations[KRMesh::KRENGINE_ATTRIB_TEXUVA] = input_var.location + 1; attribute_locations[KRMesh::KRENGINE_ATTRIB_TEXUVA] = input_var.location + 1;
} } else if (strcmp(input_var.name, "vertex_lightmap_uv") == 0) {
else if (strcmp(input_var.name, "vertex_lightmap_uv") == 0) {
attribute_locations[KRMesh::KRENGINE_ATTRIB_TEXUVB] = input_var.location + 1; attribute_locations[KRMesh::KRENGINE_ATTRIB_TEXUVB] = input_var.location + 1;
} } else if (strcmp(input_var.name, "bone_indexes") == 0) {
else if (strcmp(input_var.name, "bone_indexes") == 0) {
attribute_locations[KRMesh::KRENGINE_ATTRIB_BONEINDEXES] = input_var.location + 1; attribute_locations[KRMesh::KRENGINE_ATTRIB_BONEINDEXES] = input_var.location + 1;
} } else if (strcmp(input_var.name, "bone_weights") == 0) {
else if (strcmp(input_var.name, "bone_weights") == 0) {
attribute_locations[KRMesh::KRENGINE_ATTRIB_BONEWEIGHTS] = input_var.location + 1; attribute_locations[KRMesh::KRENGINE_ATTRIB_BONEWEIGHTS] = input_var.location + 1;
} }
} }
initPushConstantStage(ShaderStages::vertex, reflection); initPushConstantStage(ShaderStages::vertex, reflection);
} } else if (shader->getSubExtension().compare("frag") == 0) {
else if (shader->getSubExtension().compare("frag") == 0) {
stageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; stageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
initPushConstantStage(ShaderStages::fragment, reflection); initPushConstantStage(ShaderStages::fragment, reflection);
} } else {
else {
// failed! TODO - Error handling // failed! TODO - Error handling
} }
stageInfo.module = shaderModule; stageInfo.module = shaderModule;
@@ -368,11 +360,11 @@ KRPipeline::KRPipeline(KRContext& context, KRSurface& surface, const PipelineInf
switch (static_cast<ShaderStages>(iStage)) { switch (static_cast<ShaderStages>(iStage)) {
case ShaderStages::vertex: case ShaderStages::vertex:
push_constant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; push_constant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
break; break;
case ShaderStages::fragment: case ShaderStages::fragment:
push_constant.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; push_constant.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
break; break;
case ShaderStages::geometry: case ShaderStages::geometry:
push_constant.stageFlags = VK_SHADER_STAGE_GEOMETRY_BIT; push_constant.stageFlags = VK_SHADER_STAGE_GEOMETRY_BIT;
break; break;
@@ -380,7 +372,7 @@ KRPipeline::KRPipeline(KRContext& context, KRSurface& surface, const PipelineInf
push_constant.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; push_constant.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
break; break;
} }
pushConstantsLayoutInfo.pPushConstantRanges = &push_constant; pushConstantsLayoutInfo.pPushConstantRanges = &push_constant;
pushConstantsLayoutInfo.pushConstantRangeCount = 1; pushConstantsLayoutInfo.pushConstantRangeCount = 1;
@@ -421,7 +413,7 @@ KRPipeline::KRPipeline(KRContext& context, KRSurface& surface, const PipelineInf
} else { } else {
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; depthStencil.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
} }
depthStencil.depthBoundsTestEnable = VK_FALSE; depthStencil.depthBoundsTestEnable = VK_FALSE;
depthStencil.minDepthBounds = 0.0f; depthStencil.minDepthBounds = 0.0f;
depthStencil.maxDepthBounds = 1.0f; depthStencil.maxDepthBounds = 1.0f;
@@ -454,7 +446,8 @@ KRPipeline::KRPipeline(KRContext& context, KRSurface& surface, const PipelineInf
} }
} }
KRPipeline::~KRPipeline() { KRPipeline::~KRPipeline()
{
if (m_graphicsPipeline) { if (m_graphicsPipeline) {
// TODO: vkDestroyPipeline(device, m_graphicsPipeline, nullptr); // TODO: vkDestroyPipeline(device, m_graphicsPipeline, nullptr);
} }
@@ -468,8 +461,8 @@ KRPipeline::~KRPipeline() {
} }
if(getContext().getPipelineManager()->m_active_pipeline == this) { if (getContext().getPipelineManager()->m_active_pipeline == this) {
getContext().getPipelineManager()->m_active_pipeline = NULL; getContext().getPipelineManager()->m_active_pipeline = NULL;
} }
if (m_pushConstants[0].buffer) { if (m_pushConstants[0].buffer) {
delete m_pushConstants[0].buffer; delete m_pushConstants[0].buffer;
@@ -492,8 +485,7 @@ void KRPipeline::initPushConstantStage(ShaderStages stage, const SpvReflectShade
for (int iUniform = 0; iUniform < kUniformCount; iUniform++) { for (int iUniform = 0; iUniform < kUniformCount; iUniform++) {
for (int iMember = 0; iMember < block.member_count; iMember++) { for (int iMember = 0; iMember < block.member_count; iMember++) {
const SpvReflectBlockVariable& member = block.members[iMember]; const SpvReflectBlockVariable& member = block.members[iMember];
if (stricmp(KRENGINE_UNIFORM_NAMES[iUniform], member.name) == 0) if (stricmp(KRENGINE_UNIFORM_NAMES[iUniform], member.name) == 0) {
{
pushConstants.offset[iUniform] = member.offset; pushConstants.offset[iUniform] = member.offset;
pushConstants.size[iUniform] = member.size; pushConstants.size[iUniform] = member.size;
} }
@@ -535,7 +527,7 @@ void KRPipeline::setUniform(Uniform location, int value)
} }
} }
void KRPipeline::setUniform(Uniform location, const Vector2 &value) void KRPipeline::setUniform(Uniform location, const Vector2& value)
{ {
for (PushConstantStageInfo& stageConstants : m_pushConstants) { for (PushConstantStageInfo& stageConstants : m_pushConstants) {
if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) { if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) {
@@ -544,7 +536,7 @@ void KRPipeline::setUniform(Uniform location, const Vector2 &value)
} }
} }
} }
void KRPipeline::setUniform(Uniform location, const Vector3 &value) void KRPipeline::setUniform(Uniform location, const Vector3& value)
{ {
for (PushConstantStageInfo& stageConstants : m_pushConstants) { for (PushConstantStageInfo& stageConstants : m_pushConstants) {
if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) { if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) {
@@ -554,7 +546,7 @@ void KRPipeline::setUniform(Uniform location, const Vector3 &value)
} }
} }
void KRPipeline::setUniform(Uniform location, const Vector4 &value) void KRPipeline::setUniform(Uniform location, const Vector4& value)
{ {
for (PushConstantStageInfo& stageConstants : m_pushConstants) { for (PushConstantStageInfo& stageConstants : m_pushConstants) {
if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) { if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) {
@@ -564,7 +556,7 @@ void KRPipeline::setUniform(Uniform location, const Vector4 &value)
} }
} }
void KRPipeline::setUniform(Uniform location, const Matrix4 &value) void KRPipeline::setUniform(Uniform location, const Matrix4& value)
{ {
for (PushConstantStageInfo& stageConstants : m_pushConstants) { for (PushConstantStageInfo& stageConstants : m_pushConstants) {
if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) { if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) {
@@ -582,211 +574,212 @@ void KRPipeline::setUniform(Uniform location, const Matrix4* value, const size_t
} }
} }
bool KRPipeline::bind(VkCommandBuffer& commandBuffer, KRCamera &camera, const KRViewport &viewport, const Matrix4 &matModel, const std::vector<KRPointLight *> *point_lights, const std::vector<KRDirectionalLight *> *directional_lights, const std::vector<KRSpotLight *> *spot_lights, const KRNode::RenderPass &renderPass) bool KRPipeline::bind(VkCommandBuffer& commandBuffer, KRCamera& camera, const KRViewport& viewport, const Matrix4& matModel, const std::vector<KRPointLight*>* point_lights, const std::vector<KRDirectionalLight*>* directional_lights, const std::vector<KRSpotLight*>* spot_lights, const KRNode::RenderPass& renderPass)
{ {
setUniform(Uniform::absolute_time, getContext().getAbsoluteTime()); setUniform(Uniform::absolute_time, getContext().getAbsoluteTime());
int light_directional_count = 0;
//int light_point_count = 0;
//int light_spot_count = 0;
// TODO - Need to support multiple lights and more light types in forward rendering
if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && renderPass != KRNode::RENDER_PASS_DEFERRED_GBUFFER && renderPass != KRNode::RENDER_PASS_DEFERRED_OPAQUE && renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS) {
if (directional_lights) {
for (std::vector<KRDirectionalLight*>::const_iterator light_itr = directional_lights->begin(); light_itr != directional_lights->end(); light_itr++) {
KRDirectionalLight* directional_light = (*light_itr);
if (light_directional_count == 0) {
int cShadowBuffers = directional_light->getShadowBufferCount();
if (hasUniform(Uniform::shadowtexture1) && cShadowBuffers > 0) {
if (m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 3, directional_light->getShadowTextures()[0])) {
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
}
m_pContext->getTextureManager()->_setWrapModeS(3, GL_CLAMP_TO_EDGE); int light_directional_count = 0;
m_pContext->getTextureManager()->_setWrapModeT(3, GL_CLAMP_TO_EDGE); //int light_point_count = 0;
//int light_spot_count = 0;
// TODO - Need to support multiple lights and more light types in forward rendering
if (renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && renderPass != KRNode::RENDER_PASS_DEFERRED_GBUFFER && renderPass != KRNode::RENDER_PASS_DEFERRED_OPAQUE && renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS) {
if (directional_lights) {
for (std::vector<KRDirectionalLight*>::const_iterator light_itr = directional_lights->begin(); light_itr != directional_lights->end(); light_itr++) {
KRDirectionalLight* directional_light = (*light_itr);
if (light_directional_count == 0) {
int cShadowBuffers = directional_light->getShadowBufferCount();
if (hasUniform(Uniform::shadowtexture1) && cShadowBuffers > 0) {
if (m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 3, directional_light->getShadowTextures()[0])) {
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
} }
if (hasUniform(Uniform::shadowtexture2) && cShadowBuffers > 1 && camera.settings.m_cShadowBuffers > 1) { m_pContext->getTextureManager()->_setWrapModeS(3, GL_CLAMP_TO_EDGE);
if (m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 4, directional_light->getShadowTextures()[1])) { m_pContext->getTextureManager()->_setWrapModeT(3, GL_CLAMP_TO_EDGE);
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
}
m_pContext->getTextureManager()->_setWrapModeS(4, GL_CLAMP_TO_EDGE);
m_pContext->getTextureManager()->_setWrapModeT(4, GL_CLAMP_TO_EDGE);
}
if (hasUniform(Uniform::shadowtexture3) && cShadowBuffers > 2 && camera.settings.m_cShadowBuffers > 2) {
if (m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 5, directional_light->getShadowTextures()[2])) {
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
}
m_pContext->getTextureManager()->_setWrapModeS(5, GL_CLAMP_TO_EDGE);
m_pContext->getTextureManager()->_setWrapModeT(5, GL_CLAMP_TO_EDGE);
}
Matrix4 matBias;
matBias.translate(1.0, 1.0, 1.0);
matBias.scale(0.5);
for (int iShadow = 0; iShadow < cShadowBuffers; iShadow++) {
setUniform(static_cast<Uniform>(static_cast<int>(Uniform::shadow_mvp1) + iShadow), matModel * directional_light->getShadowViewports()[iShadow].getViewProjectionMatrix() * matBias);
}
if (hasUniform(Uniform::light_direction_model_space)) {
Matrix4 inverseModelMatrix = matModel;
inverseModelMatrix.invert();
// Bind the light direction vector
Vector3 lightDirObject = Matrix4::Dot(inverseModelMatrix, directional_light->getWorldLightDirection());
lightDirObject.normalize();
setUniform(Uniform::light_direction_model_space, lightDirObject);
}
} }
light_directional_count++; if (hasUniform(Uniform::shadowtexture2) && cShadowBuffers > 1 && camera.settings.m_cShadowBuffers > 1) {
} if (m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 4, directional_light->getShadowTextures()[1])) {
} GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
}
m_pContext->getTextureManager()->_setWrapModeS(4, GL_CLAMP_TO_EDGE);
m_pContext->getTextureManager()->_setWrapModeT(4, GL_CLAMP_TO_EDGE);
}
//light_point_count = point_lights.size(); if (hasUniform(Uniform::shadowtexture3) && cShadowBuffers > 2 && camera.settings.m_cShadowBuffers > 2) {
//light_spot_count = spot_lights.size(); if (m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 5, directional_light->getShadowTextures()[2])) {
} GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
}
m_pContext->getTextureManager()->_setWrapModeS(5, GL_CLAMP_TO_EDGE);
m_pContext->getTextureManager()->_setWrapModeT(5, GL_CLAMP_TO_EDGE);
}
if(hasUniform(Uniform::camerapos_model_space)) { Matrix4 matBias;
Matrix4 inverseModelMatrix = matModel; matBias.translate(1.0, 1.0, 1.0);
inverseModelMatrix.invert(); matBias.scale(0.5);
for (int iShadow = 0; iShadow < cShadowBuffers; iShadow++) {
if(hasUniform(Uniform::camerapos_model_space)) { setUniform(static_cast<Uniform>(static_cast<int>(Uniform::shadow_mvp1) + iShadow), matModel * directional_light->getShadowViewports()[iShadow].getViewProjectionMatrix() * matBias);
// Transform location of camera to object space for calculation of specular halfVec }
Vector3 cameraPosObject = Matrix4::Dot(inverseModelMatrix, viewport.getCameraPosition());
setUniform(Uniform::camerapos_model_space, cameraPosObject);
}
}
if(hasUniform(Uniform::mvp) || hasUniform(KRPipeline::Uniform::invmvp)) {
// Bind our modelmatrix variable to be a uniform called mvpmatrix in our shaderprogram
Matrix4 mvpMatrix = matModel * viewport.getViewProjectionMatrix();
setUniform(Uniform::mvp, mvpMatrix);
if(hasUniform(KRPipeline::Uniform::invmvp)) {
setUniform(KRPipeline::Uniform::invmvp, Matrix4::Invert(mvpMatrix));
}
}
if(hasUniform(KRPipeline::Uniform::view_space_model_origin) || hasUniform(Uniform::model_view_inverse_transpose) || hasUniform(KRPipeline::Uniform::model_view)) {
Matrix4 matModelView = matModel * viewport.getViewMatrix();
setUniform(Uniform::model_view, matModelView);
if(hasUniform(KRPipeline::Uniform::view_space_model_origin)) {
Vector3 view_space_model_origin = Matrix4::Dot(matModelView, Vector3::Zero()); // Origin point of model space is the light source position. No perspective, so no w divide required
setUniform(Uniform::view_space_model_origin, view_space_model_origin);
}
if(hasUniform(Uniform::model_view_inverse_transpose)) {
Matrix4 matModelViewInverseTranspose = matModelView;
matModelViewInverseTranspose.transpose();
matModelViewInverseTranspose.invert();
setUniform(Uniform::model_view_inverse_transpose, matModelViewInverseTranspose);
}
}
if(hasUniform(Uniform::model_inverse_transpose)) {
Matrix4 matModelInverseTranspose = matModel;
matModelInverseTranspose.transpose();
matModelInverseTranspose.invert();
setUniform(Uniform::model_inverse_transpose, matModelInverseTranspose);
}
if(hasUniform(KRPipeline::Uniform::invp)) {
setUniform(Uniform::invp, viewport.getInverseProjectionMatrix());
}
if(hasUniform(KRPipeline::Uniform::invmvp_no_translate)) {
Matrix4 matInvMVPNoTranslate = matModel * viewport.getViewMatrix();;
// Remove the translation
matInvMVPNoTranslate.getPointer()[3] = 0;
matInvMVPNoTranslate.getPointer()[7] = 0;
matInvMVPNoTranslate.getPointer()[11] = 0;
matInvMVPNoTranslate.getPointer()[12] = 0;
matInvMVPNoTranslate.getPointer()[13] = 0;
matInvMVPNoTranslate.getPointer()[14] = 0;
matInvMVPNoTranslate.getPointer()[15] = 1.0;
matInvMVPNoTranslate = matInvMVPNoTranslate * viewport.getProjectionMatrix();
matInvMVPNoTranslate.invert();
setUniform(Uniform::invmvp_no_translate, matInvMVPNoTranslate);
}
setUniform(Uniform::model_matrix, matModel);
if(hasUniform(Uniform::projection_matrix)) {
setUniform(Uniform::projection_matrix, viewport.getProjectionMatrix());
}
if(hasUniform(Uniform::viewport)) {
setUniform(Uniform::viewport, Vector4::Create(
(float)0.0,
(float)0.0,
(float)viewport.getSize().x,
(float)viewport.getSize().y
)
);
}
if(hasUniform(Uniform::viewport_downsample)) {
setUniform(Uniform::viewport_downsample, camera.getDownsample());
}
// Fog parameters
setUniform(Uniform::fog_near, camera.settings.fog_near);
setUniform(Uniform::fog_far, camera.settings.fog_far);
setUniform(Uniform::fog_density, camera.settings.fog_density);
setUniform(Uniform::fog_color, camera.settings.fog_color);
if(hasUniform(Uniform::fog_scale)) {
setUniform(Uniform::fog_scale, 1.0f / (camera.settings.fog_far - camera.settings.fog_near));
}
if(hasUniform(Uniform::density_premultiplied_exponential)) {
setUniform(Uniform::density_premultiplied_exponential, -camera.settings.fog_density * 1.442695f); // -fog_density / log(2)
}
if(hasUniform(Uniform::density_premultiplied_squared)) {
setUniform(Uniform::density_premultiplied_squared, (float)(-camera.settings.fog_density * camera.settings.fog_density * 1.442695)); // -fog_density * fog_density / log(2)
}
// Sets the diffuseTexture variable to the first texture unit
setUniform(Uniform::diffusetexture, 0);
// Sets the specularTexture variable to the second texture unit
setUniform(Uniform::speculartexture, 1);
// Sets the normalTexture variable to the third texture unit
setUniform(Uniform::normaltexture, 2);
// Sets the shadowTexture variable to the fourth texture unit
setUniform(Uniform::shadowtexture1, 3);
setUniform(Uniform::shadowtexture2, 4);
setUniform(Uniform::shadowtexture3, 5);
setUniform(Uniform::reflectioncubetexture, 4);
setUniform(Uniform::lightmaptexture, 5);
setUniform(Uniform::gbuffer_frame, 6);
setUniform(Uniform::gbuffer_depth, 7); // Texture unit 7 is used for reading the depth buffer in gBuffer pass #2 and in post-processing pass
setUniform(Uniform::reflectiontexture, 7); // Texture unit 7 is used for the reflection map textures in gBuffer pass #3 and when using forward rendering
setUniform(Uniform::depth_frame, 0);
setUniform(Uniform::render_frame, 1);
setUniform(Uniform::volumetric_environment_frame, 2);
for (PushConstantStageInfo& pushConstants : m_pushConstants) { if (hasUniform(Uniform::light_direction_model_space)) {
if (pushConstants.buffer) { Matrix4 inverseModelMatrix = matModel;
vkCmdPushConstants(commandBuffer, pushConstants.layout, VK_SHADER_STAGE_VERTEX_BIT, 0, pushConstants.bufferSize, pushConstants.buffer); inverseModelMatrix.invert();
// Bind the light direction vector
Vector3 lightDirObject = Matrix4::Dot(inverseModelMatrix, directional_light->getWorldLightDirection());
lightDirObject.normalize();
setUniform(Uniform::light_direction_model_space, lightDirObject);
}
}
light_directional_count++;
} }
} }
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline); //light_point_count = point_lights.size();
//light_spot_count = spot_lights.size();
}
return true; if (hasUniform(Uniform::camerapos_model_space)) {
Matrix4 inverseModelMatrix = matModel;
inverseModelMatrix.invert();
if (hasUniform(Uniform::camerapos_model_space)) {
// Transform location of camera to object space for calculation of specular halfVec
Vector3 cameraPosObject = Matrix4::Dot(inverseModelMatrix, viewport.getCameraPosition());
setUniform(Uniform::camerapos_model_space, cameraPosObject);
}
}
if (hasUniform(Uniform::mvp) || hasUniform(KRPipeline::Uniform::invmvp)) {
// Bind our modelmatrix variable to be a uniform called mvpmatrix in our shaderprogram
Matrix4 mvpMatrix = matModel * viewport.getViewProjectionMatrix();
setUniform(Uniform::mvp, mvpMatrix);
if (hasUniform(KRPipeline::Uniform::invmvp)) {
setUniform(KRPipeline::Uniform::invmvp, Matrix4::Invert(mvpMatrix));
}
}
if (hasUniform(KRPipeline::Uniform::view_space_model_origin) || hasUniform(Uniform::model_view_inverse_transpose) || hasUniform(KRPipeline::Uniform::model_view)) {
Matrix4 matModelView = matModel * viewport.getViewMatrix();
setUniform(Uniform::model_view, matModelView);
if (hasUniform(KRPipeline::Uniform::view_space_model_origin)) {
Vector3 view_space_model_origin = Matrix4::Dot(matModelView, Vector3::Zero()); // Origin point of model space is the light source position. No perspective, so no w divide required
setUniform(Uniform::view_space_model_origin, view_space_model_origin);
}
if (hasUniform(Uniform::model_view_inverse_transpose)) {
Matrix4 matModelViewInverseTranspose = matModelView;
matModelViewInverseTranspose.transpose();
matModelViewInverseTranspose.invert();
setUniform(Uniform::model_view_inverse_transpose, matModelViewInverseTranspose);
}
}
if (hasUniform(Uniform::model_inverse_transpose)) {
Matrix4 matModelInverseTranspose = matModel;
matModelInverseTranspose.transpose();
matModelInverseTranspose.invert();
setUniform(Uniform::model_inverse_transpose, matModelInverseTranspose);
}
if (hasUniform(KRPipeline::Uniform::invp)) {
setUniform(Uniform::invp, viewport.getInverseProjectionMatrix());
}
if (hasUniform(KRPipeline::Uniform::invmvp_no_translate)) {
Matrix4 matInvMVPNoTranslate = matModel * viewport.getViewMatrix();;
// Remove the translation
matInvMVPNoTranslate.getPointer()[3] = 0;
matInvMVPNoTranslate.getPointer()[7] = 0;
matInvMVPNoTranslate.getPointer()[11] = 0;
matInvMVPNoTranslate.getPointer()[12] = 0;
matInvMVPNoTranslate.getPointer()[13] = 0;
matInvMVPNoTranslate.getPointer()[14] = 0;
matInvMVPNoTranslate.getPointer()[15] = 1.0;
matInvMVPNoTranslate = matInvMVPNoTranslate * viewport.getProjectionMatrix();
matInvMVPNoTranslate.invert();
setUniform(Uniform::invmvp_no_translate, matInvMVPNoTranslate);
}
setUniform(Uniform::model_matrix, matModel);
if (hasUniform(Uniform::projection_matrix)) {
setUniform(Uniform::projection_matrix, viewport.getProjectionMatrix());
}
if (hasUniform(Uniform::viewport)) {
setUniform(Uniform::viewport, Vector4::Create(
(float)0.0,
(float)0.0,
(float)viewport.getSize().x,
(float)viewport.getSize().y
)
);
}
if (hasUniform(Uniform::viewport_downsample)) {
setUniform(Uniform::viewport_downsample, camera.getDownsample());
}
// Fog parameters
setUniform(Uniform::fog_near, camera.settings.fog_near);
setUniform(Uniform::fog_far, camera.settings.fog_far);
setUniform(Uniform::fog_density, camera.settings.fog_density);
setUniform(Uniform::fog_color, camera.settings.fog_color);
if (hasUniform(Uniform::fog_scale)) {
setUniform(Uniform::fog_scale, 1.0f / (camera.settings.fog_far - camera.settings.fog_near));
}
if (hasUniform(Uniform::density_premultiplied_exponential)) {
setUniform(Uniform::density_premultiplied_exponential, -camera.settings.fog_density * 1.442695f); // -fog_density / log(2)
}
if (hasUniform(Uniform::density_premultiplied_squared)) {
setUniform(Uniform::density_premultiplied_squared, (float)(-camera.settings.fog_density * camera.settings.fog_density * 1.442695)); // -fog_density * fog_density / log(2)
}
// Sets the diffuseTexture variable to the first texture unit
setUniform(Uniform::diffusetexture, 0);
// Sets the specularTexture variable to the second texture unit
setUniform(Uniform::speculartexture, 1);
// Sets the normalTexture variable to the third texture unit
setUniform(Uniform::normaltexture, 2);
// Sets the shadowTexture variable to the fourth texture unit
setUniform(Uniform::shadowtexture1, 3);
setUniform(Uniform::shadowtexture2, 4);
setUniform(Uniform::shadowtexture3, 5);
setUniform(Uniform::reflectioncubetexture, 4);
setUniform(Uniform::lightmaptexture, 5);
setUniform(Uniform::gbuffer_frame, 6);
setUniform(Uniform::gbuffer_depth, 7); // Texture unit 7 is used for reading the depth buffer in gBuffer pass #2 and in post-processing pass
setUniform(Uniform::reflectiontexture, 7); // Texture unit 7 is used for the reflection map textures in gBuffer pass #3 and when using forward rendering
setUniform(Uniform::depth_frame, 0);
setUniform(Uniform::render_frame, 1);
setUniform(Uniform::volumetric_environment_frame, 2);
for (PushConstantStageInfo& pushConstants : m_pushConstants) {
if (pushConstants.buffer) {
vkCmdPushConstants(commandBuffer, pushConstants.layout, VK_SHADER_STAGE_VERTEX_BIT, 0, pushConstants.bufferSize, pushConstants.buffer);
}
}
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline);
return true;
} }
const char *KRPipeline::getKey() const { const char* KRPipeline::getKey() const
return m_szKey; {
return m_szKey;
} }
VkPipeline& KRPipeline::getPipeline() VkPipeline& KRPipeline::getPipeline()

View File

@@ -45,14 +45,16 @@ class KRRenderPass;
enum class ModelFormat : __uint8_t; enum class ModelFormat : __uint8_t;
struct SpvReflectShaderModule; struct SpvReflectShaderModule;
enum class CullMode : uint32_t { enum class CullMode : uint32_t
{
kCullBack = 0, kCullBack = 0,
kCullFront, kCullFront,
kCullNone kCullNone
}; };
// Note: RasterMode is likely to be refactored later to a bitfield // Note: RasterMode is likely to be refactored later to a bitfield
enum class RasterMode : uint32_t { enum class RasterMode : uint32_t
{
kOpaque = 0, kOpaque = 0,
/* /*
kOpaque is equivalent to: kOpaque is equivalent to:
@@ -173,7 +175,8 @@ enum class RasterMode : uint32_t {
*/ */
}; };
class PipelineInfo { class PipelineInfo
{
public: public:
const std::string* shader_name; const std::string* shader_name;
KRCamera* pCamera; KRCamera* pCamera;
@@ -204,128 +207,130 @@ public:
KRNode::RenderPass renderPass; KRNode::RenderPass renderPass;
}; };
class KRPipeline : public KRContextObject { class KRPipeline : public KRContextObject
{
public: public:
KRPipeline(KRContext& context, KRSurface& surface, const PipelineInfo& info, const char* szKey, const std::vector<KRShader*>& shaders, uint32_t vertexAttributes, ModelFormat modelFormat); KRPipeline(KRContext& context, KRSurface& surface, const PipelineInfo& info, const char* szKey, const std::vector<KRShader*>& shaders, uint32_t vertexAttributes, ModelFormat modelFormat);
virtual ~KRPipeline(); virtual ~KRPipeline();
const char *getKey() const; const char* getKey() const;
bool bind(VkCommandBuffer& commandBuffer, KRCamera &camera, const KRViewport &viewport, const Matrix4 &matModel, const std::vector<KRPointLight *> *point_lights, const std::vector<KRDirectionalLight *> *directional_lights, const std::vector<KRSpotLight *>*spot_lights, const KRNode::RenderPass &renderPass);
enum class Uniform : uint8_t { bool bind(VkCommandBuffer& commandBuffer, KRCamera& camera, const KRViewport& viewport, const Matrix4& matModel, const std::vector<KRPointLight*>* point_lights, const std::vector<KRDirectionalLight*>* directional_lights, const std::vector<KRSpotLight*>* spot_lights, const KRNode::RenderPass& renderPass);
material_ambient = 0,
material_diffuse,
material_specular,
material_reflection,
material_alpha,
material_shininess,
light_position,
light_direction_model_space,
light_direction_view_space,
light_color,
light_decay_start,
light_cutoff,
light_intensity,
flare_size,
view_space_model_origin,
mvp,
invp,
invmvp,
invmvp_no_translate,
model_view_inverse_transpose,
model_inverse_transpose,
model_view,
model_matrix,
projection_matrix,
camerapos_model_space,
viewport,
viewport_downsample,
diffusetexture,
speculartexture,
reflectioncubetexture,
reflectiontexture,
normaltexture,
diffusetexture_scale,
speculartexture_scale,
reflectiontexture_scale,
normaltexture_scale,
ambienttexture_scale,
diffusetexture_offset,
speculartexture_offset,
reflectiontexture_offset,
normaltexture_offset,
ambienttexture_offset,
shadow_mvp1,
shadow_mvp2,
shadow_mvp3,
shadowtexture1,
shadowtexture2,
shadowtexture3,
lightmaptexture,
gbuffer_frame,
gbuffer_depth,
depth_frame,
volumetric_environment_frame,
render_frame,
absolute_time,
fog_near,
fog_far,
fog_density,
fog_color,
fog_scale,
density_premultiplied_exponential,
density_premultiplied_squared,
slice_depth_scale,
particle_origin,
bone_transforms,
rim_color,
rim_power,
fade_color,
NUM_UNIFORMS
};
static const size_t kUniformCount = static_cast<size_t>(Uniform::NUM_UNIFORMS); enum class Uniform : uint8_t
{
material_ambient = 0,
material_diffuse,
material_specular,
material_reflection,
material_alpha,
material_shininess,
light_position,
light_direction_model_space,
light_direction_view_space,
light_color,
light_decay_start,
light_cutoff,
light_intensity,
flare_size,
view_space_model_origin,
mvp,
invp,
invmvp,
invmvp_no_translate,
model_view_inverse_transpose,
model_inverse_transpose,
model_view,
model_matrix,
projection_matrix,
camerapos_model_space,
viewport,
viewport_downsample,
diffusetexture,
speculartexture,
reflectioncubetexture,
reflectiontexture,
normaltexture,
diffusetexture_scale,
speculartexture_scale,
reflectiontexture_scale,
normaltexture_scale,
ambienttexture_scale,
diffusetexture_offset,
speculartexture_offset,
reflectiontexture_offset,
normaltexture_offset,
ambienttexture_offset,
shadow_mvp1,
shadow_mvp2,
shadow_mvp3,
shadowtexture1,
shadowtexture2,
shadowtexture3,
lightmaptexture,
gbuffer_frame,
gbuffer_depth,
depth_frame,
volumetric_environment_frame,
render_frame,
absolute_time,
fog_near,
fog_far,
fog_density,
fog_color,
fog_scale,
density_premultiplied_exponential,
density_premultiplied_squared,
slice_depth_scale,
particle_origin,
bone_transforms,
rim_color,
rim_power,
fade_color,
NUM_UNIFORMS
};
enum class ShaderStages : uint8_t static const size_t kUniformCount = static_cast<size_t>(Uniform::NUM_UNIFORMS);
{
vertex = 0,
fragment,
geometry,
compute,
shaderStageCount
};
static const size_t kShaderStageCount = static_cast<size_t>(ShaderStages::shaderStageCount); enum class ShaderStages : uint8_t
{
bool hasUniform(Uniform location) const; vertex = 0,
void setUniform(Uniform location, float value); fragment,
void setUniform(Uniform location, int value); geometry,
void setUniform(Uniform location, const Vector2 &value); compute,
void setUniform(Uniform location, const Vector3 &value); shaderStageCount
void setUniform(Uniform location, const Vector4 &value); };
void setUniform(Uniform location, const Matrix4 &value);
void setUniform(Uniform location, const Matrix4* value, const size_t count); static const size_t kShaderStageCount = static_cast<size_t>(ShaderStages::shaderStageCount);
bool hasUniform(Uniform location) const;
void setUniform(Uniform location, float value);
void setUniform(Uniform location, int value);
void setUniform(Uniform location, const Vector2& value);
void setUniform(Uniform location, const Vector3& value);
void setUniform(Uniform location, const Vector4& value);
void setUniform(Uniform location, const Matrix4& value);
void setUniform(Uniform location, const Matrix4* value, const size_t count);
VkPipeline& getPipeline();
VkPipeline& getPipeline();
private: private:
static const char* KRENGINE_UNIFORM_NAMES[]; static const char* KRENGINE_UNIFORM_NAMES[];
struct PushConstantStageInfo struct PushConstantStageInfo
{ {
int offset[kUniformCount]; int offset[kUniformCount];
__uint8_t size[kUniformCount]; __uint8_t size[kUniformCount];
uint8_t* buffer; uint8_t* buffer;
int bufferSize; int bufferSize;
VkPipelineLayout layout; VkPipelineLayout layout;
}; };
PushConstantStageInfo m_pushConstants[static_cast<size_t>(ShaderStages::shaderStageCount)]; PushConstantStageInfo m_pushConstants[static_cast<size_t>(ShaderStages::shaderStageCount)];
char m_szKey[256]; char m_szKey[256];
VkPipelineLayout m_pipelineLayout; VkPipelineLayout m_pipelineLayout;
VkPipeline m_graphicsPipeline; VkPipeline m_graphicsPipeline;
void initPushConstantStage(ShaderStages stage, const SpvReflectShaderModule* reflection); void initPushConstantStage(ShaderStages stage, const SpvReflectShaderModule* reflection);
}; };

View File

@@ -44,20 +44,21 @@
using namespace std; using namespace std;
KRPipelineManager::KRPipelineManager(KRContext &context) : KRContextObject(context) { KRPipelineManager::KRPipelineManager(KRContext& context) : KRContextObject(context)
m_active_pipeline = NULL; {
m_active_pipeline = NULL;
#ifndef ANDROID #ifndef ANDROID
bool success = glslang::InitializeProcess(); bool success = glslang::InitializeProcess();
if (success) { if (success) {
printf("GLSLang Initialized.\n"); printf("GLSLang Initialized.\n");
} } else {
else { printf("Failed to initialize GLSLang.\n");
printf("Failed to initialize GLSLang.\n"); }
}
#endif // ANDROID #endif // ANDROID
} }
KRPipelineManager::~KRPipelineManager() { KRPipelineManager::~KRPipelineManager()
{
#ifndef ANDROID #ifndef ANDROID
glslang::FinalizeProcess(); glslang::FinalizeProcess();
#endif // ANDROID #endif // ANDROID
@@ -92,7 +93,7 @@ KRPipeline* KRPipelineManager::getPipeline(KRSurface& surface, const PipelineInf
/* /*
// TODO - Vulkan Refactoring, merge with Vulkan version // TODO - Vulkan Refactoring, merge with Vulkan version
KRPipeline *KRPipelineManager::getPipeline(KRSurface& surface, const PipelineInfo &info) { KRPipeline *KRPipelineManager::getPipeline(KRSurface& surface, const PipelineInfo &info) {
int iShadowQuality = 0; // FINDME - HACK - Placeholder code, need to iterate through lights and dynamically build shader int iShadowQuality = 0; // FINDME - HACK - Placeholder code, need to iterate through lights and dynamically build shader
@@ -103,7 +104,7 @@ KRPipeline *KRPipelineManager::getPipeline(KRSurface& surface, const PipelineInf
if (info.directional_lights) { if (info.directional_lights) {
light_directional_count = (int)info.directional_lights->size(); light_directional_count = (int)info.directional_lights->size();
} }
if (info.point_lights) { if (info.point_lights) {
light_point_count = (int)info.point_lights->size(); light_point_count = (int)info.point_lights->size();
} }
@@ -115,13 +116,13 @@ KRPipeline *KRPipelineManager::getPipeline(KRSurface& surface, const PipelineInf
iShadowQuality = directional_light->getShadowBufferCount(); iShadowQuality = directional_light->getShadowBufferCount();
} }
} }
if(iShadowQuality > info.pCamera->settings.m_cShadowBuffers) { if(iShadowQuality > info.pCamera->settings.m_cShadowBuffers) {
iShadowQuality = info.pCamera->settings.m_cShadowBuffers; iShadowQuality = info.pCamera->settings.m_cShadowBuffers;
} }
bool bFadeColorEnabled = info.pCamera->getFadeColor().w >= 0.0f; bool bFadeColorEnabled = info.pCamera->getFadeColor().w >= 0.0f;
std::pair<std::string, std::vector<int> > key; std::pair<std::string, std::vector<int> > key;
key.first = *info.shader_name; key.first = *info.shader_name;
key.second.push_back(light_directional_count); key.second.push_back(light_directional_count);
@@ -171,10 +172,10 @@ KRPipeline *KRPipelineManager::getPipeline(KRSurface& surface, const PipelineInf
key.second.push_back((int)(info.pCamera->settings.vignette_falloff * 1000.0f)); key.second.push_back((int)(info.pCamera->settings.vignette_falloff * 1000.0f));
key.second.push_back(info.bRimColor); key.second.push_back(info.bRimColor);
key.second.push_back(bFadeColorEnabled); key.second.push_back(bFadeColorEnabled);
KRPipeline *pPipeline = m_pipelines[key]; KRPipeline *pPipeline = m_pipelines[key];
if(pPipeline == NULL) { if(pPipeline == NULL) {
if(m_pipelines.size() > KRContext::KRENGINE_MAX_PIPELINE_HANDLES) { if(m_pipelines.size() > KRContext::KRENGINE_MAX_PIPELINE_HANDLES) {
// Keep the size of the pipeline cache reasonable // Keep the size of the pipeline cache reasonable
@@ -183,7 +184,7 @@ KRPipeline *KRPipelineManager::getPipeline(KRSurface& surface, const PipelineInf
m_pipelines.erase(itr); m_pipelines.erase(itr);
KRContext::Log(KRContext::LOG_LEVEL_INFORMATION, "Swapping pipelines...\n"); KRContext::Log(KRContext::LOG_LEVEL_INFORMATION, "Swapping pipelines...\n");
} }
stringstream stream; stringstream stream;
stream.precision(std::numeric_limits<long double>::digits10); stream.precision(std::numeric_limits<long double>::digits10);
@@ -194,37 +195,37 @@ KRPipeline *KRPipelineManager::getPipeline(KRSurface& surface, const PipelineInf
stream << "\n#define mediump"; stream << "\n#define mediump";
stream << "\n#define highp"; stream << "\n#define highp";
#endif #endif
stream << "\n#define LIGHT_DIRECTIONAL_COUNT " << light_directional_count; stream << "\n#define LIGHT_DIRECTIONAL_COUNT " << light_directional_count;
stream << "\n#define LIGHT_POINT_COUNT " << light_point_count; stream << "\n#define LIGHT_POINT_COUNT " << light_point_count;
stream << "\n#define LIGHT_SPOT_COUNT " << light_spot_count; stream << "\n#define LIGHT_SPOT_COUNT " << light_spot_count;
stream << "\n#define BONE_COUNT " << info.bone_count; stream << "\n#define BONE_COUNT " << info.bone_count;
stream << "\n#define HAS_DIFFUSE_MAP " << (info.bDiffuseMap ? "1" : "0"); stream << "\n#define HAS_DIFFUSE_MAP " << (info.bDiffuseMap ? "1" : "0");
stream << "\n#define HAS_DIFFUSE_MAP_SCALE " << (info.bDiffuseMapScale ? "1" : "0"); stream << "\n#define HAS_DIFFUSE_MAP_SCALE " << (info.bDiffuseMapScale ? "1" : "0");
stream << "\n#define HAS_DIFFUSE_MAP_OFFSET " << (info.bDiffuseMapOffset ? "1" : "0"); stream << "\n#define HAS_DIFFUSE_MAP_OFFSET " << (info.bDiffuseMapOffset ? "1" : "0");
stream << "\n#define HAS_SPEC_MAP " << (info.bSpecMap ? "1" : "0"); stream << "\n#define HAS_SPEC_MAP " << (info.bSpecMap ? "1" : "0");
stream << "\n#define HAS_SPEC_MAP_SCALE " << (info.bSpecMapScale ? "1" : "0"); stream << "\n#define HAS_SPEC_MAP_SCALE " << (info.bSpecMapScale ? "1" : "0");
stream << "\n#define HAS_SPEC_MAP_OFFSET " << (info.bSpecMapOffset ? "1" : "0"); stream << "\n#define HAS_SPEC_MAP_OFFSET " << (info.bSpecMapOffset ? "1" : "0");
stream << "\n#define HAS_NORMAL_MAP " << (info.bNormalMap ? "1" : "0"); stream << "\n#define HAS_NORMAL_MAP " << (info.bNormalMap ? "1" : "0");
stream << "\n#define HAS_NORMAL_MAP_SCALE " << (info.bNormalMapScale ? "1" : "0"); stream << "\n#define HAS_NORMAL_MAP_SCALE " << (info.bNormalMapScale ? "1" : "0");
stream << "\n#define HAS_NORMAL_MAP_OFFSET " << (info.bNormalMapOffset ? "1" : "0"); stream << "\n#define HAS_NORMAL_MAP_OFFSET " << (info.bNormalMapOffset ? "1" : "0");
stream << "\n#define HAS_REFLECTION_MAP " << (info.bReflectionMap ? "1" : "0"); stream << "\n#define HAS_REFLECTION_MAP " << (info.bReflectionMap ? "1" : "0");
stream << "\n#define HAS_REFLECTION_MAP_SCALE " << (info.bReflectionMapScale ? "1" : "0"); stream << "\n#define HAS_REFLECTION_MAP_SCALE " << (info.bReflectionMapScale ? "1" : "0");
stream << "\n#define HAS_REFLECTION_MAP_OFFSET " << (info.bReflectionMapOffset ? "1" : "0"); stream << "\n#define HAS_REFLECTION_MAP_OFFSET " << (info.bReflectionMapOffset ? "1" : "0");
stream << "\n#define HAS_LIGHT_MAP " << (info.bLightMap ? "1" : "0"); stream << "\n#define HAS_LIGHT_MAP " << (info.bLightMap ? "1" : "0");
stream << "\n#define HAS_REFLECTION_CUBE_MAP " << (info.bReflectionCubeMap ? "1" : "0"); stream << "\n#define HAS_REFLECTION_CUBE_MAP " << (info.bReflectionCubeMap ? "1" : "0");
stream << "\n#define ALPHA_TEST " << (info.bAlphaTest ? "1" : "0"); stream << "\n#define ALPHA_TEST " << (info.bAlphaTest ? "1" : "0");
stream << "\n#define ALPHA_BLEND " << ((info.rasterMode == RasterMode::kAlphaBlend stream << "\n#define ALPHA_BLEND " << ((info.rasterMode == RasterMode::kAlphaBlend
|| info.rasterMode == RasterMode::kAlphaBlendNoTest || info.rasterMode == RasterMode::kAlphaBlendNoTest
|| info.rasterMode == RasterMode::kAdditive || info.rasterMode == RasterMode::kAdditive
|| info.rasterMode == RasterMode::kAdditiveNoTest) ? "1" : "0"); || info.rasterMode == RasterMode::kAdditiveNoTest) ? "1" : "0");
stream << "\n#define ENABLE_PER_PIXEL " << (info.pCamera->settings.bEnablePerPixel ? "1" : "0"); stream << "\n#define ENABLE_PER_PIXEL " << (info.pCamera->settings.bEnablePerPixel ? "1" : "0");
stream << "\n#define DEBUG_PSSM " << (info.pCamera->settings.bDebugPSSM ? "1" : "0"); stream << "\n#define DEBUG_PSSM " << (info.pCamera->settings.bDebugPSSM ? "1" : "0");
stream << "\n#define SHADOW_QUALITY " << iShadowQuality; stream << "\n#define SHADOW_QUALITY " << iShadowQuality;
@@ -253,12 +254,12 @@ KRPipeline *KRPipelineManager::getPipeline(KRSurface& surface, const PipelineInf
stream << "\n#define ENABLE_FLASH " << (info.pCamera->settings.bEnableFlash ? "1" : "0"); stream << "\n#define ENABLE_FLASH " << (info.pCamera->settings.bEnableFlash ? "1" : "0");
stream << "\n#define ENABLE_VIGNETTE " << (info.pCamera->settings.bEnableVignette ? "1" : "0"); stream << "\n#define ENABLE_VIGNETTE " << (info.pCamera->settings.bEnableVignette ? "1" : "0");
stream << "\n#define VOLUMETRIC_ENVIRONMENT_DOWNSAMPLED " << (info.pCamera->settings.volumetric_environment_enable && info.pCamera->settings.volumetric_environment_downsample != 0 ? "1" : "0"); stream << "\n#define VOLUMETRIC_ENVIRONMENT_DOWNSAMPLED " << (info.pCamera->settings.volumetric_environment_enable && info.pCamera->settings.volumetric_environment_downsample != 0 ? "1" : "0");
stream.setf(ios::fixed,ios::floatfield); stream.setf(ios::fixed,ios::floatfield);
stream.precision(std::numeric_limits<long double>::digits10); stream.precision(std::numeric_limits<long double>::digits10);
stream << "\n#define DOF_DEPTH " << info.pCamera->settings.dof_depth; stream << "\n#define DOF_DEPTH " << info.pCamera->settings.dof_depth;
stream << "\n#define DOF_FALLOFF " << info.pCamera->settings.dof_falloff; stream << "\n#define DOF_FALLOFF " << info.pCamera->settings.dof_falloff;
stream << "\n#define FLASH_DEPTH " << info.pCamera->settings.flash_depth; stream << "\n#define FLASH_DEPTH " << info.pCamera->settings.flash_depth;
@@ -266,26 +267,26 @@ KRPipeline *KRPipelineManager::getPipeline(KRSurface& surface, const PipelineInf
stream << "\n#define FLASH_INTENSITY " << info.pCamera->settings.flash_intensity; stream << "\n#define FLASH_INTENSITY " << info.pCamera->settings.flash_intensity;
stream << "\n#define VIGNETTE_RADIUS " << info.pCamera->settings.vignette_radius; stream << "\n#define VIGNETTE_RADIUS " << info.pCamera->settings.vignette_radius;
stream << "\n#define VIGNETTE_FALLOFF " << info.pCamera->settings.vignette_falloff; stream << "\n#define VIGNETTE_FALLOFF " << info.pCamera->settings.vignette_falloff;
stream << "\n"; stream << "\n";
std::string options = stream.str(); std::string options = stream.str();
KRSourceManager *sourceManager = m_pContext->getSourceManager(); KRSourceManager *sourceManager = m_pContext->getSourceManager();
KRSource *vertSource = sourceManager->get(info.shader_name->c_str(), "vert"); KRSource *vertSource = sourceManager->get(info.shader_name->c_str(), "vert");
KRSource *fragSource = sourceManager->get(info.shader_name->c_str(), "frag"); KRSource *fragSource = sourceManager->get(info.shader_name->c_str(), "frag");
if(vertSource == nullptr) { if(vertSource == nullptr) {
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Vertex Shader Missing: %s", info.shader_name->c_str()); KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Vertex Shader Missing: %s", info.shader_name->c_str());
} }
if(fragSource == nullptr) { if(fragSource == nullptr) {
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Fragment Shader Missing: %s", info.shader_name->c_str()); KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Fragment Shader Missing: %s", info.shader_name->c_str());
} }
Vector4 fade_color = info.pCamera->getFadeColor(); Vector4 fade_color = info.pCamera->getFadeColor();
char szKey[256]; char szKey[256];
sprintf(szKey, "%i_%i_%i_%i_%i_%i_%i_%i_%i_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%i_%s_%i_%d_%d_%f_%f_%f_%f_%f_%f_%f_%f_%f_%f_%f", (int)info.rasterMode, (int)info.cullMode, (int)info.modelFormat, (int)info.vertexAttributes, light_directional_count, light_point_count, light_spot_count, info.bone_count, info.pCamera->settings.fog_type, info.pCamera->settings.bEnablePerPixel, info.bAlphaTest, info.bDiffuseMap, info.bNormalMap, info.bSpecMap, info.bReflectionMap, info.bReflectionCubeMap, info.pCamera->settings.bDebugPSSM, iShadowQuality, info.pCamera->settings.bEnableAmbient, info.pCamera->settings.bEnableDiffuse, info.pCamera->settings.bEnableSpecular, info.bLightMap, info.bDiffuseMapScale, info.bSpecMapScale, info.bReflectionMapScale, info.bNormalMapScale, info.bDiffuseMapOffset, info.bSpecMapOffset, info.bReflectionMapOffset, info.bNormalMapOffset, info.pCamera->settings.volumetric_environment_enable && info.pCamera->settings.volumetric_environment_downsample != 0, info.renderPass, info.shader_name->c_str(), info.pCamera->settings.dof_quality, info.pCamera->settings.bEnableFlash, info.pCamera->settings.bEnableVignette, info.pCamera->settings.dof_depth, info.pCamera->settings.dof_falloff, info.pCamera->settings.flash_depth, info.pCamera->settings.flash_falloff, info.pCamera->settings.flash_intensity, info.pCamera->settings.vignette_radius, info.pCamera->settings.vignette_falloff, fade_color.x, fade_color.y, fade_color.z, fade_color.w); sprintf(szKey, "%i_%i_%i_%i_%i_%i_%i_%i_%i_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%i_%s_%i_%d_%d_%f_%f_%f_%f_%f_%f_%f_%f_%f_%f_%f", (int)info.rasterMode, (int)info.cullMode, (int)info.modelFormat, (int)info.vertexAttributes, light_directional_count, light_point_count, light_spot_count, info.bone_count, info.pCamera->settings.fog_type, info.pCamera->settings.bEnablePerPixel, info.bAlphaTest, info.bDiffuseMap, info.bNormalMap, info.bSpecMap, info.bReflectionMap, info.bReflectionCubeMap, info.pCamera->settings.bDebugPSSM, iShadowQuality, info.pCamera->settings.bEnableAmbient, info.pCamera->settings.bEnableDiffuse, info.pCamera->settings.bEnableSpecular, info.bLightMap, info.bDiffuseMapScale, info.bSpecMapScale, info.bReflectionMapScale, info.bNormalMapScale, info.bDiffuseMapOffset, info.bSpecMapOffset, info.bReflectionMapOffset, info.bNormalMapOffset, info.pCamera->settings.volumetric_environment_enable && info.pCamera->settings.volumetric_environment_downsample != 0, info.renderPass, info.shader_name->c_str(), info.pCamera->settings.dof_quality, info.pCamera->settings.bEnableFlash, info.pCamera->settings.bEnableVignette, info.pCamera->settings.dof_depth, info.pCamera->settings.dof_falloff, info.pCamera->settings.flash_depth, info.pCamera->settings.flash_falloff, info.pCamera->settings.flash_intensity, info.pCamera->settings.vignette_radius, info.pCamera->settings.vignette_falloff, fade_color.x, fade_color.y, fade_color.z, fade_color.w);
pPipeline = new KRPipeline(getContext(), szKey, options, vertSource->getData()->getString(), fragSource->getData()->getString()); pPipeline = new KRPipeline(getContext(), szKey, options, vertSource->getData()->getString(), fragSource->getData()->getString());
m_pipelines[key] = pPipeline; m_pipelines[key] = pPipeline;
@@ -294,8 +295,9 @@ KRPipeline *KRPipelineManager::getPipeline(KRSurface& surface, const PipelineInf
} }
*/ */
size_t KRPipelineManager::getPipelineHandlesUsed() { size_t KRPipelineManager::getPipelineHandlesUsed()
return m_pipelines.size(); {
return m_pipelines.size();
} }

View File

@@ -48,18 +48,19 @@ class KRPipeline;
class PipelineInfo; class PipelineInfo;
class KRCamera; class KRCamera;
class KRPipelineManager : public KRContextObject { class KRPipelineManager : public KRContextObject
{
public: public:
KRPipelineManager(KRContext &context); KRPipelineManager(KRContext& context);
virtual ~KRPipelineManager(); virtual ~KRPipelineManager();
KRPipeline* get(const char* szKey); KRPipeline* get(const char* szKey);
KRPipeline* getPipeline(KRSurface& surface, const PipelineInfo& info);
size_t getPipelineHandlesUsed(); KRPipeline* getPipeline(KRSurface& surface, const PipelineInfo& info);
KRPipeline *m_active_pipeline; size_t getPipelineHandlesUsed();
KRPipeline* m_active_pipeline;
private: private:
typedef std::map<std::pair<std::string, std::vector<int> >, KRPipeline*> PipelineMap; typedef std::map<std::pair<std::string, std::vector<int> >, KRPipeline*> PipelineMap;

View File

@@ -42,199 +42,204 @@ void KRPointLight::InitNodeInfo(KrNodeInfo* nodeInfo)
// No additional members // No additional members
} }
KRPointLight::KRPointLight(KRScene &scene, std::string name) : KRLight(scene, name) KRPointLight::KRPointLight(KRScene& scene, std::string name) : KRLight(scene, name)
{ {
m_sphereVertices = NULL; m_sphereVertices = NULL;
m_cVertices = 0; m_cVertices = 0;
} }
KRPointLight::~KRPointLight() KRPointLight::~KRPointLight()
{ {
if(m_sphereVertices) { if (m_sphereVertices) {
delete m_sphereVertices; delete m_sphereVertices;
m_cVertices = 0; m_cVertices = 0;
} }
} }
std::string KRPointLight::getElementName() { std::string KRPointLight::getElementName()
return "point_light"; {
return "point_light";
} }
AABB KRPointLight::getBounds() { AABB KRPointLight::getBounds()
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE); {
if(influence_radius < m_flareOcclusionSize) { float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
influence_radius = m_flareOcclusionSize; if (influence_radius < m_flareOcclusionSize) {
} influence_radius = m_flareOcclusionSize;
return AABB::Create(Vector3::Create(-influence_radius), Vector3::Create(influence_radius), getModelMatrix()); }
return AABB::Create(Vector3::Create(-influence_radius), Vector3::Create(influence_radius), getModelMatrix());
} }
void KRPointLight::render(RenderInfo& ri) void KRPointLight::render(RenderInfo& ri)
{ {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if (m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRLight::render(ri);
bool bVisualize = ri.renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && ri.camera->settings.bShowDeferred;
if(ri.renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS || bVisualize) {
// Lights are rendered on the second pass of the deferred renderer
std::vector<KRPointLight *> this_light;
this_light.push_back(this);
Vector3 light_position = getLocalTranslation(); KRLight::render(ri);
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
Matrix4 sphereModelMatrix = Matrix4();
sphereModelMatrix.scale(influence_radius);
sphereModelMatrix.translate(light_position.x, light_position.y, light_position.z);
if(ri.viewport.visible(getBounds())) { // Cull out any lights not within the view frustrum bool bVisualize = ri.renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && ri.camera->settings.bShowDeferred;
Vector3 view_light_position = Matrix4::Dot(ri.viewport.getViewMatrix(), light_position); if (ri.renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS || bVisualize) {
// Lights are rendered on the second pass of the deferred renderer
bool bInsideLight = view_light_position.sqrMagnitude() <= (influence_radius + ri.camera->settings.getPerspectiveNearZ()) * (influence_radius + ri.camera->settings.getPerspectiveNearZ());
std::string shader_name(bVisualize ? "visualize_overlay" : (bInsideLight ? "light_point_inside" : "light_point"));
PipelineInfo info{};
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &this_light;
info.renderPass = ri.renderPass;
if (bInsideLight) {
info.rasterMode = bVisualize ? RasterMode::kAdditiveNoTest : RasterMode::kAlphaBlendNoTest;
}
else {
info.rasterMode = bVisualize ? RasterMode::kAdditive : RasterMode::kAlphaBlend;
}
info.vertexAttributes = bInsideLight ? m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES.getVertexAttributes() : 1 << KRMesh::KRENGINE_ATTRIB_VERTEX;
info.modelFormat = bInsideLight ? ModelFormat::KRENGINE_MODEL_FORMAT_STRIP : ModelFormat::KRENGINE_MODEL_FORMAT_TRIANGLES;
KRPipeline *pShader = getContext().getPipelineManager()->getPipeline(*ri.surface, info); std::vector<KRPointLight*> this_light;
pShader->setUniform(KRPipeline::Uniform::light_color, m_color); this_light.push_back(this);
pShader->setUniform(KRPipeline::Uniform::light_intensity, m_intensity * 0.01f);
pShader->setUniform(KRPipeline::Uniform::light_decay_start, getDecayStart());
pShader->setUniform(KRPipeline::Uniform::light_cutoff, KRLIGHT_MIN_INFLUENCE);
pShader->setUniform(KRPipeline::Uniform::light_position, light_position);
pShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, sphereModelMatrix, &this_light, nullptr, nullptr, ri.renderPass);
if(bInsideLight) {
// Render a full screen quad
m_pContext->getMeshManager()->bindVBO(ri.commandBuffer, &m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
vkCmdDraw(ri.commandBuffer, 4, 1, 0, 0);
} else {
// Render sphere of light's influence
generateMesh();
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_VERTEX, 3, GL_FLOAT, 0, 0, m_sphereVertices));
vkCmdDraw(ri.commandBuffer, m_cVertices, 1, 0, 0); Vector3 light_position = getLocalTranslation();
}
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
Matrix4 sphereModelMatrix = Matrix4();
sphereModelMatrix.scale(influence_radius);
sphereModelMatrix.translate(light_position.x, light_position.y, light_position.z);
if (ri.viewport.visible(getBounds())) { // Cull out any lights not within the view frustrum
Vector3 view_light_position = Matrix4::Dot(ri.viewport.getViewMatrix(), light_position);
bool bInsideLight = view_light_position.sqrMagnitude() <= (influence_radius + ri.camera->settings.getPerspectiveNearZ()) * (influence_radius + ri.camera->settings.getPerspectiveNearZ());
std::string shader_name(bVisualize ? "visualize_overlay" : (bInsideLight ? "light_point_inside" : "light_point"));
PipelineInfo info{};
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &this_light;
info.renderPass = ri.renderPass;
if (bInsideLight) {
info.rasterMode = bVisualize ? RasterMode::kAdditiveNoTest : RasterMode::kAlphaBlendNoTest;
} else {
info.rasterMode = bVisualize ? RasterMode::kAdditive : RasterMode::kAlphaBlend;
}
info.vertexAttributes = bInsideLight ? m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES.getVertexAttributes() : 1 << KRMesh::KRENGINE_ATTRIB_VERTEX;
info.modelFormat = bInsideLight ? ModelFormat::KRENGINE_MODEL_FORMAT_STRIP : ModelFormat::KRENGINE_MODEL_FORMAT_TRIANGLES;
KRPipeline* pShader = getContext().getPipelineManager()->getPipeline(*ri.surface, info);
pShader->setUniform(KRPipeline::Uniform::light_color, m_color);
pShader->setUniform(KRPipeline::Uniform::light_intensity, m_intensity * 0.01f);
pShader->setUniform(KRPipeline::Uniform::light_decay_start, getDecayStart());
pShader->setUniform(KRPipeline::Uniform::light_cutoff, KRLIGHT_MIN_INFLUENCE);
pShader->setUniform(KRPipeline::Uniform::light_position, light_position);
pShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, sphereModelMatrix, &this_light, nullptr, nullptr, ri.renderPass);
if (bInsideLight) {
// Render a full screen quad
m_pContext->getMeshManager()->bindVBO(ri.commandBuffer, &m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
vkCmdDraw(ri.commandBuffer, 4, 1, 0, 0);
} else {
// Render sphere of light's influence
generateMesh();
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_VERTEX, 3, GL_FLOAT, 0, 0, m_sphereVertices));
vkCmdDraw(ri.commandBuffer, m_cVertices, 1, 0, 0);
}
}
} }
}
} }
void KRPointLight::generateMesh() { void KRPointLight::generateMesh()
// Create a triangular facet approximation to a sphere {
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/ // Create a triangular facet approximation to a sphere
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
int iterations = 3;
int facet_count = (int)(pow(4, iterations) * 8);
if(m_cVertices != facet_count * 3) {
if(m_sphereVertices) {
free(m_sphereVertices);
m_sphereVertices = NULL;
}
m_cVertices = facet_count * 3;
int iterations = 3;
class Facet3 { int facet_count = (int)(pow(4, iterations) * 8);
public:
Facet3() {
}
~Facet3() {
}
Vector3 p1;
Vector3 p2;
Vector3 p3;
};
std::vector<Facet3> f = std::vector<Facet3>(facet_count);
int i,it;
float a;
Vector3 p[6] = {
Vector3::Create(0,0,1),
Vector3::Create(0,0,-1),
Vector3::Create(-1,-1,0),
Vector3::Create(1,-1,0),
Vector3::Create(1,1,0),
Vector3::Create(-1,1,0)
};
Vector3 pa,pb,pc; if (m_cVertices != facet_count * 3) {
int nt = 0,ntold; if (m_sphereVertices) {
free(m_sphereVertices);
/* Create the level 0 object */ m_sphereVertices = NULL;
a = 1.0f / sqrtf(2.0f);
for (i=0;i<6;i++) {
p[i].x *= a;
p[i].y *= a;
}
f[0].p1 = p[0]; f[0].p2 = p[3]; f[0].p3 = p[4];
f[1].p1 = p[0]; f[1].p2 = p[4]; f[1].p3 = p[5];
f[2].p1 = p[0]; f[2].p2 = p[5]; f[2].p3 = p[2];
f[3].p1 = p[0]; f[3].p2 = p[2]; f[3].p3 = p[3];
f[4].p1 = p[1]; f[4].p2 = p[4]; f[4].p3 = p[3];
f[5].p1 = p[1]; f[5].p2 = p[5]; f[5].p3 = p[4];
f[6].p1 = p[1]; f[6].p2 = p[2]; f[6].p3 = p[5];
f[7].p1 = p[1]; f[7].p2 = p[3]; f[7].p3 = p[2];
nt = 8;
/* Bisect each edge and move to the surface of a unit sphere */
for (it=0;it<iterations;it++) {
ntold = nt;
for (i=0;i<ntold;i++) {
pa.x = (f[i].p1.x + f[i].p2.x) / 2;
pa.y = (f[i].p1.y + f[i].p2.y) / 2;
pa.z = (f[i].p1.z + f[i].p2.z) / 2;
pb.x = (f[i].p2.x + f[i].p3.x) / 2;
pb.y = (f[i].p2.y + f[i].p3.y) / 2;
pb.z = (f[i].p2.z + f[i].p3.z) / 2;
pc.x = (f[i].p3.x + f[i].p1.x) / 2;
pc.y = (f[i].p3.y + f[i].p1.y) / 2;
pc.z = (f[i].p3.z + f[i].p1.z) / 2;
pa.normalize();
pb.normalize();
pc.normalize();
f[nt].p1 = f[i].p1; f[nt].p2 = pa; f[nt].p3 = pc; nt++;
f[nt].p1 = pa; f[nt].p2 = f[i].p2; f[nt].p3 = pb; nt++;
f[nt].p1 = pb; f[nt].p2 = f[i].p3; f[nt].p3 = pc; nt++;
f[i].p1 = pa;
f[i].p2 = pb;
f[i].p3 = pc;
}
}
m_sphereVertices = (float*)malloc(sizeof(float) * m_cVertices * 3);
assert(m_sphereVertices != NULL);
float*pDest = m_sphereVertices;
for(int facet_index=0; facet_index < facet_count; facet_index++) {
*pDest++ = f[facet_index].p1.x;
*pDest++ = f[facet_index].p1.y;
*pDest++ = f[facet_index].p1.z;
*pDest++ = f[facet_index].p2.x;
*pDest++ = f[facet_index].p2.y;
*pDest++ = f[facet_index].p2.z;
*pDest++ = f[facet_index].p3.x;
*pDest++ = f[facet_index].p3.y;
*pDest++ = f[facet_index].p3.z;
}
} }
m_cVertices = facet_count * 3;
class Facet3
{
public:
Facet3()
{
}
~Facet3()
{
}
Vector3 p1;
Vector3 p2;
Vector3 p3;
};
std::vector<Facet3> f = std::vector<Facet3>(facet_count);
int i, it;
float a;
Vector3 p[6] = {
Vector3::Create(0,0,1),
Vector3::Create(0,0,-1),
Vector3::Create(-1,-1,0),
Vector3::Create(1,-1,0),
Vector3::Create(1,1,0),
Vector3::Create(-1,1,0)
};
Vector3 pa, pb, pc;
int nt = 0, ntold;
/* Create the level 0 object */
a = 1.0f / sqrtf(2.0f);
for (i = 0; i < 6; i++) {
p[i].x *= a;
p[i].y *= a;
}
f[0].p1 = p[0]; f[0].p2 = p[3]; f[0].p3 = p[4];
f[1].p1 = p[0]; f[1].p2 = p[4]; f[1].p3 = p[5];
f[2].p1 = p[0]; f[2].p2 = p[5]; f[2].p3 = p[2];
f[3].p1 = p[0]; f[3].p2 = p[2]; f[3].p3 = p[3];
f[4].p1 = p[1]; f[4].p2 = p[4]; f[4].p3 = p[3];
f[5].p1 = p[1]; f[5].p2 = p[5]; f[5].p3 = p[4];
f[6].p1 = p[1]; f[6].p2 = p[2]; f[6].p3 = p[5];
f[7].p1 = p[1]; f[7].p2 = p[3]; f[7].p3 = p[2];
nt = 8;
/* Bisect each edge and move to the surface of a unit sphere */
for (it = 0; it < iterations; it++) {
ntold = nt;
for (i = 0; i < ntold; i++) {
pa.x = (f[i].p1.x + f[i].p2.x) / 2;
pa.y = (f[i].p1.y + f[i].p2.y) / 2;
pa.z = (f[i].p1.z + f[i].p2.z) / 2;
pb.x = (f[i].p2.x + f[i].p3.x) / 2;
pb.y = (f[i].p2.y + f[i].p3.y) / 2;
pb.z = (f[i].p2.z + f[i].p3.z) / 2;
pc.x = (f[i].p3.x + f[i].p1.x) / 2;
pc.y = (f[i].p3.y + f[i].p1.y) / 2;
pc.z = (f[i].p3.z + f[i].p1.z) / 2;
pa.normalize();
pb.normalize();
pc.normalize();
f[nt].p1 = f[i].p1; f[nt].p2 = pa; f[nt].p3 = pc; nt++;
f[nt].p1 = pa; f[nt].p2 = f[i].p2; f[nt].p3 = pb; nt++;
f[nt].p1 = pb; f[nt].p2 = f[i].p3; f[nt].p3 = pc; nt++;
f[i].p1 = pa;
f[i].p2 = pb;
f[i].p3 = pc;
}
}
m_sphereVertices = (float*)malloc(sizeof(float) * m_cVertices * 3);
assert(m_sphereVertices != NULL);
float* pDest = m_sphereVertices;
for (int facet_index = 0; facet_index < facet_count; facet_index++) {
*pDest++ = f[facet_index].p1.x;
*pDest++ = f[facet_index].p1.y;
*pDest++ = f[facet_index].p1.z;
*pDest++ = f[facet_index].p2.x;
*pDest++ = f[facet_index].p2.y;
*pDest++ = f[facet_index].p2.z;
*pDest++ = f[facet_index].p3.x;
*pDest++ = f[facet_index].p3.y;
*pDest++ = f[facet_index].p3.z;
}
}
} }

View File

@@ -33,21 +33,21 @@
#include "KRLight.h" #include "KRLight.h"
class KRPointLight : public KRLight { class KRPointLight : public KRLight
{
public: public:
static void InitNodeInfo(KrNodeInfo* nodeInfo); static void InitNodeInfo(KrNodeInfo* nodeInfo);
KRPointLight(KRScene &scene, std::string name); KRPointLight(KRScene& scene, std::string name);
virtual ~KRPointLight(); virtual ~KRPointLight();
virtual std::string getElementName(); virtual std::string getElementName();
virtual AABB getBounds(); virtual AABB getBounds();
virtual void render(RenderInfo& ri);
virtual void render(RenderInfo& ri);
private: private:
void generateMesh(); void generateMesh();
float *m_sphereVertices; float* m_sphereVertices;
int m_cVertices; int m_cVertices;
}; };

View File

@@ -71,8 +71,7 @@ void KRPresentationThread::run()
std::chrono::microseconds sleep_duration(15000); std::chrono::microseconds sleep_duration(15000);
m_activeState = PresentThreadState::run; m_activeState = PresentThreadState::run;
while (m_requestedState != PresentThreadRequest::stop) while (m_requestedState != PresentThreadRequest::stop) {
{
switch (m_activeState) { switch (m_activeState) {
case PresentThreadState::pause: case PresentThreadState::pause:
case PresentThreadState::stop: case PresentThreadState::stop:
@@ -103,7 +102,7 @@ void KRPresentationThread::renderFrame()
unordered_map<KrSurfaceHandle, std::unique_ptr<KRSurface>>& surfaces = m_pContext->getSurfaceManager()->getSurfaces(); unordered_map<KrSurfaceHandle, std::unique_ptr<KRSurface>>& surfaces = m_pContext->getSurfaceManager()->getSurfaces();
KRSceneManager* sceneManager = m_pContext->getSceneManager(); KRSceneManager* sceneManager = m_pContext->getSceneManager();
KRScene *scene = sceneManager->getFirstScene(); KRScene* scene = sceneManager->getFirstScene();
for (auto surfaceItr = surfaces.begin(); surfaceItr != surfaces.end(); surfaceItr++) { for (auto surfaceItr = surfaces.begin(); surfaceItr != surfaces.end(); surfaceItr++) {
KRSurface& surface = *(*surfaceItr).second; KRSurface& surface = *(*surfaceItr).second;

View File

@@ -35,7 +35,7 @@
KRRenderPass::KRRenderPass(KRContext& context) KRRenderPass::KRRenderPass(KRContext& context)
: KRContextObject(context) : KRContextObject(context)
, m_renderPass(VK_NULL_HANDLE) , m_renderPass(VK_NULL_HANDLE)
{ {
} }
@@ -45,7 +45,7 @@ KRRenderPass::~KRRenderPass()
assert(m_renderPass == VK_NULL_HANDLE); assert(m_renderPass == VK_NULL_HANDLE);
} }
void KRRenderPass::create(KRDevice &device, VkFormat swapChainImageFormat, VkFormat depthImageFormat, const RenderPassInfo& info) void KRRenderPass::create(KRDevice& device, VkFormat swapChainImageFormat, VkFormat depthImageFormat, const RenderPassInfo& info)
{ {
if (m_renderPass) { if (m_renderPass) {
return; return;
@@ -110,7 +110,7 @@ void KRRenderPass::create(KRDevice &device, VkFormat swapChainImageFormat, VkFor
} }
} }
void KRRenderPass::destroy(KRDevice &device) void KRRenderPass::destroy(KRDevice& device)
{ {
if (m_renderPass) { if (m_renderPass) {
vkDestroyRenderPass(device.m_logicalDevice, m_renderPass, nullptr); vkDestroyRenderPass(device.m_logicalDevice, m_renderPass, nullptr);

View File

@@ -51,9 +51,9 @@ public:
void create(KRDevice& device, VkFormat swapChainImageFormat, VkFormat depthImageFormat, const RenderPassInfo& info); void create(KRDevice& device, VkFormat swapChainImageFormat, VkFormat depthImageFormat, const RenderPassInfo& info);
void destroy(KRDevice& device); void destroy(KRDevice& device);
void begin(VkCommandBuffer &commandBuffer, KRSurface& surface, const Vector4& clearColor); void begin(VkCommandBuffer& commandBuffer, KRSurface& surface, const Vector4& clearColor);
void end(VkCommandBuffer& commandBuffer); void end(VkCommandBuffer& commandBuffer);
// private: // private:
VkRenderPass m_renderPass; VkRenderPass m_renderPass;
}; };

View File

@@ -33,195 +33,197 @@
KRRenderSettings::KRRenderSettings() KRRenderSettings::KRRenderSettings()
{ {
siren_enable = true; siren_enable = true;
siren_enable_reverb = true; siren_enable_reverb = true;
siren_enable_hrtf = true; siren_enable_hrtf = true;
siren_reverb_max_length = 2.0f; siren_reverb_max_length = 2.0f;
m_enable_realtime_occlusion = false; m_enable_realtime_occlusion = false;
bShowShadowBuffer = false; bShowShadowBuffer = false;
bShowOctree = false; bShowOctree = false;
bShowDeferred = false; bShowDeferred = false;
bEnablePerPixel = true; bEnablePerPixel = true;
bEnableDiffuseMap = true; bEnableDiffuseMap = true;
bEnableNormalMap = true; bEnableNormalMap = true;
bEnableSpecMap = true; bEnableSpecMap = true;
bEnableReflectionMap = true; bEnableReflectionMap = true;
bEnableReflection = true; bEnableReflection = true;
bDebugPSSM = false; bDebugPSSM = false;
bEnableAmbient = true; bEnableAmbient = true;
bEnableDiffuse = true; bEnableDiffuse = true;
bEnableSpecular = true; bEnableSpecular = true;
bEnableLightMap = true; bEnableLightMap = true;
bEnableDeferredLighting = false; bEnableDeferredLighting = false;
max_anisotropy = 4.0f; max_anisotropy = 4.0f;
ambient_intensity = Vector3::Zero(); ambient_intensity = Vector3::Zero();
light_intensity = Vector3::One(); light_intensity = Vector3::One();
perspective_fov = 45.0f * D2R; perspective_fov = 45.0f * D2R;
perspective_nearz = 0.3f; // was 0.05f perspective_nearz = 0.3f; // was 0.05f
perspective_farz = 1000.0f; perspective_farz = 1000.0f;
dof_quality = 0; dof_quality = 0;
dof_depth = 0.05f; dof_depth = 0.05f;
dof_falloff = 0.05f; dof_falloff = 0.05f;
bEnableFlash = false; bEnableFlash = false;
flash_intensity = 1.0f; flash_intensity = 1.0f;
flash_depth = 0.7f; flash_depth = 0.7f;
flash_falloff = 0.5f; flash_falloff = 0.5f;
bEnableVignette = false; bEnableVignette = false;
vignette_radius = 0.4f; vignette_radius = 0.4f;
vignette_falloff = 1.0f; vignette_falloff = 1.0f;
m_cShadowBuffers = 0; m_cShadowBuffers = 0;
volumetric_environment_enable = false; volumetric_environment_enable = false;
volumetric_environment_downsample = 2; volumetric_environment_downsample = 2;
volumetric_environment_max_distance = 100.0f; volumetric_environment_max_distance = 100.0f;
volumetric_environment_quality = (50.0f - 5.0f) / 495.0f; volumetric_environment_quality = (50.0f - 5.0f) / 495.0f;
volumetric_environment_intensity = 0.9f; volumetric_environment_intensity = 0.9f;
fog_near = 50.0f; fog_near = 50.0f;
fog_far = 500.0f; fog_far = 500.0f;
fog_density = 0.0005f; fog_density = 0.0005f;
fog_color = Vector3::Create(0.45f, 0.45f, 0.5f); fog_color = Vector3::Create(0.45f, 0.45f, 0.5f);
fog_type = 0; fog_type = 0;
dust_particle_intensity = 0.25f; dust_particle_intensity = 0.25f;
dust_particle_enable = false; dust_particle_enable = false;
m_lodBias = 0.0f; m_lodBias = 0.0f;
debug_display = KRENGINE_DEBUG_DISPLAY_NONE; debug_display = KRENGINE_DEBUG_DISPLAY_NONE;
} }
KRRenderSettings::~KRRenderSettings() KRRenderSettings::~KRRenderSettings()
{ {
} }
KRRenderSettings& KRRenderSettings::operator=(const KRRenderSettings &s) KRRenderSettings& KRRenderSettings::operator=(const KRRenderSettings& s)
{ {
siren_enable = s.siren_enable; siren_enable = s.siren_enable;
siren_enable_reverb = s.siren_enable_reverb; siren_enable_reverb = s.siren_enable_reverb;
siren_enable_hrtf = s.siren_enable_hrtf; siren_enable_hrtf = s.siren_enable_hrtf;
siren_reverb_max_length = s.siren_reverb_max_length; siren_reverb_max_length = s.siren_reverb_max_length;
bEnablePerPixel = s.bEnablePerPixel; bEnablePerPixel = s.bEnablePerPixel;
bEnableDiffuseMap = s.bEnableDiffuseMap; bEnableDiffuseMap = s.bEnableDiffuseMap;
bEnableNormalMap = s.bEnableNormalMap; bEnableNormalMap = s.bEnableNormalMap;
bEnableSpecMap = s.bEnableSpecMap; bEnableSpecMap = s.bEnableSpecMap;
bEnableReflectionMap = s.bEnableReflectionMap; bEnableReflectionMap = s.bEnableReflectionMap;
bEnableReflection=s.bEnableReflection; bEnableReflection = s.bEnableReflection;
bEnableLightMap=s.bEnableLightMap; bEnableLightMap = s.bEnableLightMap;
bDebugPSSM=s.bDebugPSSM; bDebugPSSM = s.bDebugPSSM;
bShowShadowBuffer=s.bShowShadowBuffer; bShowShadowBuffer = s.bShowShadowBuffer;
bShowOctree=s.bShowOctree; bShowOctree = s.bShowOctree;
bShowDeferred=s.bShowDeferred; bShowDeferred = s.bShowDeferred;
bEnableAmbient=s.bEnableAmbient; bEnableAmbient = s.bEnableAmbient;
bEnableDiffuse=s.bEnableDiffuse; bEnableDiffuse = s.bEnableDiffuse;
bEnableSpecular=s.bEnableSpecular; bEnableSpecular = s.bEnableSpecular;
bEnableDeferredLighting=s.bEnableDeferredLighting; bEnableDeferredLighting = s.bEnableDeferredLighting;
light_intensity=s.light_intensity; light_intensity = s.light_intensity;
ambient_intensity=s.ambient_intensity; ambient_intensity = s.ambient_intensity;
perspective_fov=s.perspective_fov; perspective_fov = s.perspective_fov;
dof_quality=s.dof_quality; dof_quality = s.dof_quality;
dof_depth=s.dof_depth; dof_depth = s.dof_depth;
dof_falloff=s.dof_falloff; dof_falloff = s.dof_falloff;
bEnableFlash=s.bEnableFlash; bEnableFlash = s.bEnableFlash;
flash_intensity=s.flash_intensity; flash_intensity = s.flash_intensity;
flash_depth=s.flash_depth; flash_depth = s.flash_depth;
flash_falloff=s.flash_falloff; flash_falloff = s.flash_falloff;
bEnableVignette=s.bEnableVignette; bEnableVignette = s.bEnableVignette;
vignette_radius=s.vignette_radius; vignette_radius = s.vignette_radius;
vignette_falloff=s.vignette_falloff; vignette_falloff = s.vignette_falloff;
m_viewportSize=s.m_viewportSize; m_viewportSize = s.m_viewportSize;
m_cShadowBuffers=s.m_cShadowBuffers; m_cShadowBuffers = s.m_cShadowBuffers;
m_debug_text=s.m_debug_text; m_debug_text = s.m_debug_text;
volumetric_environment_enable=s.volumetric_environment_enable; volumetric_environment_enable = s.volumetric_environment_enable;
volumetric_environment_downsample=s.volumetric_environment_downsample; volumetric_environment_downsample = s.volumetric_environment_downsample;
volumetric_environment_max_distance=s.volumetric_environment_max_distance; volumetric_environment_max_distance = s.volumetric_environment_max_distance;
volumetric_environment_quality=s.volumetric_environment_quality; volumetric_environment_quality = s.volumetric_environment_quality;
volumetric_environment_intensity=s.volumetric_environment_intensity; volumetric_environment_intensity = s.volumetric_environment_intensity;
fog_near=s.fog_near; fog_near = s.fog_near;
fog_far=s.fog_far; fog_far = s.fog_far;
fog_density=s.fog_density; fog_density = s.fog_density;
fog_color=s.fog_color; fog_color = s.fog_color;
fog_type=s.fog_type; fog_type = s.fog_type;
dust_particle_intensity=s.dust_particle_intensity; dust_particle_intensity = s.dust_particle_intensity;
dust_particle_enable=s.dust_particle_enable; dust_particle_enable = s.dust_particle_enable;
perspective_nearz=s.perspective_nearz; perspective_nearz = s.perspective_nearz;
perspective_farz=s.perspective_farz; perspective_farz = s.perspective_farz;
debug_display = s.debug_display; debug_display = s.debug_display;
m_lodBias = s.m_lodBias; m_lodBias = s.m_lodBias;
m_enable_realtime_occlusion = s.m_enable_realtime_occlusion; m_enable_realtime_occlusion = s.m_enable_realtime_occlusion;
max_anisotropy = s.max_anisotropy; max_anisotropy = s.max_anisotropy;
return *this; return *this;
} }
const Vector2 &KRRenderSettings::getViewportSize() { const Vector2& KRRenderSettings::getViewportSize()
return m_viewportSize; {
return m_viewportSize;
} }
void KRRenderSettings::setViewportSize(const Vector2 &size) { void KRRenderSettings::setViewportSize(const Vector2& size)
m_viewportSize = size; {
m_viewportSize = size;
} }
float KRRenderSettings::getPerspectiveNearZ() float KRRenderSettings::getPerspectiveNearZ()
{ {
return perspective_nearz; return perspective_nearz;
} }
float KRRenderSettings::getPerspectiveFarZ() float KRRenderSettings::getPerspectiveFarZ()
{ {
return perspective_farz; return perspective_farz;
} }
void KRRenderSettings::setPerspectiveNear(float v) void KRRenderSettings::setPerspectiveNear(float v)
{ {
if(perspective_nearz != v) { if (perspective_nearz != v) {
perspective_nearz = v; perspective_nearz = v;
} }
} }
void KRRenderSettings::setPerpsectiveFarZ(float v) void KRRenderSettings::setPerpsectiveFarZ(float v)
{ {
if(perspective_farz != v) { if (perspective_farz != v) {
perspective_farz = v; perspective_farz = v;
} }
} }
float KRRenderSettings::getLODBias() float KRRenderSettings::getLODBias()
{ {
return m_lodBias; return m_lodBias;
} }
void KRRenderSettings::setLODBias(float v) void KRRenderSettings::setLODBias(float v)
{ {
m_lodBias = v; m_lodBias = v;
} }
bool KRRenderSettings::getEnableRealtimeOcclusion() bool KRRenderSettings::getEnableRealtimeOcclusion()
{ {
return m_enable_realtime_occlusion; return m_enable_realtime_occlusion;
} }
void KRRenderSettings::setEnableRealtimeOcclusion(bool enable) void KRRenderSettings::setEnableRealtimeOcclusion(bool enable)
{ {
m_enable_realtime_occlusion = enable; m_enable_realtime_occlusion = enable;
} }

View File

@@ -33,104 +33,106 @@
#include "KREngine-common.h" #include "KREngine-common.h"
class KRRenderSettings { class KRRenderSettings
{
public: public:
KRRenderSettings(); KRRenderSettings();
~KRRenderSettings(); ~KRRenderSettings();
// Overload assignment operator // Overload assignment operator
KRRenderSettings& operator=(const KRRenderSettings &s); KRRenderSettings& operator=(const KRRenderSettings& s);
const Vector2 &getViewportSize(); const Vector2& getViewportSize();
void setViewportSize(const Vector2 &size); void setViewportSize(const Vector2& size);
float getPerspectiveNearZ(); float getPerspectiveNearZ();
float getPerspectiveFarZ(); float getPerspectiveFarZ();
void setPerspectiveNear(float v); void setPerspectiveNear(float v);
void setPerpsectiveFarZ(float v); void setPerpsectiveFarZ(float v);
float getLODBias(); float getLODBias();
void setLODBias(float v); void setLODBias(float v);
bool bEnablePerPixel; bool bEnablePerPixel;
bool bEnableDiffuseMap; bool bEnableDiffuseMap;
bool bEnableNormalMap; bool bEnableNormalMap;
bool bEnableSpecMap; bool bEnableSpecMap;
bool bEnableReflectionMap; bool bEnableReflectionMap;
bool bEnableReflection; bool bEnableReflection;
bool bEnableLightMap; bool bEnableLightMap;
bool bDebugPSSM; bool bDebugPSSM;
bool bShowShadowBuffer; bool bShowShadowBuffer;
bool bShowOctree; bool bShowOctree;
bool bShowDeferred; bool bShowDeferred;
bool bEnableAmbient; bool bEnableAmbient;
bool bEnableDiffuse; bool bEnableDiffuse;
bool bEnableSpecular; bool bEnableSpecular;
bool bEnableDeferredLighting; bool bEnableDeferredLighting;
Vector3 light_intensity; Vector3 light_intensity;
Vector3 ambient_intensity; Vector3 ambient_intensity;
float perspective_fov; float perspective_fov;
int dof_quality; int dof_quality;
float dof_depth; float dof_depth;
float dof_falloff; float dof_falloff;
bool bEnableFlash; bool bEnableFlash;
float flash_intensity; float flash_intensity;
float flash_depth; float flash_depth;
float flash_falloff; float flash_falloff;
bool bEnableVignette; bool bEnableVignette;
float vignette_radius; float vignette_radius;
float vignette_falloff; float vignette_falloff;
Vector2 m_viewportSize; Vector2 m_viewportSize;
int m_cShadowBuffers; int m_cShadowBuffers;
std::string m_debug_text; std::string m_debug_text;
bool volumetric_environment_enable; bool volumetric_environment_enable;
int volumetric_environment_downsample; int volumetric_environment_downsample;
float volumetric_environment_max_distance; float volumetric_environment_max_distance;
float volumetric_environment_quality; float volumetric_environment_quality;
float volumetric_environment_intensity; float volumetric_environment_intensity;
float fog_near; float fog_near;
float fog_far; float fog_far;
float fog_density; float fog_density;
Vector3 fog_color; Vector3 fog_color;
int fog_type; // 0 = no fog, 1 = linear, 2 = exponential, 3 = exponential squared int fog_type; // 0 = no fog, 1 = linear, 2 = exponential, 3 = exponential squared
float dust_particle_intensity; float dust_particle_intensity;
bool dust_particle_enable; bool dust_particle_enable;
float perspective_nearz; float perspective_nearz;
float perspective_farz; float perspective_farz;
enum debug_display_type{ enum debug_display_type
KRENGINE_DEBUG_DISPLAY_NONE = 0, {
KRENGINE_DEBUG_DISPLAY_TIME, KRENGINE_DEBUG_DISPLAY_NONE = 0,
KRENGINE_DEBUG_DISPLAY_MEMORY, KRENGINE_DEBUG_DISPLAY_TIME,
KRENGINE_DEBUG_DISPLAY_TEXTURES, KRENGINE_DEBUG_DISPLAY_MEMORY,
KRENGINE_DEBUG_DISPLAY_DRAW_CALLS, KRENGINE_DEBUG_DISPLAY_TEXTURES,
KRENGINE_DEBUG_DISPLAY_OCTREE, KRENGINE_DEBUG_DISPLAY_DRAW_CALLS,
KRENGINE_DEBUG_DISPLAY_COLLIDERS, KRENGINE_DEBUG_DISPLAY_OCTREE,
KRENGINE_DEBUG_DISPLAY_BONES, KRENGINE_DEBUG_DISPLAY_COLLIDERS,
KRENGINE_DEBUG_DISPLAY_SIREN_REVERB_ZONES, KRENGINE_DEBUG_DISPLAY_BONES,
KRENGINE_DEBUG_DISPLAY_SIREN_AMBIENT_ZONES, KRENGINE_DEBUG_DISPLAY_SIREN_REVERB_ZONES,
KRENGINE_DEBUG_DISPLAY_NUMBER KRENGINE_DEBUG_DISPLAY_SIREN_AMBIENT_ZONES,
} debug_display; KRENGINE_DEBUG_DISPLAY_NUMBER
} debug_display;
bool getEnableRealtimeOcclusion();
void setEnableRealtimeOcclusion(bool enable); bool getEnableRealtimeOcclusion();
void setEnableRealtimeOcclusion(bool enable);
bool siren_enable;
bool siren_enable_reverb; bool siren_enable;
bool siren_enable_hrtf; bool siren_enable_reverb;
float siren_reverb_max_length; bool siren_enable_hrtf;
float siren_reverb_max_length;
float max_anisotropy;
float max_anisotropy;
private: private:
float m_lodBias; float m_lodBias;
bool m_enable_realtime_occlusion; bool m_enable_realtime_occlusion;
}; };

View File

@@ -36,131 +36,141 @@
#include "KRResource+blend.h" #include "KRResource+blend.h"
KRScene* KRResource::LoadBlenderScene(KRContext &context, const std::string& path) { KRScene* KRResource::LoadBlenderScene(KRContext& context, const std::string& path)
KRScene *pScene = new KRScene(context, KRResource::GetFileBase(path)); {
KRScene* pScene = new KRScene(context, KRResource::GetFileBase(path));
KRDataBlock data;
KRDataBlock data;
if(data.load(path)) {
//KRBlendFile blend_file = KRBlendFile(pFile); if (data.load(path)) {
} //KRBlendFile blend_file = KRBlendFile(pFile);
}
return pScene;
return pScene;
} }
KRBlendFile::KRBlendFile(const void *pFile) { KRBlendFile::KRBlendFile(const void* pFile)
unsigned char *scan = (unsigned char *)pFile; {
readHeader(scan); unsigned char* scan = (unsigned char*)pFile;
std::string block_code = ""; readHeader(scan);
while(block_code != "ENDB") { std::string block_code = "";
Block b = Block(this, scan); while (block_code != "ENDB") {
block_code = b.getCode(); Block b = Block(this, scan);
m_blocks.push_back(b); block_code = b.getCode();
m_blocks.push_back(b);
printf("Loaded block: %s - %i bytes\n", b.getCode().c_str(), b.getDataSize());
} printf("Loaded block: %s - %i bytes\n", b.getCode().c_str(), b.getDataSize());
}
} }
void KRBlendFile::readHeader(unsigned char *&scan) { void KRBlendFile::readHeader(unsigned char*& scan)
if(strncmp((char *)scan, "BLENDER", 7) != 0) { {
// TODO throw exception if (strncmp((char*)scan, "BLENDER", 7) != 0) {
} // TODO throw exception
scan += 7; }
if(scan[0] == '_' && scan[1] == 'v') { scan += 7;
// 32-bit, little-endian if (scan[0] == '_' && scan[1] == 'v') {
m_file_type = KRBLEND_LITTLEENDIAN_32BIT; // 32-bit, little-endian
} else if(scan[0] == '_' && scan[1] == 'V') { m_file_type = KRBLEND_LITTLEENDIAN_32BIT;
// 32-bit, bit-endian } else if (scan[0] == '_' && scan[1] == 'V') {
m_file_type = KRBLEND_BIGENDIAN_32BIT; // 32-bit, bit-endian
} else if(scan[0] == '-' && scan[1] == 'v') { m_file_type = KRBLEND_BIGENDIAN_32BIT;
// 64-bit, little-endian } else if (scan[0] == '-' && scan[1] == 'v') {
m_file_type = KRBLEND_LITTLEENDIAN_64BIT; // 64-bit, little-endian
} else if(scan[0] == '-' && scan[1] == 'V') { m_file_type = KRBLEND_LITTLEENDIAN_64BIT;
// 64-bit, big-endian } else if (scan[0] == '-' && scan[1] == 'V') {
m_file_type = KRBLEND_BIGENDIAN_64BIT; // 64-bit, big-endian
} else { m_file_type = KRBLEND_BIGENDIAN_64BIT;
// TODO - throw exception } else {
} // TODO - throw exception
scan += 5; // Skip and ignore version }
scan += 5; // Skip and ignore version
} }
__int32_t KRBlendFile::readInt(unsigned char *&scan) { __int32_t KRBlendFile::readInt(unsigned char*& scan)
__int32_t ret = 0; {
// read a 32-bit integer and increment scan __int32_t ret = 0;
// read a 32-bit integer and increment scan
switch (m_file_type) {
case KRBLEND_BIGENDIAN_32BIT: switch (m_file_type) {
case KRBLEND_BIGENDIAN_64BIT: case KRBLEND_BIGENDIAN_32BIT:
ret = (__int32_t)scan[3] + (__int32_t)scan[2] * 0x100 + (__int32_t)scan[1] * 0x10000 + (__int32_t)scan[0] * 0x1000000; case KRBLEND_BIGENDIAN_64BIT:
break; ret = (__int32_t)scan[3] + (__int32_t)scan[2] * 0x100 + (__int32_t)scan[1] * 0x10000 + (__int32_t)scan[0] * 0x1000000;
case KRBLEND_LITTLEENDIAN_32BIT: break;
case KRBLEND_LITTLEENDIAN_64BIT: case KRBLEND_LITTLEENDIAN_32BIT:
ret = (__int32_t)scan[0] + (__int32_t)scan[1] * 0x100 + (__int32_t)scan[2] * 0x10000 + (__int32_t)scan[3] * 0x1000000; case KRBLEND_LITTLEENDIAN_64BIT:
break; ret = (__int32_t)scan[0] + (__int32_t)scan[1] * 0x100 + (__int32_t)scan[2] * 0x10000 + (__int32_t)scan[3] * 0x1000000;
} break;
}
scan += 4;
return ret;
}
__int64_t KRBlendFile::readPointer(unsigned char*& scan)
{
__int64_t ret = 0;
// read a 32-bit integer and increment scan
switch (m_file_type) {
case KRBLEND_BIGENDIAN_32BIT:
ret = scan[3] + scan[2] * 0x100 + scan[1] * 0x10000 + scan[0] * 0x1000000;
scan += 4; scan += 4;
return ret; break;
case KRBLEND_LITTLEENDIAN_32BIT:
ret = scan[0] + scan[1] * 0x100 + scan[2] * 0x10000 + scan[3] * 0x1000000;
scan += 4;
break;
case KRBLEND_BIGENDIAN_64BIT:
ret = scan[7] + scan[6] * 0x100 + scan[5] * 0x10000 + scan[4] * 0x1000000 + scan[3] * 0x100000000 + scan[2] * 0x10000000000 + scan[1] * 0x1000000000000 + scan[0] * 0x100000000000000;
scan += 8;
break;
case KRBLEND_LITTLEENDIAN_64BIT:
ret = scan[0] + scan[1] * 0x100 + scan[2] * 0x10000 + scan[3] * 0x1000000 + scan[4] * 0x100000000 + scan[5] * 0x10000000000 + scan[6] * 0x1000000000000 + scan[7] * 0x100000000000000;
scan += 8;
break;
}
return ret;
} }
__int64_t KRBlendFile::readPointer(unsigned char *&scan) { KRBlendFile::~KRBlendFile()
__int64_t ret = 0; {
// read a 32-bit integer and increment scan
switch (m_file_type) {
case KRBLEND_BIGENDIAN_32BIT:
ret = scan[3] + scan[2] * 0x100 + scan[1] * 0x10000 + scan[0] * 0x1000000;
scan += 4;
break;
case KRBLEND_LITTLEENDIAN_32BIT:
ret = scan[0] + scan[1] * 0x100 + scan[2] * 0x10000 + scan[3] * 0x1000000;
scan += 4;
break;
case KRBLEND_BIGENDIAN_64BIT:
ret = scan[7] + scan[6] * 0x100 + scan[5] * 0x10000 + scan[4] * 0x1000000 + scan[3] * 0x100000000 + scan[2] * 0x10000000000 + scan[1] * 0x1000000000000 + scan[0] * 0x100000000000000;
scan += 8;
break;
case KRBLEND_LITTLEENDIAN_64BIT:
ret = scan[0] + scan[1] * 0x100 + scan[2] * 0x10000 + scan[3] * 0x1000000 + scan[4] * 0x100000000 + scan[5] * 0x10000000000 + scan[6] * 0x1000000000000 + scan[7] * 0x100000000000000;
scan += 8;
break;
}
return ret;
}
KRBlendFile::~KRBlendFile() {
} }
KRBlendFile::Block::Block(KRBlendFile *blendFile, unsigned char *&scan) { KRBlendFile::Block::Block(KRBlendFile* blendFile, unsigned char*& scan)
scan += (__int64_t)scan % 4; // Scan forward until the next 4-byte boundary {
char szBlock[5]; scan += (__int64_t)scan % 4; // Scan forward until the next 4-byte boundary
szBlock[0] = *scan++; char szBlock[5];
szBlock[1] = *scan++; szBlock[0] = *scan++;
szBlock[2] = *scan++; szBlock[1] = *scan++;
szBlock[3] = *scan++; szBlock[2] = *scan++;
szBlock[4] = '\0'; szBlock[3] = *scan++;
m_code = szBlock; szBlock[4] = '\0';
m_dataSize = blendFile->readInt(scan); m_code = szBlock;
m_prev_pointer = blendFile->readPointer(scan); m_dataSize = blendFile->readInt(scan);
m_sdna_index = blendFile->readInt(scan); m_prev_pointer = blendFile->readPointer(scan);
m_structure_count = blendFile->readInt(scan); m_sdna_index = blendFile->readInt(scan);
m_data = scan; m_structure_count = blendFile->readInt(scan);
scan += m_dataSize; m_data = scan;
scan += m_dataSize;
} }
KRBlendFile::Block::~Block() { KRBlendFile::Block::~Block()
{
} }
std::string KRBlendFile::Block::getCode() { std::string KRBlendFile::Block::getCode()
return m_code; {
return m_code;
} }
int KRBlendFile::Block::getDataSize() { int KRBlendFile::Block::getDataSize()
return m_dataSize; {
return m_dataSize;
} }

View File

@@ -31,38 +31,41 @@
#pragma once #pragma once
class KRBlendFile { class KRBlendFile
{
public: public:
KRBlendFile(const void *pFile); KRBlendFile(const void* pFile);
~KRBlendFile(); ~KRBlendFile();
class Block { class Block
public: {
Block(KRBlendFile *blendFile, unsigned char *&scan); public:
~Block(); Block(KRBlendFile* blendFile, unsigned char*& scan);
~Block();
std::string getCode();
int getDataSize(); std::string getCode();
private: int getDataSize();
std::string m_code; private:
__int32_t m_dataSize; std::string m_code;
__int32_t m_sdna_index; __int32_t m_dataSize;
__int32_t m_structure_count; __int32_t m_sdna_index;
__int64_t m_prev_pointer; __int32_t m_structure_count;
unsigned char *m_data; __int64_t m_prev_pointer;
}; unsigned char* m_data;
};
private: private:
enum file_type { enum file_type
KRBLEND_LITTLEENDIAN_32BIT, {
KRBLEND_LITTLEENDIAN_64BIT, KRBLEND_LITTLEENDIAN_32BIT,
KRBLEND_BIGENDIAN_32BIT, KRBLEND_LITTLEENDIAN_64BIT,
KRBLEND_BIGENDIAN_64BIT KRBLEND_BIGENDIAN_32BIT,
} m_file_type; KRBLEND_BIGENDIAN_64BIT
void readHeader(unsigned char *&scan); } m_file_type;
void readHeader(unsigned char*& scan);
__int32_t readInt(unsigned char *&scan);
__int64_t readPointer(unsigned char *&scan); __int32_t readInt(unsigned char*& scan);
__int64_t readPointer(unsigned char*& scan);
std::vector<Block> m_blocks;
std::vector<Block> m_blocks;
}; };

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More