dos2unix crlf conversion and fix warnings

This commit is contained in:
2019-01-11 00:48:33 -08:00
parent d5545ca6b1
commit db02be6232
31 changed files with 11949 additions and 11949 deletions

View File

@@ -1,167 +1,167 @@
// //
// KRAmbientZone.cpp // KRAmbientZone.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-12-06. // Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KRAmbientZone.h" #include "KRAmbientZone.h"
#include "KRContext.h" #include "KRContext.h"
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() { std::string KRAmbientZone::getElementName() {
return "ambient_zone"; return "ambient_zone";
} }
tinyxml2::XMLElement *KRAmbientZone::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRAmbientZone::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("zone", m_zone.c_str()); e->SetAttribute("zone", m_zone.c_str());
e->SetAttribute("sample", m_ambient.c_str()); e->SetAttribute("sample", m_ambient.c_str());
e->SetAttribute("gain", m_ambient_gain); e->SetAttribute("gain", m_ambient_gain);
e->SetAttribute("gradient", m_gradient_distance); e->SetAttribute("gradient", m_gradient_distance);
return e; return e;
} }
void KRAmbientZone::loadXML(tinyxml2::XMLElement *e) void KRAmbientZone::loadXML(tinyxml2::XMLElement *e)
{ {
KRNode::loadXML(e); KRNode::loadXML(e);
m_zone = e->Attribute("zone"); 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) { if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
m_gradient_distance = 0.25f; m_gradient_distance = 0.25f;
} }
m_ambient = e->Attribute("sample"); m_ambient = e->Attribute("sample");
m_ambient_gain = 1.0f; m_ambient_gain = 1.0f;
if(e->QueryFloatAttribute("gain", &m_ambient_gain) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("gain", &m_ambient_gain) != tinyxml2::XML_SUCCESS) {
m_ambient_gain = 1.0f; 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(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) void KRAmbientZone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
{ {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_AMBIENT_ZONES; bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_AMBIENT_ZONES;
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) { if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
Matrix4 sphereModelMatrix = getModelMatrix(); Matrix4 sphereModelMatrix = getModelMatrix();
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
// Enable additive blending // Enable additive blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
// Disable z-buffer write // Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE)); GLDEBUG(glDepthMask(GL_FALSE));
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LEQUAL)); GLDEBUG(glDepthFunc(GL_LEQUAL));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere"); std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
if(sphereModels.size()) { if(sphereModels.size()) {
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) { for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f); sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
} }
} }
// Enable alpha blending // Enable alpha blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
} }
} }
} }
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 // Ambient zones always have a -1, -1, -1 to 1, 1, 1 bounding box
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix()); return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
} }
float KRAmbientZone::getContainment(const Vector3 &pos) float KRAmbientZone::getContainment(const Vector3 &pos)
{ {
AABB bounds = getBounds(); AABB bounds = getBounds();
if(bounds.contains(pos)) { if(bounds.contains(pos)) {
Vector3 size = bounds.size(); Vector3 size = bounds.size();
Vector3 diff = pos - bounds.center(); Vector3 diff = pos - bounds.center();
diff = diff * 2.0f; diff = diff * 2.0f;
diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z); diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z);
float d = diff.magnitude(); float d = diff.magnitude();
if(m_gradient_distance <= 0.0f) { if(m_gradient_distance <= 0.0f) {
// Avoid division by zero // Avoid division by zero
d = d > 1.0f ? 0.0f : 1.0f; d = d > 1.0f ? 0.0f : 1.0f;
} else { } else {
d = (1.0f - d) / m_gradient_distance; d = (1.0f - d) / m_gradient_distance;
d = KRCLAMP(d, 0.0f, 1.0f); d = KRCLAMP(d, 0.0f, 1.0f);
} }
return d; return d;
} else { } else {
return 0.0f; return 0.0f;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,97 +1,97 @@
// //
// KRBone.cpp // KRBone.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-12-06. // Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KRBone.h" #include "KRBone.h"
#include "KRContext.h" #include "KRContext.h"
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() { std::string KRBone::getElementName() {
return "bone"; return "bone";
} }
tinyxml2::XMLElement *KRBone::saveXML( tinyxml2::XMLNode *parent) 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(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) void KRBone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
{ {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_BONES; bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_BONES;
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) { if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
Matrix4 sphereModelMatrix = getModelMatrix(); Matrix4 sphereModelMatrix = getModelMatrix();
// Enable additive blending // Enable additive blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
// Disable z-buffer write // Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE)); GLDEBUG(glDepthMask(GL_FALSE));
// Disable z-buffer test // Disable z-buffer test
GLDEBUG(glDisable(GL_DEPTH_TEST)); GLDEBUG(glDisable(GL_DEPTH_TEST));
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere"); std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
if(sphereModels.size()) { if(sphereModels.size()) {
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) { for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f); sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
} }
} }
} }
// Enable alpha blending // Enable alpha blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LEQUAL)); GLDEBUG(glDepthFunc(GL_LEQUAL));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
} }
} }
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;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,229 +1,229 @@
// //
// KRCollider.cpp // KRCollider.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRCollider.h" #include "KRCollider.h"
#include "KRContext.h" #include "KRContext.h"
#include "KRMesh.h" #include "KRMesh.h"
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_model_name = model_name;
m_layer_mask = layer_mask; m_layer_mask = layer_mask;
m_audio_occlusion = audio_occlusion; m_audio_occlusion = audio_occlusion;
} }
KRCollider::~KRCollider() { KRCollider::~KRCollider() {
} }
std::string KRCollider::getElementName() { std::string KRCollider::getElementName() {
return "collider"; return "collider";
} }
tinyxml2::XMLElement *KRCollider::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRCollider::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("mesh", m_model_name.c_str()); e->SetAttribute("mesh", m_model_name.c_str());
e->SetAttribute("layer_mask", m_layer_mask); e->SetAttribute("layer_mask", m_layer_mask);
e->SetAttribute("audio_occlusion", m_audio_occlusion); e->SetAttribute("audio_occlusion", m_audio_occlusion);
return e; return e;
} }
void KRCollider::loadXML(tinyxml2::XMLElement *e) { void KRCollider::loadXML(tinyxml2::XMLElement *e) {
KRNode::loadXML(e); KRNode::loadXML(e);
m_model_name = e->Attribute("mesh"); m_model_name = e->Attribute("mesh");
m_layer_mask = 65535; m_layer_mask = 65535;
if(e->QueryUnsignedAttribute("layer_mask", &m_layer_mask) != tinyxml2::XML_SUCCESS) { if(e->QueryUnsignedAttribute("layer_mask", &m_layer_mask) != tinyxml2::XML_SUCCESS) {
m_layer_mask = 65535; m_layer_mask = 65535;
} }
m_audio_occlusion = 1.0f; m_audio_occlusion = 1.0f;
if(e->QueryFloatAttribute("audio_occlusion", &m_audio_occlusion) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("audio_occlusion", &m_audio_occlusion) != tinyxml2::XML_SUCCESS) {
m_audio_occlusion = 1.0f; m_audio_occlusion = 1.0f;
} }
} }
void KRCollider::loadModel() { void KRCollider::loadModel() {
if(m_models.size() == 0) { if(m_models.size() == 0) {
m_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 m_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
if(m_models.size() > 0) { if(m_models.size() > 0) {
getScene().notify_sceneGraphModify(this); getScene().notify_sceneGraphModify(this);
} }
} }
} }
AABB KRCollider::getBounds() { AABB KRCollider::getBounds() {
loadModel(); loadModel();
if(m_models.size() > 0) { if(m_models.size() > 0) {
return AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix()); return AABB::Create(m_models[0]->getMinPoint(), m_models[0]->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_models.size()) { if(m_models.size()) {
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_models[0]->lineCast(v0_model_space, v1_model_space, hitinfo_model_space)) { if(m_models[0]->lineCast(v0_model_space, v1_model_space, hitinfo_model_space)) {
Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition()); 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); 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 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_models.size()) { if(m_models.size()) {
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_models[0]->rayCast(v0_model_space, dir_model_space, hitinfo_model_space)) { if(m_models[0]->rayCast(v0_model_space, dir_model_space, hitinfo_model_space)) {
Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition()); 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); 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 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_models.size()) { if(m_models.size()) {
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_models[0]->sphereCast(getModelMatrix(), v0, v1, radius, hitinfo)) { if(m_models[0]->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(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) void KRCollider::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
{ {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_COLLIDERS) { if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_COLLIDERS) {
loadModel(); loadModel();
if(m_models.size()) { if(m_models.size()) {
GL_PUSH_GROUP_MARKER("Debug Overlays"); GL_PUSH_GROUP_MARKER("Debug Overlays");
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
// Enable additive blending // Enable additive blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
// Disable z-buffer write // Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE)); GLDEBUG(glDepthMask(GL_FALSE));
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LEQUAL)); GLDEBUG(glDepthFunc(GL_LEQUAL));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
for(int i=0; i < m_models[0]->getSubmeshCount(); i++) { for(int i=0; i < m_models[0]->getSubmeshCount(); i++) {
m_models[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f); m_models[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
} }
// Enable alpha blending // Enable alpha blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
} }
GL_POP_GROUP_MARKER; GL_POP_GROUP_MARKER;
} }
} }
} }

View File

@@ -1,207 +1,207 @@
// //
// KREngine.h // KREngine.h
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include "KRDSP.h" #include "KRDSP.h"
#ifdef KRDSP_SLOW #ifdef KRDSP_SLOW
#include "KREngine-common.h" #include "KREngine-common.h"
namespace KRDSP { namespace KRDSP {
FFTWorkspace::FFTWorkspace() FFTWorkspace::FFTWorkspace()
{ {
sin_table = nullptr; sin_table = nullptr;
cos_table = nullptr; cos_table = nullptr;
} }
FFTWorkspace::~FFTWorkspace() FFTWorkspace::~FFTWorkspace()
{ {
destroy(); destroy();
} }
void FFTWorkspace::create(size_t length) void FFTWorkspace::create(size_t length)
{ {
size_t size = (length / 2); size_t size = (length / 2);
cos_table = new float[size]; cos_table = new float[size];
sin_table = new float[size]; sin_table = new float[size];
for (int i = 0; i < size / 2; i++) { for (int i = 0; i < size / 2; i++) {
float a = 2.0f * M_PI * i / length; float a = 2.0f * (float)M_PI * i / length;
cos_table[i] = cos(a); cos_table[i] = cos(a);
sin_table[i] = sin(a); sin_table[i] = sin(a);
} }
} }
void FFTWorkspace::destroy() void FFTWorkspace::destroy()
{ {
if (sin_table) { if (sin_table) {
delete sin_table; delete sin_table;
sin_table = nullptr; sin_table = nullptr;
} }
if (cos_table) { if (cos_table) {
delete cos_table; delete cos_table;
cos_table = nullptr; cos_table = nullptr;
} }
} }
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
// Only power-of-two sizes supported // Only power-of-two sizes supported
assert((count & (count - 1)) == 0); assert((count & (count - 1)) == 0);
int levels = 0; unsigned int levels = 0;
while (1 << levels <= count) { while (1 << levels <= count) {
levels++; levels++;
} }
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
size_t j = 0; size_t j = 0;
for (int k = 0; k < levels; k++) { for (int k = 0; k < levels; k++) {
j <<= 1; j <<= 1;
j |= ((i >> k) & 1); j |= ((i >> k) & 1);
} }
if (j > i) { if (j > i) {
float temp = src->realp[i]; float temp = src->realp[i];
src->realp[i] = src->realp[j]; src->realp[i] = src->realp[j];
src->realp[j] = temp; src->realp[j] = temp;
temp = src->imagp[i]; temp = src->imagp[i];
src->imagp[i] = src->imagp[j]; src->imagp[i] = src->imagp[j];
src->imagp[j] = temp; src->imagp[j] = temp;
} }
} }
for (size_t size = 2; size <= count; size *= 2) { for (size_t size = 2; size <= count; size *= 2) {
size_t halfsize = size / 2; size_t halfsize = size / 2;
size_t step = count / size; size_t step = count / size;
for (size_t i = 0; i < count; i += size) { for (size_t i = 0; i < count; i += size) {
for (size_t j = i, k = 0; j < i + halfsize; j++, k += step) { for (size_t j = i, k = 0; j < i + halfsize; j++, k += step) {
float temp_real = src->realp[j + halfsize] * workspace.cos_table[k]; float temp_real = src->realp[j + halfsize] * workspace.cos_table[k];
temp_real += src->imagp[j + halfsize] * workspace.sin_table[k]; temp_real += src->imagp[j + halfsize] * workspace.sin_table[k];
float temp_imag = -src->realp[j + halfsize] * workspace.sin_table[k]; float temp_imag = -src->realp[j + halfsize] * workspace.sin_table[k];
temp_imag += src->imagp[j + halfsize] * workspace.cos_table[k]; temp_imag += src->imagp[j + halfsize] * workspace.cos_table[k];
src->realp[j + halfsize] = src->realp[j] - temp_real; src->realp[j + halfsize] = src->realp[j] - temp_real;
src->imagp[j + halfsize] = src->imagp[j] - temp_imag; src->imagp[j + halfsize] = src->imagp[j] - temp_imag;
src->realp[j] += temp_real; src->realp[j] += temp_real;
src->imagp[j] += temp_imag; src->imagp[j] += temp_imag;
} }
} }
} }
} }
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;
swapped.realp = src->imagp; swapped.realp = src->imagp;
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;
w += destStride; w += destStride;
} }
} }
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++;
r++; r++;
} }
} }
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;
w++; w++;
s += scaleStep; s += scaleStep;
} }
} }
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;
r += buffer2Stride; r += buffer2Stride;
} }
} }
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];
buffer->realp[i] += buffer2->realp[i]; buffer->realp[i] += buffer2->realp[i];
} }
} }
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];
c->imagp[i] = a->realp[i] * b->imagp[i] + a->imagp[i] * b->realp[i]; c->imagp[i] = a->realp[i] * b->imagp[i] + a->imagp[i] * b->realp[i];
} }
} }
} // namespace KRDSP } // namespace KRDSP
#endif // KRDSP_SLOW #endif // KRDSP_SLOW

View File

@@ -1,135 +1,135 @@
// //
// KRDirectionalLight.cpp // KRDirectionalLight.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-04-05. // Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRDirectionalLight.h" #include "KRDirectionalLight.h"
#include "KRShader.h" #include "KRShader.h"
#include "KRContext.h" #include "KRContext.h"
#include "assert.h" #include "assert.h"
#include "KRStockGeometry.h" #include "KRStockGeometry.h"
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 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; int cShadows = 1;
for(int iShadow=0; iShadow < cShadows; iShadow++) { 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 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 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 min_depth = 0.0f;
float max_depth = 1.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())); 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); 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); 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 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 matShadowView = Matrix4::LookAt(worldSpacefrustrumSliceBounds.center() - shadowLook, worldSpacefrustrumSliceBounds.center(), shadowUp);
Matrix4 matShadowProjection = Matrix4(); Matrix4 matShadowProjection = Matrix4();
AABB shadowSpaceFrustrumSliceBounds = AABB::Create(worldSpacefrustrumSliceBounds.min, worldSpacefrustrumSliceBounds.max, Matrix4::Invert(matShadowProjection)); AABB shadowSpaceFrustrumSliceBounds = AABB::Create(worldSpacefrustrumSliceBounds.min, worldSpacefrustrumSliceBounds.max, Matrix4::Invert(matShadowProjection));
AABB shadowSpaceSceneBounds = AABB::Create(getScene().getRootOctreeBounds().min, getScene().getRootOctreeBounds().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 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); matShadowProjection.scale(1.0f / shadowSpaceFrustrumSliceBounds.size().x, 1.0f / shadowSpaceFrustrumSliceBounds.size().y, 1.0f / shadowSpaceFrustrumSliceBounds.size().z);
Matrix4 matBias; Matrix4 matBias;
matBias.bias(); matBias.bias();
matShadowProjection *= matBias; matShadowProjection *= matBias;
KRViewport newShadowViewport = KRViewport(Vector2::Create(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection); 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 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())); AABB minimumShadowBounds = AABB::Create(-Vector3::One(), Vector3::One(), Matrix4::Invert(newShadowViewport.getViewProjectionMatrix()));
minimumShadowBounds.scale(1.0f / KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE); 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 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; m_shadowViewports[iShadow] = newShadowViewport;
shadowValid[iShadow] = false; shadowValid[iShadow] = false;
fprintf(stderr, "Kraken - Generate shadow maps...\n"); fprintf(stderr, "Kraken - Generate shadow maps...\n");
} }
} }
return 1; return 1;
} }
void KRDirectionalLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { void KRDirectionalLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) { if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) {
// Lights are rendered on the second pass of the deferred renderer // Lights are rendered on the second pass of the deferred renderer
std::vector<KRDirectionalLight *> this_light; std::vector<KRDirectionalLight *> this_light;
this_light.push_back(this); this_light.push_back(this);
Matrix4 matModelViewInverseTranspose = viewport.getViewMatrix() * getModelMatrix(); Matrix4 matModelViewInverseTranspose = viewport.getViewMatrix() * getModelMatrix();
matModelViewInverseTranspose.transpose(); matModelViewInverseTranspose.transpose();
matModelViewInverseTranspose.invert(); matModelViewInverseTranspose.invert();
Vector3 light_direction_view_space = getWorldLightDirection(); Vector3 light_direction_view_space = getWorldLightDirection();
light_direction_view_space = Matrix4::Dot(matModelViewInverseTranspose, light_direction_view_space); light_direction_view_space = Matrix4::Dot(matModelViewInverseTranspose, light_direction_view_space);
light_direction_view_space.normalize(); light_direction_view_space.normalize();
KRShader *pShader = getContext().getShaderManager()->getShader("light_directional", pCamera, std::vector<KRPointLight *>(), this_light, std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRShader *pShader = getContext().getShaderManager()->getShader("light_directional", pCamera, std::vector<KRPointLight *>(), this_light, std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), std::vector<KRPointLight *>(), this_light, std::vector<KRSpotLight *>(), 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), std::vector<KRPointLight *>(), this_light, std::vector<KRSpotLight *>(), 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_DIRECTION_VIEW_SPACE, light_direction_view_space); pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_DIRECTION_VIEW_SPACE, light_direction_view_space);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color); pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f); pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f);
// Disable z-buffer write // Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE)); GLDEBUG(glDepthMask(GL_FALSE));
// Disable z-buffer test // Disable z-buffer test
GLDEBUG(glDisable(GL_DEPTH_TEST)); GLDEBUG(glDisable(GL_DEPTH_TEST));
// Render a full screen quad // Render a full screen quad
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f); m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
} }
} }
} }
AABB KRDirectionalLight::getBounds() AABB KRDirectionalLight::getBounds()
{ {
return AABB::Infinite(); return AABB::Infinite();
} }

View File

@@ -1,173 +1,173 @@
// //
// KRLODGroup.cpp // KRLODGroup.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-12-06. // Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KRLODGroup.h" #include "KRLODGroup.h"
#include "KRLODSet.h" #include "KRLODSet.h"
#include "KRContext.h" #include "KRContext.h"
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() { std::string KRLODGroup::getElementName() {
return "lod_group"; return "lod_group";
} }
tinyxml2::XMLElement *KRLODGroup::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRLODGroup::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("min_distance", m_min_distance); e->SetAttribute("min_distance", m_min_distance);
e->SetAttribute("max_distance", m_max_distance); e->SetAttribute("max_distance", m_max_distance);
e->SetAttribute("reference_min_x", m_reference.min.x); e->SetAttribute("reference_min_x", m_reference.min.x);
e->SetAttribute("reference_min_y", m_reference.min.y); e->SetAttribute("reference_min_y", m_reference.min.y);
e->SetAttribute("reference_min_z", m_reference.min.z); e->SetAttribute("reference_min_z", m_reference.min.z);
e->SetAttribute("reference_max_x", m_reference.max.x); e->SetAttribute("reference_max_x", m_reference.max.x);
e->SetAttribute("reference_max_y", m_reference.max.y); e->SetAttribute("reference_max_y", m_reference.max.y);
e->SetAttribute("reference_max_z", m_reference.max.z); e->SetAttribute("reference_max_z", m_reference.max.z);
e->SetAttribute("use_world_units", m_use_world_units ? "true" : "false"); e->SetAttribute("use_world_units", m_use_world_units ? "true" : "false");
return e; return e;
} }
void KRLODGroup::loadXML(tinyxml2::XMLElement *e) void KRLODGroup::loadXML(tinyxml2::XMLElement *e)
{ {
KRNode::loadXML(e); KRNode::loadXML(e);
m_min_distance = 0.0f; m_min_distance = 0.0f;
if(e->QueryFloatAttribute("min_distance", &m_min_distance) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("min_distance", &m_min_distance) != tinyxml2::XML_SUCCESS) {
m_min_distance = 0.0f; m_min_distance = 0.0f;
} }
m_max_distance = 0.0f; m_max_distance = 0.0f;
if(e->QueryFloatAttribute("max_distance", &m_max_distance) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("max_distance", &m_max_distance) != tinyxml2::XML_SUCCESS) {
m_max_distance = 0.0f; m_max_distance = 0.0f;
} }
float x=0.0f, y=0.0f, z=0.0f; float x=0.0f, y=0.0f, z=0.0f;
if(e->QueryFloatAttribute("reference_min_x", &x) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("reference_min_x", &x) != tinyxml2::XML_SUCCESS) {
x = 0.0f; x = 0.0f;
} }
if(e->QueryFloatAttribute("reference_min_y", &y) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("reference_min_y", &y) != tinyxml2::XML_SUCCESS) {
y = 0.0f; y = 0.0f;
} }
if(e->QueryFloatAttribute("reference_min_z", &z) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("reference_min_z", &z) != tinyxml2::XML_SUCCESS) {
z = 0.0f; 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; x=0.0f; y=0.0f; z=0.0f;
if(e->QueryFloatAttribute("reference_max_x", &x) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("reference_max_x", &x) != tinyxml2::XML_SUCCESS) {
x = 0.0f; x = 0.0f;
} }
if(e->QueryFloatAttribute("reference_max_y", &y) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("reference_max_y", &y) != tinyxml2::XML_SUCCESS) {
y = 0.0f; y = 0.0f;
} }
if(e->QueryFloatAttribute("reference_max_z", &z) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("reference_max_z", &z) != tinyxml2::XML_SUCCESS) {
z = 0.0f; z = 0.0f;
} }
m_reference.max = Vector3::Create(x,y,z); m_reference.max = Vector3::Create(x,y,z);
m_use_world_units = true; m_use_world_units = true;
if(e->QueryBoolAttribute("use_world_units", &m_use_world_units) != tinyxml2::XML_SUCCESS) { if(e->QueryBoolAttribute("use_world_units", &m_use_world_units) != tinyxml2::XML_SUCCESS) {
m_use_world_units = true; 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 { } else {
float lod_bias = viewport.getLODBias(); float lod_bias = viewport.getLODBias();
lod_bias = pow(2.0f, -lod_bias); lod_bias = pow(2.0f, -lod_bias);
// Compare using squared distances as sqrt is expensive // Compare using squared distances as sqrt is expensive
float sqr_distance; float sqr_distance;
float sqr_prestream_distance; float sqr_prestream_distance;
Vector3 world_camera_position = viewport.getCameraPosition(); Vector3 world_camera_position = viewport.getCameraPosition();
Vector3 local_camera_position = worldToLocal(world_camera_position); Vector3 local_camera_position = worldToLocal(world_camera_position);
Vector3 local_reference_point = m_reference.nearestPoint(local_camera_position); Vector3 local_reference_point = m_reference.nearestPoint(local_camera_position);
if(m_use_world_units) { if(m_use_world_units) {
Vector3 world_reference_point = localToWorld(local_reference_point); Vector3 world_reference_point = localToWorld(local_reference_point);
sqr_distance = (world_camera_position - world_reference_point).sqrMagnitude() * (lod_bias * lod_bias); sqr_distance = (world_camera_position - world_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
sqr_prestream_distance = getContext().KRENGINE_PRESTREAM_DISTANCE * getContext().KRENGINE_PRESTREAM_DISTANCE; sqr_prestream_distance = getContext().KRENGINE_PRESTREAM_DISTANCE * getContext().KRENGINE_PRESTREAM_DISTANCE;
} else { } else {
sqr_distance = (local_camera_position - local_reference_point).sqrMagnitude() * (lod_bias * lod_bias); sqr_distance = (local_camera_position - local_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
Vector3 world_reference_point = localToWorld(local_reference_point); Vector3 world_reference_point = localToWorld(local_reference_point);
sqr_prestream_distance = worldToLocal(Vector3::Normalize(world_reference_point - world_camera_position) * getContext().KRENGINE_PRESTREAM_DISTANCE).sqrMagnitude(); // TODO, FINDME - Optimize with precalc? sqr_prestream_distance = worldToLocal(Vector3::Normalize(world_reference_point - world_camera_position) * getContext().KRENGINE_PRESTREAM_DISTANCE).sqrMagnitude(); // TODO, FINDME - Optimize with precalc?
} }
float sqr_min_visible_distance = m_min_distance * m_min_distance; float sqr_min_visible_distance = m_min_distance * m_min_distance;
float sqr_max_visible_distance = m_max_distance * m_max_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)) { 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; 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)) { } 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; return LOD_VISIBILITY_PRESTREAM;
} else { } else {
return LOD_VISIBILITY_HIDDEN; 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

@@ -1,485 +1,485 @@
// //
// KRLight.cpp // KRLight.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-04-05. // Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRLight.h" #include "KRLight.h"
#include "KRNode.h" #include "KRNode.h"
#include "KRCamera.h" #include "KRCamera.h"
#include "KRContext.h" #include "KRContext.h"
#include "KRShaderManager.h" #include "KRShaderManager.h"
#include "KRShader.h" #include "KRShader.h"
#include "KRStockGeometry.h" #include "KRStockGeometry.h"
#include "KRDirectionalLight.h" #include "KRDirectionalLight.h"
#include "KRSpotLight.h" #include "KRSpotLight.h"
#include "KRPointLight.h" #include "KRPointLight.h"
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_occlusionQuery = 0; m_occlusionQuery = 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); KRNode::loadXML(e);
float x=1.0f,y=1.0f,z=1.0f; float x=1.0f,y=1.0f,z=1.0f;
if(e->QueryFloatAttribute("color_r", &x) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("color_r", &x) != tinyxml2::XML_SUCCESS) {
x = 1.0; x = 1.0;
} }
if(e->QueryFloatAttribute("color_g", &y) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("color_g", &y) != tinyxml2::XML_SUCCESS) {
y = 1.0; y = 1.0;
} }
if(e->QueryFloatAttribute("color_b", &z) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("color_b", &z) != tinyxml2::XML_SUCCESS) {
z = 1.0; 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) { if(e->QueryFloatAttribute("intensity", &m_intensity) != tinyxml2::XML_SUCCESS) {
m_intensity = 100.0; m_intensity = 100.0;
} }
if(e->QueryFloatAttribute("decay_start", &m_decayStart) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("decay_start", &m_decayStart) != tinyxml2::XML_SUCCESS) {
m_decayStart = 0.0; m_decayStart = 0.0;
} }
if(e->QueryFloatAttribute("flare_size", &m_flareSize) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("flare_size", &m_flareSize) != tinyxml2::XML_SUCCESS) {
m_flareSize = 0.0; m_flareSize = 0.0;
} }
if(e->QueryFloatAttribute("flare_occlusion_size", &m_flareOcclusionSize) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("flare_occlusion_size", &m_flareOcclusionSize) != tinyxml2::XML_SUCCESS) {
m_flareOcclusionSize = 0.05f; m_flareOcclusionSize = 0.05f;
} }
if(e->QueryBoolAttribute("casts_shadow", &m_casts_shadow) != tinyxml2::XML_SUCCESS) { if(e->QueryBoolAttribute("casts_shadow", &m_casts_shadow) != tinyxml2::XML_SUCCESS) {
m_casts_shadow = true; m_casts_shadow = true;
} }
if(e->QueryBoolAttribute("light_shafts", &m_light_shafts) != tinyxml2::XML_SUCCESS) { if(e->QueryBoolAttribute("light_shafts", &m_light_shafts) != tinyxml2::XML_SUCCESS) {
m_light_shafts = true; m_light_shafts = true;
} }
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) { 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;
} }
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) { 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;
} }
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) { 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;
} }
const char *szFlareTexture = e->Attribute("flare_texture"); const char *szFlareTexture = e->Attribute("flare_texture");
if(szFlareTexture) { if(szFlareTexture) {
m_flareTexture = szFlareTexture; m_flareTexture = szFlareTexture;
} else { } else {
m_flareTexture = ""; 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_flareTexture = flare_texture;
m_pFlareTexture = NULL; 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(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { void KRLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
if(renderPass == KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && (pCamera->settings.volumetric_environment_enable || pCamera->settings.dust_particle_enable || (pCamera->settings.m_cShadowBuffers > 0 && m_casts_shadow))) { if(renderPass == KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && (pCamera->settings.volumetric_environment_enable || pCamera->settings.dust_particle_enable || (pCamera->settings.m_cShadowBuffers > 0 && m_casts_shadow))) {
allocateShadowBuffers(configureShadowBufferViewports(viewport)); allocateShadowBuffers(configureShadowBufferViewports(viewport));
renderShadowBuffers(pCamera); renderShadowBuffers(pCamera);
} }
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES && pCamera->settings.dust_particle_enable) { if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES && pCamera->settings.dust_particle_enable) {
// Render brownian particles for dust floating in air // 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(m_cShadowBuffers >= 1 && shadowValid[0] && m_dust_particle_density > 0.0f && m_dust_particle_size > 0.0f && m_dust_particle_intensity > 0.0f) {
if(viewport.visible(getBounds()) || true) { // FINDME, HACK need to remove "|| true"? if(viewport.visible(getBounds()) || true) { // FINDME, HACK need to remove "|| true"?
float particle_range = 600.0f; float particle_range = 600.0f;
int particle_count = m_dust_particle_density * pow(particle_range, 3); int particle_count = m_dust_particle_density * pow(particle_range, 3);
if(particle_count > KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES) particle_count = KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES; if(particle_count > KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES) particle_count = KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES;
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
Matrix4 particleModelMatrix; Matrix4 particleModelMatrix;
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.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(viewport.getCameraPosition()); particleModelMatrix.translate(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);
} }
KRShader *pParticleShader = m_pContext->getShaderManager()->getShader("dust_particle", pCamera, this_point_light, this_directional_light, this_spot_light, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRShader *pParticleShader = m_pContext->getShaderManager()->getShader("dust_particle", pCamera, this_point_light, this_directional_light, this_spot_light, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pParticleShader, viewport, particleModelMatrix, this_point_light, this_directional_light, this_spot_light, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getShaderManager()->selectShader(*pCamera, pParticleShader, viewport, particleModelMatrix, this_point_light, this_directional_light, this_spot_light, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color * pCamera->settings.dust_particle_intensity * m_dust_particle_intensity * m_intensity); pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color * pCamera->settings.dust_particle_intensity * m_dust_particle_intensity * m_intensity);
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_PARTICLE_ORIGIN, Matrix4::DotWDiv(Matrix4::Invert(particleModelMatrix), Vector3::Zero())); pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_PARTICLE_ORIGIN, Matrix4::DotWDiv(Matrix4::Invert(particleModelMatrix), Vector3::Zero()));
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_dust_particle_size); pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_dust_particle_size);
KRDataBlock particle_index_data; KRDataBlock particle_index_data;
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getRandomParticles(), particle_index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), true, 1.0f); m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getRandomParticles(), particle_index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), true, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3)); GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
} }
} }
} }
} }
if(renderPass == KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && pCamera->settings.volumetric_environment_enable && m_light_shafts) { if(renderPass == KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && pCamera->settings.volumetric_environment_enable && m_light_shafts) {
std::string shader_name = pCamera->settings.volumetric_environment_downsample != 0 ? "volumetric_fog_downsampled" : "volumetric_fog"; std::string shader_name = pCamera->settings.volumetric_environment_downsample != 0 ? "volumetric_fog_downsampled" : "volumetric_fog";
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);
} }
KRShader *pFogShader = m_pContext->getShaderManager()->getShader(shader_name, pCamera, this_point_light, this_directional_light, this_spot_light, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_ADDITIVE_PARTICLES); KRShader *pFogShader = m_pContext->getShaderManager()->getShader(shader_name, pCamera, this_point_light, this_directional_light, this_spot_light, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_ADDITIVE_PARTICLES);
if(getContext().getShaderManager()->selectShader(*pCamera, pFogShader, viewport, Matrix4(), this_point_light, this_directional_light, this_spot_light, 0, KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getShaderManager()->selectShader(*pCamera, pFogShader, viewport, Matrix4(), this_point_light, this_directional_light, this_spot_light, 0, KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE, Vector3::Zero(), 0.0f, Vector4::Zero())) {
int slice_count = (int)(pCamera->settings.volumetric_environment_quality * 495.0) + 5; int slice_count = (int)(pCamera->settings.volumetric_environment_quality * 495.0) + 5;
float slice_near = -pCamera->settings.getPerspectiveNearZ(); float slice_near = -pCamera->settings.getPerspectiveNearZ();
float slice_far = -pCamera->settings.volumetric_environment_max_distance; float slice_far = -pCamera->settings.volumetric_environment_max_distance;
float slice_spacing = (slice_far - slice_near) / slice_count; float slice_spacing = (slice_far - slice_near) / slice_count;
pFogShader->setUniform(KRShader::KRENGINE_UNIFORM_SLICE_DEPTH_SCALE, Vector2::Create(slice_near, slice_spacing)); pFogShader->setUniform(KRShader::KRENGINE_UNIFORM_SLICE_DEPTH_SCALE, Vector2::Create(slice_near, slice_spacing));
pFogShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, (m_color * pCamera->settings.volumetric_environment_intensity * m_intensity * -slice_spacing / 1000.0f)); pFogShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, (m_color * pCamera->settings.volumetric_environment_intensity * m_intensity * -slice_spacing / 1000.0f));
KRDataBlock index_data; KRDataBlock index_data;
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getVolumetricLightingVertexes(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX), true, 1.0f); m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getVolumetricLightingVertexes(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX), true, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, slice_count*6)); GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, slice_count*6));
} }
} }
if(renderPass == KRNode::RENDER_PASS_PARTICLE_OCCLUSION) { if(renderPass == KRNode::RENDER_PASS_PARTICLE_OCCLUSION) {
if(m_flareTexture.size() && m_flareSize > 0.0f) { if(m_flareTexture.size() && m_flareSize > 0.0f) {
Matrix4 occlusion_test_sphere_matrix = Matrix4(); Matrix4 occlusion_test_sphere_matrix = Matrix4();
occlusion_test_sphere_matrix.scale(m_localScale * m_flareOcclusionSize); occlusion_test_sphere_matrix.scale(m_localScale * m_flareOcclusionSize);
occlusion_test_sphere_matrix.translate(m_localTranslation); occlusion_test_sphere_matrix.translate(m_localTranslation);
if(m_parentNode) { if(m_parentNode) {
occlusion_test_sphere_matrix *= m_parentNode->getModelMatrix(); occlusion_test_sphere_matrix *= m_parentNode->getModelMatrix();
} }
if(getContext().getShaderManager()->selectShader("occlusion_test", *pCamera, point_lights, directional_lights, spot_lights, 0, viewport, occlusion_test_sphere_matrix, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getShaderManager()->selectShader("occlusion_test", *pCamera, point_lights, directional_lights, spot_lights, 0, viewport, occlusion_test_sphere_matrix, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
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
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere"); std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
if(sphereModels.size()) { if(sphereModels.size()) {
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) { for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "occlusion_test", 1.0f); sphereModels[0]->renderSubmesh(i, 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(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
if(m_flareTexture.size() && m_flareSize > 0.0f) { if(m_flareTexture.size() && m_flareSize > 0.0f) {
if(m_occlusionQuery) { if(m_occlusionQuery) {
GLuint params = 0; GLuint params = 0;
GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, &params)); GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, &params));
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery)); GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
if(params) { if(params) {
if(!m_pFlareTexture && m_flareTexture.size()) { if(!m_pFlareTexture && m_flareTexture.size()) {
m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture); m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture);
} }
if(m_pFlareTexture) { if(m_pFlareTexture) {
// Disable z-buffer test // Disable z-buffer test
GLDEBUG(glDisable(GL_DEPTH_TEST)); GLDEBUG(glDisable(GL_DEPTH_TEST));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
// Render light flare on transparency pass // Render light flare on transparency pass
KRShader *pShader = getContext().getShaderManager()->getShader("flare", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRShader *pShader = getContext().getShaderManager()->getShader("flare", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, 1.0f); pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, 1.0f);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_flareSize); pShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_flareSize);
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(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f); m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
} }
} }
} }
} }
} }
} }
} }
void KRLight::allocateShadowBuffers(int cBuffers) { void KRLight::allocateShadowBuffers(int cBuffers) {
// First deallocate buffers no longer needed // First deallocate buffers no longer needed
for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) { for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) {
if (shadowDepthTexture[iShadow]) { if (shadowDepthTexture[iShadow]) {
GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow)); GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow));
shadowDepthTexture[iShadow] = 0; shadowDepthTexture[iShadow] = 0;
} }
if (shadowFramebuffer[iShadow]) { if (shadowFramebuffer[iShadow]) {
GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow)); GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow));
shadowFramebuffer[iShadow] = 0; shadowFramebuffer[iShadow] = 0;
} }
} }
// Allocate newly required buffers // Allocate newly required buffers
for(int iShadow = 0; iShadow < cBuffers; iShadow++) { for(int iShadow = 0; iShadow < cBuffers; iShadow++) {
Vector2 viewportSize = m_shadowViewports[iShadow].getSize(); Vector2 viewportSize = m_shadowViewports[iShadow].getSize();
if(!shadowDepthTexture[iShadow]) { if(!shadowDepthTexture[iShadow]) {
shadowValid[iShadow] = false; shadowValid[iShadow] = false;
GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow)); GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow));
GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow)); GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow));
// ===== Create offscreen shadow framebuffer object ===== // ===== Create offscreen shadow framebuffer object =====
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow])); GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
// ----- Create Depth Texture for shadowFramebuffer ----- // ----- Create Depth Texture for shadowFramebuffer -----
GLDEBUG( glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow])); 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_MIN_FILTER, GL_NEAREST));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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()->_setWrapModeS(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
m_pContext->getTextureManager()->_setWrapModeT(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, viewportSize.x, viewportSize.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL)); GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, viewportSize.x, 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(KRCamera *pCamera) void KRLight::renderShadowBuffers(KRCamera *pCamera)
{ {
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(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
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));
GLDEBUG(glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y)); GLDEBUG(glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y));
GLDEBUG(glClearDepthf(0.0f)); GLDEBUG(glClearDepthf(0.0f));
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT)); GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
GLDEBUG(glViewport(1, 1, m_shadowViewports[iShadow].getSize().x - 2, m_shadowViewports[iShadow].getSize().y - 2)); GLDEBUG(glViewport(1, 1, m_shadowViewports[iShadow].getSize().x - 2, m_shadowViewports[iShadow].getSize().y - 2));
GLDEBUG(glClearDepthf(1.0f)); GLDEBUG(glClearDepthf(1.0f));
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT)); GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
GLDEBUG(glDisable(GL_DITHER)); GLDEBUG(glDisable(GL_DITHER));
//GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts //GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts
//GLDEBUG(glEnable(GL_CULL_FACE)); //GLDEBUG(glEnable(GL_CULL_FACE));
GLDEBUG(glDisable(GL_CULL_FACE)); GLDEBUG(glDisable(GL_CULL_FACE));
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LESS)); GLDEBUG(glDepthFunc(GL_LESS));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
// Disable alpha blending as we are using alpha channel for packed depth info // Disable alpha blending as we are using alpha channel for packed depth info
GLDEBUG(glDisable(GL_BLEND)); GLDEBUG(glDisable(GL_BLEND));
// Use shader program // Use shader program
KRShader *shadowShader = m_pContext->getShaderManager()->getShader("ShadowShader", pCamera, std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); KRShader *shadowShader = m_pContext->getShaderManager()->getShader("ShadowShader", pCamera, std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
getContext().getShaderManager()->selectShader(*pCamera, shadowShader, m_shadowViewports[iShadow], Matrix4(), std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, KRNode::RENDER_PASS_SHADOWMAP, Vector3::Zero(), 0.0f, Vector4::Zero()); getContext().getShaderManager()->selectShader(*pCamera, shadowShader, m_shadowViewports[iShadow], Matrix4(), std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, KRNode::RENDER_PASS_SHADOWMAP, Vector3::Zero(), 0.0f, Vector4::Zero());
getScene().render(pCamera, m_shadowViewports[iShadow].getVisibleBounds(), m_shadowViewports[iShadow], KRNode::RENDER_PASS_SHADOWMAP, true); getScene().render(pCamera, m_shadowViewports[iShadow].getVisibleBounds(), m_shadowViewports[iShadow], KRNode::RENDER_PASS_SHADOWMAP, true);
GLDEBUG(glEnable(GL_CULL_FACE)); GLDEBUG(glEnable(GL_CULL_FACE));
} }
} }
} }
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

@@ -1,422 +1,422 @@
// //
// KRMaterial.cpp // KRMaterial.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRMaterial.h" #include "KRMaterial.h"
#include "KRTextureManager.h" #include "KRTextureManager.h"
#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_name = szName;
m_pAmbientMap = NULL; m_pAmbientMap = NULL;
m_pDiffuseMap = NULL; m_pDiffuseMap = NULL;
m_pSpecularMap = NULL; m_pSpecularMap = NULL;
m_pNormalMap = NULL; m_pNormalMap = NULL;
m_pReflectionMap = NULL; m_pReflectionMap = NULL;
m_pReflectionCube = NULL; m_pReflectionCube = NULL;
m_ambientColor = Vector3::Zero(); m_ambientColor = Vector3::Zero();
m_diffuseColor = Vector3::One(); m_diffuseColor = Vector3::One();
m_specularColor = Vector3::One(); m_specularColor = Vector3::One();
m_reflectionColor = Vector3::Zero(); m_reflectionColor = Vector3::Zero();
m_tr = (GLfloat)1.0f; m_tr = (GLfloat)1.0f;
m_ns = (GLfloat)0.0f; m_ns = (GLfloat)0.0f;
m_ambientMap = ""; m_ambientMap = "";
m_diffuseMap = ""; m_diffuseMap = "";
m_specularMap = ""; m_specularMap = "";
m_normalMap = ""; m_normalMap = "";
m_reflectionMap = ""; m_reflectionMap = "";
m_reflectionCube = ""; m_reflectionCube = "";
m_ambientMapOffset = Vector2::Create(0.0f, 0.0f); m_ambientMapOffset = Vector2::Create(0.0f, 0.0f);
m_specularMapOffset = Vector2::Create(0.0f, 0.0f); m_specularMapOffset = Vector2::Create(0.0f, 0.0f);
m_diffuseMapOffset = Vector2::Create(0.0f, 0.0f); m_diffuseMapOffset = Vector2::Create(0.0f, 0.0f);
m_ambientMapScale = Vector2::Create(1.0f, 1.0f); m_ambientMapScale = Vector2::Create(1.0f, 1.0f);
m_specularMapScale = Vector2::Create(1.0f, 1.0f); m_specularMapScale = Vector2::Create(1.0f, 1.0f);
m_diffuseMapScale = Vector2::Create(1.0f, 1.0f); m_diffuseMapScale = Vector2::Create(1.0f, 1.0f);
m_reflectionMapOffset = Vector2::Create(0.0f, 0.0f); m_reflectionMapOffset = Vector2::Create(0.0f, 0.0f);
m_reflectionMapScale = Vector2::Create(1.0f, 1.0f); m_reflectionMapScale = Vector2::Create(1.0f, 1.0f);
m_alpha_mode = KRMATERIAL_ALPHA_MODE_OPAQUE; 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; std::stringstream stream;
stream.precision(std::numeric_limits<long double>::digits10); stream.precision(std::numeric_limits<long double>::digits10);
stream.setf(std::ios::fixed,std::ios::floatfield); stream.setf(std::ios::fixed,std::ios::floatfield);
stream << "newmtl " << m_name; stream << "newmtl " << m_name;
stream << "\nka " << m_ambientColor.x << " " << m_ambientColor.y << " " << m_ambientColor.z; stream << "\nka " << m_ambientColor.x << " " << m_ambientColor.y << " " << m_ambientColor.z;
stream << "\nkd " << m_diffuseColor.x << " " << m_diffuseColor.y << " " << m_diffuseColor.z; stream << "\nkd " << m_diffuseColor.x << " " << m_diffuseColor.y << " " << m_diffuseColor.z;
stream << "\nks " << m_specularColor.x << " " << m_specularColor.y << " " << m_specularColor.z; stream << "\nks " << m_specularColor.x << " " << m_specularColor.y << " " << m_specularColor.z;
stream << "\nkr " << m_reflectionColor.x << " " << m_reflectionColor.y << " " << m_reflectionColor.z; stream << "\nkr " << m_reflectionColor.x << " " << m_reflectionColor.y << " " << m_reflectionColor.z;
stream << "\nTr " << m_tr; stream << "\nTr " << m_tr;
stream << "\nNs " << m_ns; stream << "\nNs " << m_ns;
if(m_ambientMap.size()) { if(m_ambientMap.size()) {
stream << "\nmap_Ka " << m_ambientMap << ".pvr -s " << m_ambientMapScale.x << " " << m_ambientMapScale.y << " -o " << m_ambientMapOffset.x << " " << m_ambientMapOffset.y; stream << "\nmap_Ka " << m_ambientMap << ".pvr -s " << m_ambientMapScale.x << " " << m_ambientMapScale.y << " -o " << m_ambientMapOffset.x << " " << m_ambientMapOffset.y;
} else { } else {
stream << "\n# map_Ka filename.pvr -s 1.0 1.0 -o 0.0 0.0"; stream << "\n# map_Ka filename.pvr -s 1.0 1.0 -o 0.0 0.0";
} }
if(m_diffuseMap.size()) { if(m_diffuseMap.size()) {
stream << "\nmap_Kd " << m_diffuseMap << ".pvr -s " << m_diffuseMapScale.x << " " << m_diffuseMapScale.y << " -o " << m_diffuseMapOffset.x << " " << m_diffuseMapOffset.y; stream << "\nmap_Kd " << m_diffuseMap << ".pvr -s " << m_diffuseMapScale.x << " " << m_diffuseMapScale.y << " -o " << m_diffuseMapOffset.x << " " << m_diffuseMapOffset.y;
} else { } else {
stream << "\n# map_Kd filename.pvr -s 1.0 1.0 -o 0.0 0.0"; stream << "\n# map_Kd filename.pvr -s 1.0 1.0 -o 0.0 0.0";
} }
if(m_specularMap.size()) { 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"; stream << "\nmap_Ks " << m_specularMap << ".pvr -s " << m_specularMapScale.x << " " << m_specularMapScale.y << " -o " << m_specularMapOffset.x << " " << m_specularMapOffset.y << "\n";
} else { } else {
stream << "\n# map_Ks filename.pvr -s 1.0 1.0 -o 0.0 0.0"; stream << "\n# map_Ks filename.pvr -s 1.0 1.0 -o 0.0 0.0";
} }
if(m_normalMap.size()) { if(m_normalMap.size()) {
stream << "\nmap_Normal " << m_normalMap << ".pvr -s " << m_normalMapScale.x << " " << m_normalMapScale.y << " -o " << m_normalMapOffset.x << " " << m_normalMapOffset.y; stream << "\nmap_Normal " << m_normalMap << ".pvr -s " << m_normalMapScale.x << " " << m_normalMapScale.y << " -o " << m_normalMapOffset.x << " " << m_normalMapOffset.y;
} else { } else {
stream << "\n# map_Normal filename.pvr -s 1.0 1.0 -o 0.0 0.0"; stream << "\n# map_Normal filename.pvr -s 1.0 1.0 -o 0.0 0.0";
} }
if(m_reflectionMap.size()) { if(m_reflectionMap.size()) {
stream << "\nmap_Reflection " << m_reflectionMap << ".pvr -s " << m_reflectionMapScale.x << " " << m_reflectionMapScale.y << " -o " << m_reflectionMapOffset.x << " " << m_reflectionMapOffset.y; stream << "\nmap_Reflection " << m_reflectionMap << ".pvr -s " << m_reflectionMapScale.x << " " << m_reflectionMapScale.y << " -o " << m_reflectionMapOffset.x << " " << m_reflectionMapOffset.y;
} else { } else {
stream << "\n# map_Reflection filename.pvr -s 1.0 1.0 -o 0.0 0.0"; stream << "\n# map_Reflection filename.pvr -s 1.0 1.0 -o 0.0 0.0";
} }
if(m_reflectionCube.size()) { if(m_reflectionCube.size()) {
stream << "\nmap_ReflectionCube " << m_reflectionCube << ".pvr"; stream << "\nmap_ReflectionCube " << m_reflectionCube << ".pvr";
} else { } else {
stream << "\n# map_ReflectionCube cubemapname"; stream << "\n# map_ReflectionCube cubemapname";
} }
switch(m_alpha_mode) { switch(m_alpha_mode) {
case KRMATERIAL_ALPHA_MODE_OPAQUE: case KRMATERIAL_ALPHA_MODE_OPAQUE:
stream << "\nalpha_mode opaque"; stream << "\nalpha_mode opaque";
break; break;
case KRMATERIAL_ALPHA_MODE_TEST: case KRMATERIAL_ALPHA_MODE_TEST:
stream << "\nalpha_mode test"; stream << "\nalpha_mode test";
break; break;
case KRMATERIAL_ALPHA_MODE_BLENDONESIDE: case KRMATERIAL_ALPHA_MODE_BLENDONESIDE:
stream << "\nalpha_mode blendoneside"; stream << "\nalpha_mode blendoneside";
break; break;
case KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE: case KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE:
stream << "\nalpha_mode blendtwoside"; stream << "\nalpha_mode blendtwoside";
break; break;
} }
stream << "\n# alpha_mode opaque, test, blendoneside, or blendtwoside"; stream << "\n# alpha_mode opaque, test, blendoneside, or blendtwoside";
stream << "\n"; stream << "\n";
data.append(stream.str()); data.append(stream.str());
return true; 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_ambientMap = texture_name;
m_ambientMapScale = texture_scale; m_ambientMapScale = texture_scale;
m_ambientMapOffset = texture_offset; 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_diffuseMap = texture_name;
m_diffuseMapScale = texture_scale; m_diffuseMapScale = texture_scale;
m_diffuseMapOffset = texture_offset; 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_specularMap = texture_name;
m_specularMapScale = texture_scale; m_specularMapScale = texture_scale;
m_specularMapOffset = texture_offset; 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_normalMap = texture_name;
m_normalMapScale = texture_scale; m_normalMapScale = texture_scale;
m_normalMapOffset = texture_offset; 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_reflectionMap = texture_name;
m_reflectionMapScale = texture_scale; m_reflectionMapScale = texture_scale;
m_reflectionMapOffset = texture_offset; 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(GLfloat a) { void KRMaterial::setTransparency(GLfloat a) {
if(a < 1.0f && m_alpha_mode == KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE) { if(a < 1.0f && m_alpha_mode == KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE) {
setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE); setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
} }
m_tr = a; m_tr = a;
} }
void KRMaterial::setShininess(GLfloat s) { void KRMaterial::setShininess(GLfloat 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(); getTextures();
if(m_pAmbientMap) { if(m_pAmbientMap) {
stream_level = KRMIN(stream_level, m_pAmbientMap->getStreamLevel(KRTexture::TEXTURE_USAGE_AMBIENT_MAP)); stream_level = KRMIN(stream_level, m_pAmbientMap->getStreamLevel(KRTexture::TEXTURE_USAGE_AMBIENT_MAP));
} }
if(m_pDiffuseMap) { if(m_pDiffuseMap) {
stream_level = KRMIN(stream_level, m_pDiffuseMap->getStreamLevel(KRTexture::TEXTURE_USAGE_DIFFUSE_MAP)); stream_level = KRMIN(stream_level, m_pDiffuseMap->getStreamLevel(KRTexture::TEXTURE_USAGE_DIFFUSE_MAP));
} }
if(m_pNormalMap) { if(m_pNormalMap) {
stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(KRTexture::TEXTURE_USAGE_NORMAL_MAP)); stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(KRTexture::TEXTURE_USAGE_NORMAL_MAP));
} }
if(m_pSpecularMap) { if(m_pSpecularMap) {
stream_level = KRMIN(stream_level, m_pSpecularMap->getStreamLevel(KRTexture::TEXTURE_USAGE_SPECULAR_MAP)); stream_level = KRMIN(stream_level, m_pSpecularMap->getStreamLevel(KRTexture::TEXTURE_USAGE_SPECULAR_MAP));
} }
if(m_pReflectionMap) { if(m_pReflectionMap) {
stream_level = KRMIN(stream_level, m_pReflectionMap->getStreamLevel(KRTexture::TEXTURE_USAGE_REFLECTION_MAP)); stream_level = KRMIN(stream_level, m_pReflectionMap->getStreamLevel(KRTexture::TEXTURE_USAGE_REFLECTION_MAP));
} }
if(m_pReflectionCube) { if(m_pReflectionCube) {
stream_level = KRMIN(stream_level, m_pReflectionCube->getStreamLevel(KRTexture::TEXTURE_USAGE_REFECTION_CUBE)); stream_level = KRMIN(stream_level, m_pReflectionCube->getStreamLevel(KRTexture::TEXTURE_USAGE_REFECTION_CUBE));
} }
return stream_level; 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());
} }
} }
bool KRMaterial::bind(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const std::vector<KRBone *> &bones, const std::vector<Matrix4> &bind_poses, const KRViewport &viewport, const Matrix4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const Vector3 &rim_color, float rim_power, float lod_coverage) { bool KRMaterial::bind(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const std::vector<KRBone *> &bones, const std::vector<Matrix4> &bind_poses, const KRViewport &viewport, const Matrix4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const Vector3 &rim_color, float rim_power, float lod_coverage) {
bool bLightMap = pLightMap && pCamera->settings.bEnableLightMap; bool bLightMap = pLightMap && pCamera->settings.bEnableLightMap;
getTextures(); getTextures();
Vector2 default_scale = Vector2::One(); Vector2 default_scale = Vector2::One();
Vector2 default_offset = Vector2::Zero(); Vector2 default_offset = Vector2::Zero();
bool bHasReflection = m_reflectionColor != Vector3::Zero(); bool bHasReflection = m_reflectionColor != Vector3::Zero();
bool bDiffuseMap = m_pDiffuseMap != NULL && pCamera->settings.bEnableDiffuseMap; bool bDiffuseMap = m_pDiffuseMap != NULL && pCamera->settings.bEnableDiffuseMap;
bool bNormalMap = m_pNormalMap != NULL && pCamera->settings.bEnableNormalMap; bool bNormalMap = m_pNormalMap != NULL && pCamera->settings.bEnableNormalMap;
bool bSpecMap = m_pSpecularMap != NULL && pCamera->settings.bEnableSpecMap; bool bSpecMap = m_pSpecularMap != NULL && pCamera->settings.bEnableSpecMap;
bool bReflectionMap = m_pReflectionMap != NULL && pCamera->settings.bEnableReflectionMap && pCamera->settings.bEnableReflection && bHasReflection; bool bReflectionMap = m_pReflectionMap != NULL && pCamera->settings.bEnableReflectionMap && pCamera->settings.bEnableReflection && bHasReflection;
bool bReflectionCubeMap = m_pReflectionCube != NULL && pCamera->settings.bEnableReflection && bHasReflection; bool bReflectionCubeMap = m_pReflectionCube != NULL && pCamera->settings.bEnableReflection && bHasReflection;
bool bAlphaTest = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_TEST) && bDiffuseMap; 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); bool bAlphaBlend = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE) || (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
KRShader *pShader = getContext().getShaderManager()->getShader("ObjectShader", pCamera, point_lights, directional_lights, spot_lights, bones.size(), bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, bLightMap, m_diffuseMapScale != default_scale && bDiffuseMap, m_specularMapScale != default_scale && bSpecMap, m_normalMapScale != default_scale && bNormalMap, m_reflectionMapScale != default_scale && bReflectionMap, m_diffuseMapOffset != default_offset && bDiffuseMap, m_specularMapOffset != default_offset && bSpecMap, m_normalMapOffset != default_offset && bNormalMap, m_reflectionMapOffset != default_offset && bReflectionMap, bAlphaTest, bAlphaBlend, renderPass, rim_power != 0.0f); KRShader *pShader = getContext().getShaderManager()->getShader("ObjectShader", pCamera, point_lights, directional_lights, spot_lights, bones.size(), bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, bLightMap, m_diffuseMapScale != default_scale && bDiffuseMap, m_specularMapScale != default_scale && bSpecMap, m_normalMapScale != default_scale && bNormalMap, m_reflectionMapScale != default_scale && bReflectionMap, m_diffuseMapOffset != default_offset && bDiffuseMap, m_specularMapOffset != default_offset && bSpecMap, m_normalMapOffset != default_offset && bNormalMap, m_reflectionMapOffset != default_offset && bReflectionMap, bAlphaTest, bAlphaBlend, renderPass, rim_power != 0.0f);
Vector4 fade_color; Vector4 fade_color;
if(!getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, matModel, point_lights, directional_lights, spot_lights, 0, renderPass, rim_color, rim_power, fade_color)) { if(!getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, matModel, point_lights, directional_lights, spot_lights, 0, renderPass, rim_color, rim_power, fade_color)) {
return false; return false;
} }
// Bind bones // Bind bones
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) { if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
GLfloat bone_mats[256 * 16]; GLfloat bone_mats[256 * 16];
GLfloat *bone_mat_component = bone_mats; GLfloat *bone_mat_component = bone_mats;
for(int bone_index=0; bone_index < bones.size(); bone_index++) { for(int bone_index=0; bone_index < bones.size(); bone_index++) {
KRBone *bone = bones[bone_index]; KRBone *bone = bones[bone_index];
// Vector3 initialRotation = bone->getInitialLocalRotation(); // Vector3 initialRotation = bone->getInitialLocalRotation();
// Vector3 rotation = bone->getLocalRotation(); // Vector3 rotation = bone->getLocalRotation();
// Vector3 initialTranslation = bone->getInitialLocalTranslation(); // Vector3 initialTranslation = bone->getInitialLocalTranslation();
// Vector3 translation = bone->getLocalTranslation(); // Vector3 translation = bone->getLocalTranslation();
// Vector3 initialScale = bone->getInitialLocalScale(); // Vector3 initialScale = bone->getInitialLocalScale();
// Vector3 scale = bone->getLocalScale(); // 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 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 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); // 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 skin_bone_bind_pose = bind_poses[bone_index];
Matrix4 active_mat = bone->getActivePoseMatrix(); Matrix4 active_mat = bone->getActivePoseMatrix();
Matrix4 inv_bind_mat = bone->getInverseBindPoseMatrix(); Matrix4 inv_bind_mat = bone->getInverseBindPoseMatrix();
Matrix4 inv_bind_mat2 = Matrix4::Invert(bind_poses[bone_index]); Matrix4 inv_bind_mat2 = Matrix4::Invert(bind_poses[bone_index]);
Matrix4 t = (inv_bind_mat * active_mat); Matrix4 t = (inv_bind_mat * active_mat);
Matrix4 t2 = inv_bind_mat2 * bone->getModelMatrix(); Matrix4 t2 = inv_bind_mat2 * bone->getModelMatrix();
for(int i=0; i < 16; i++) { for(int i=0; i < 16; i++) {
*bone_mat_component++ = t[i]; *bone_mat_component++ = t[i];
} }
} }
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) { if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
glUniformMatrix4fv(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS], bones.size(), GL_FALSE, bone_mats); glUniformMatrix4fv(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS], bones.size(), GL_FALSE, bone_mats);
} }
} }
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_AMBIENT, m_ambientColor + pCamera->settings.ambient_intensity); pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_AMBIENT, m_ambientColor + pCamera->settings.ambient_intensity);
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) { if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
// We pre-multiply the light color with the material color in the forward renderer // We pre-multiply the light color with the material color in the forward renderer
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, Vector3::Create(m_diffuseColor.x * pCamera->settings.light_intensity.x, m_diffuseColor.y * pCamera->settings.light_intensity.y, m_diffuseColor.z * pCamera->settings.light_intensity.z)); pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, Vector3::Create(m_diffuseColor.x * pCamera->settings.light_intensity.x, m_diffuseColor.y * pCamera->settings.light_intensity.y, m_diffuseColor.z * pCamera->settings.light_intensity.z));
} else { } else {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, m_diffuseColor); pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, m_diffuseColor);
} }
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) { if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
// We pre-multiply the light color with the material color in the forward renderer // We pre-multiply the light color with the material color in the forward renderer
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SPECULAR, Vector3::Create(m_specularColor.x * pCamera->settings.light_intensity.x, m_specularColor.y * pCamera->settings.light_intensity.y, m_specularColor.z * pCamera->settings.light_intensity.z)); pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SPECULAR, Vector3::Create(m_specularColor.x * pCamera->settings.light_intensity.x, m_specularColor.y * pCamera->settings.light_intensity.y, m_specularColor.z * pCamera->settings.light_intensity.z));
} else { } else {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SPECULAR, m_specularColor); pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SPECULAR, m_specularColor);
} }
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SHININESS, m_ns); pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SHININESS, m_ns);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_REFLECTION, m_reflectionColor); pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_REFLECTION, m_reflectionColor);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_SCALE, m_diffuseMapScale); pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_SCALE, m_diffuseMapScale);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_SCALE, m_specularMapScale); pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_SCALE, m_specularMapScale);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_SCALE, m_reflectionMapScale); pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_SCALE, m_reflectionMapScale);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_SCALE, m_normalMapScale); pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_SCALE, m_normalMapScale);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_OFFSET, m_diffuseMapOffset); pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_OFFSET, m_diffuseMapOffset);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_OFFSET, m_specularMapOffset); pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_OFFSET, m_specularMapOffset);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_OFFSET, m_reflectionMapOffset); pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_OFFSET, m_reflectionMapOffset);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_OFFSET, m_normalMapOffset); pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_OFFSET, m_normalMapOffset);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_tr); pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_tr);
if(bDiffuseMap) { if(bDiffuseMap) {
m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap, lod_coverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP); m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap, lod_coverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
} }
if(bSpecMap) { if(bSpecMap) {
m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap, lod_coverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP); m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap, lod_coverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
} }
if(bNormalMap) { if(bNormalMap) {
m_pContext->getTextureManager()->selectTexture(2, m_pNormalMap, lod_coverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP); m_pContext->getTextureManager()->selectTexture(2, m_pNormalMap, lod_coverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
} }
if(bReflectionCubeMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) { if(bReflectionCubeMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) {
m_pContext->getTextureManager()->selectTexture(4, m_pReflectionCube, lod_coverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE); m_pContext->getTextureManager()->selectTexture(4, m_pReflectionCube, lod_coverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
} }
if(bReflectionMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) { if(bReflectionMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || 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 // 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); m_pContext->getTextureManager()->selectTexture(7, m_pReflectionMap, lod_coverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
} }
return true; return true;
} }
const std::string &KRMaterial::getName() const const std::string &KRMaterial::getName() const
{ {
return m_name; return m_name;
} }

View File

@@ -1,288 +1,288 @@
// //
// KRMaterialManager.cpp // KRMaterialManager.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRMaterialManager.h" #include "KRMaterialManager.h"
KRMaterialManager::KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRShaderManager *pShaderManager) : KRContextObject(context) KRMaterialManager::KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRShaderManager *pShaderManager) : KRContextObject(context)
{ {
m_pTextureManager = pTextureManager; m_pTextureManager = pTextureManager;
m_pShaderManager = pShaderManager; m_pShaderManager = pShaderManager;
} }
KRMaterialManager::~KRMaterialManager() { KRMaterialManager::~KRMaterialManager() {
} }
unordered_map<std::string, KRMaterial *> &KRMaterialManager::getMaterials() unordered_map<std::string, KRMaterial *> &KRMaterialManager::getMaterials()
{ {
return m_materials; return m_materials;
} }
void KRMaterialManager::configure(bool blend_enable, GLenum blend_src, GLenum blend_dest, bool depth_test_enable, GLenum depth_func, bool depth_write_enable) { void KRMaterialManager::configure(bool blend_enable, GLenum blend_src, GLenum blend_dest, bool depth_test_enable, GLenum depth_func, bool depth_write_enable) {
if(blend_enable) { if(blend_enable) {
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(blend_src, blend_dest)); GLDEBUG(glBlendFunc(blend_src, blend_dest));
} else { } else {
GLDEBUG(glDisable(GL_BLEND)); GLDEBUG(glDisable(GL_BLEND));
} }
if(depth_test_enable) { if(depth_test_enable) {
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(depth_func)); GLDEBUG(glDepthFunc(depth_func));
} else { } else {
GLDEBUG(glDisable(GL_DEPTH_TEST)); GLDEBUG(glDisable(GL_DEPTH_TEST));
} }
if(depth_write_enable) { if(depth_write_enable) {
GLDEBUG(glDepthMask(GL_TRUE)); GLDEBUG(glDepthMask(GL_TRUE));
} else { } else {
GLDEBUG(glDepthMask(GL_FALSE)); GLDEBUG(glDepthMask(GL_FALSE));
} }
} }
KRMaterial *KRMaterialManager::getMaterial(const std::string &name) { KRMaterial *KRMaterialManager::getMaterial(const std::string &name) {
std::string lowerName = name; std::string lowerName = name;
std::transform(lowerName.begin(), lowerName.end(), std::transform(lowerName.begin(), lowerName.end(),
lowerName.begin(), ::tolower); lowerName.begin(), ::tolower);
unordered_map<std::string, KRMaterial *>::iterator itr = m_materials.find(lowerName); unordered_map<std::string, KRMaterial *>::iterator itr = m_materials.find(lowerName);
if(itr == m_materials.end()) { if(itr == m_materials.end()) {
KRContext::Log(KRContext::LOG_LEVEL_WARNING, "Material not found: %s", name.c_str()); KRContext::Log(KRContext::LOG_LEVEL_WARNING, "Material not found: %s", name.c_str());
// Not found // Not found
return NULL; return NULL;
} else { } else {
return (*itr).second; return (*itr).second;
} }
} }
void KRMaterialManager::add(KRMaterial *new_material) { void KRMaterialManager::add(KRMaterial *new_material) {
// FINDME, TODO - Potential memory leak if multiple materials with the same name are added // FINDME, TODO - Potential memory leak if multiple materials with the same name are added
std::string lowerName = new_material->getName(); std::string lowerName = new_material->getName();
std::transform(lowerName.begin(), lowerName.end(), std::transform(lowerName.begin(), lowerName.end(),
lowerName.begin(), ::tolower); lowerName.begin(), ::tolower);
m_materials[lowerName] = new_material; m_materials[lowerName] = new_material;
} }
bool KRMaterialManager::load(const char *szName, KRDataBlock *data) { bool KRMaterialManager::load(const char *szName, KRDataBlock *data) {
KRMaterial *pMaterial = NULL; KRMaterial *pMaterial = NULL;
char szSymbol[16][256]; char szSymbol[16][256];
data->lock(); data->lock();
char *pScan = (char *)data->getStart(); char *pScan = (char *)data->getStart();
char *pEnd = (char *)data->getEnd(); char *pEnd = (char *)data->getEnd();
while(pScan < pEnd) { while(pScan < pEnd) {
// Scan through whitespace // Scan through whitespace
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) { while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
pScan++; pScan++;
} }
if(*pScan == '#') { if(*pScan == '#') {
// Line is a comment line // Line is a comment line
// Scan to the end of the line // Scan to the end of the line
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') { while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
pScan++; pScan++;
} }
} else { } else {
int cSymbols = 0; int cSymbols = 0;
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') { while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
char *pDest = szSymbol[cSymbols++]; char *pDest = szSymbol[cSymbols++];
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') { while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
if(*pScan >= 'A' && *pScan <= 'Z') { if(*pScan >= 'A' && *pScan <= 'Z') {
*pDest++ = *pScan++ + 'a' - 'A'; // convert to lower case for case sensitve comparison later *pDest++ = *pScan++ + 'a' - 'A'; // convert to lower case for case sensitve comparison later
} else { } else {
*pDest++ = *pScan++; *pDest++ = *pScan++;
} }
} }
*pDest = '\0'; *pDest = '\0';
// Scan through whitespace, but don't advance to next line // Scan through whitespace, but don't advance to next line
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) { while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
pScan++; pScan++;
} }
} }
if(cSymbols > 0) { if(cSymbols > 0) {
if(strcmp(szSymbol[0], "newmtl") == 0 && cSymbols >= 2) { if(strcmp(szSymbol[0], "newmtl") == 0 && cSymbols >= 2) {
pMaterial = new KRMaterial(*m_pContext, szSymbol[1]); pMaterial = new KRMaterial(*m_pContext, szSymbol[1]);
m_materials[szSymbol[1]] = pMaterial; m_materials[szSymbol[1]] = pMaterial;
} }
if(pMaterial != NULL) { if(pMaterial != NULL) {
if(strcmp(szSymbol[0], "alpha_mode") == 0) { if(strcmp(szSymbol[0], "alpha_mode") == 0) {
if(cSymbols == 2) { if(cSymbols == 2) {
if(strcmp(szSymbol[1], "test") == 0) { if(strcmp(szSymbol[1], "test") == 0) {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_TEST); pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_TEST);
} else if(strcmp(szSymbol[1], "blendoneside") == 0) { } else if(strcmp(szSymbol[1], "blendoneside") == 0) {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE); pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
} else if(strcmp(szSymbol[1], "blendtwoside") == 0) { } else if(strcmp(szSymbol[1], "blendtwoside") == 0) {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE); pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
} else { } else {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE); pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE);
} }
} }
} else if(strcmp(szSymbol[0], "ka") == 0) { } else if(strcmp(szSymbol[0], "ka") == 0) {
char *pScan2 = szSymbol[1]; char *pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2); float r = strtof(pScan2, &pScan2);
if(cSymbols == 2) { if(cSymbols == 2) {
pMaterial->setAmbient(Vector3::Create(r, r, r)); pMaterial->setAmbient(Vector3::Create(r, r, r));
} else if(cSymbols == 4) { } else if(cSymbols == 4) {
pScan2 = szSymbol[2]; pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2); float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3]; pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2); float b = strtof(pScan2, &pScan2);
pMaterial->setAmbient(Vector3::Create(r, g, b)); pMaterial->setAmbient(Vector3::Create(r, g, b));
} }
} else if(strcmp(szSymbol[0], "kd") == 0) { } else if(strcmp(szSymbol[0], "kd") == 0) {
char *pScan2 = szSymbol[1]; char *pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2); float r = strtof(pScan2, &pScan2);
if(cSymbols == 2) { if(cSymbols == 2) {
pMaterial->setDiffuse(Vector3::Create(r, r, r)); pMaterial->setDiffuse(Vector3::Create(r, r, r));
} else if(cSymbols == 4) { } else if(cSymbols == 4) {
pScan2 = szSymbol[2]; pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2); float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3]; pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2); float b = strtof(pScan2, &pScan2);
pMaterial->setDiffuse(Vector3::Create(r, g, b)); pMaterial->setDiffuse(Vector3::Create(r, g, b));
} }
} else if(strcmp(szSymbol[0], "ks") == 0) { } else if(strcmp(szSymbol[0], "ks") == 0) {
char *pScan2 = szSymbol[1]; char *pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2); float r = strtof(pScan2, &pScan2);
if(cSymbols == 2) { if(cSymbols == 2) {
pMaterial->setSpecular(Vector3::Create(r, r, r)); pMaterial->setSpecular(Vector3::Create(r, r, r));
} else if(cSymbols == 4) { } else if(cSymbols == 4) {
pScan2 = szSymbol[2]; pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2); float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3]; pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2); float b = strtof(pScan2, &pScan2);
pMaterial->setSpecular(Vector3::Create(r, g, b)); pMaterial->setSpecular(Vector3::Create(r, g, b));
} }
} else if(strcmp(szSymbol[0], "kr") == 0) { } else if(strcmp(szSymbol[0], "kr") == 0) {
char *pScan2 = szSymbol[1]; char *pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2); float r = strtof(pScan2, &pScan2);
if(cSymbols == 2) { if(cSymbols == 2) {
pMaterial->setReflection(Vector3::Create(r, r, r)); pMaterial->setReflection(Vector3::Create(r, r, r));
} else if(cSymbols == 4) { } else if(cSymbols == 4) {
pScan2 = szSymbol[2]; pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2); float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3]; pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2); float b = strtof(pScan2, &pScan2);
pMaterial->setReflection(Vector3::Create(r, g, b)); pMaterial->setReflection(Vector3::Create(r, g, b));
} }
} else if(strcmp(szSymbol[0], "tr") == 0) { } else if(strcmp(szSymbol[0], "tr") == 0) {
char *pScan2 = szSymbol[1]; char *pScan2 = szSymbol[1];
float a = strtof(pScan2, &pScan2); float a = strtof(pScan2, &pScan2);
pMaterial->setTransparency(a); pMaterial->setTransparency(a);
} else if(strcmp(szSymbol[0], "ns") == 0) { } else if(strcmp(szSymbol[0], "ns") == 0) {
char *pScan2 = szSymbol[1]; char *pScan2 = szSymbol[1];
float a = strtof(pScan2, &pScan2); float a = strtof(pScan2, &pScan2);
pMaterial->setShininess(a); pMaterial->setShininess(a);
} else if(strncmp(szSymbol[0], "map", 3) == 0) { } else if(strncmp(szSymbol[0], "map", 3) == 0) {
// Truncate file extension // Truncate file extension
char *pScan2 = szSymbol[1]; char *pScan2 = szSymbol[1];
char *pLastPeriod = NULL; char *pLastPeriod = NULL;
while(*pScan2 != '\0') { while(*pScan2 != '\0') {
if(*pScan2 == '.') { if(*pScan2 == '.') {
pLastPeriod = pScan2; pLastPeriod = pScan2;
} }
pScan2++; pScan2++;
} }
if(pLastPeriod) { if(pLastPeriod) {
*pLastPeriod = '\0'; *pLastPeriod = '\0';
} }
Vector2 texture_scale = Vector2::Create(1.0f, 1.0f); Vector2 texture_scale = Vector2::Create(1.0f, 1.0f);
Vector2 texture_offset = Vector2::Create(0.0f, 0.0f); Vector2 texture_offset = Vector2::Create(0.0f, 0.0f);
int iScanSymbol = 2; int iScanSymbol = 2;
int iScaleParam = -1; int iScaleParam = -1;
int iOffsetParam = -1; int iOffsetParam = -1;
while(iScanSymbol < cSymbols) { while(iScanSymbol < cSymbols) {
if(strcmp(szSymbol[iScanSymbol], "-s") == 0) { if(strcmp(szSymbol[iScanSymbol], "-s") == 0) {
// Scale // Scale
iScaleParam = 0; iScaleParam = 0;
iOffsetParam = -1; iOffsetParam = -1;
} else if(strcmp(szSymbol[iScanSymbol], "-o") == 0) { } else if(strcmp(szSymbol[iScanSymbol], "-o") == 0) {
// Offset // Offset
iOffsetParam = 0; iOffsetParam = 0;
iScaleParam = -1; iScaleParam = -1;
} else { } else {
char *pScan3 = szSymbol[iScanSymbol]; char *pScan3 = szSymbol[iScanSymbol];
float v = strtof(pScan3, &pScan3); float v = strtof(pScan3, &pScan3);
if(iScaleParam == 0) { if(iScaleParam == 0) {
texture_scale.x = v; texture_scale.x = v;
iScaleParam++; iScaleParam++;
} else if(iScaleParam == 1) { } else if(iScaleParam == 1) {
texture_scale.y = v; texture_scale.y = v;
iScaleParam++; iScaleParam++;
} else if(iOffsetParam == 0) { } else if(iOffsetParam == 0) {
texture_offset.x = v; texture_offset.x = v;
iOffsetParam++; iOffsetParam++;
} else if(iOffsetParam == 1) { } else if(iOffsetParam == 1) {
texture_offset.y = v; texture_offset.y = v;
iOffsetParam++; iOffsetParam++;
} }
} }
iScanSymbol++; iScanSymbol++;
} }
if(strcmp(szSymbol[0], "map_ka") == 0) { if(strcmp(szSymbol[0], "map_ka") == 0) {
pMaterial->setAmbientMap(szSymbol[1], texture_scale, texture_offset); pMaterial->setAmbientMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_kd") == 0) { } else if(strcmp(szSymbol[0], "map_kd") == 0) {
pMaterial->setDiffuseMap(szSymbol[1], texture_scale, texture_offset); pMaterial->setDiffuseMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_ks") == 0) { } else if(strcmp(szSymbol[0], "map_ks") == 0) {
pMaterial->setSpecularMap(szSymbol[1], texture_scale, texture_offset); pMaterial->setSpecularMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_normal") == 0) { } else if(strcmp(szSymbol[0], "map_normal") == 0) {
pMaterial->setNormalMap(szSymbol[1], texture_scale, texture_offset); pMaterial->setNormalMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_reflection") == 0) { } else if(strcmp(szSymbol[0], "map_reflection") == 0) {
pMaterial->setReflectionMap(szSymbol[1], texture_scale, texture_offset); pMaterial->setReflectionMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_reflectioncube") == 0) { } else if(strcmp(szSymbol[0], "map_reflectioncube") == 0) {
pMaterial->setReflectionCube(szSymbol[1]); pMaterial->setReflectionCube(szSymbol[1]);
} }
} }
} }
} }
} }
} }
data->unlock(); data->unlock();
delete data; delete data;
return true; return true;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,69 +1,69 @@
// //
// KRMeshCube.cpp // KRMeshCube.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#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; 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.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_starts.push_back(0);
mi.submesh_lengths.push_back(mi.vertices.size()); mi.submesh_lengths.push_back(mi.vertices.size());
mi.material_names.push_back(""); mi.material_names.push_back("");
mi.format = KRENGINE_MODEL_FORMAT_STRIP; mi.format = KRENGINE_MODEL_FORMAT_STRIP;
LoadData(mi, true, true); LoadData(mi, true, true);
} }
KRMeshCube::~KRMeshCube() KRMeshCube::~KRMeshCube()
{ {
} }

View File

@@ -1,63 +1,63 @@
// //
// KRMeshQuad.cpp // KRMeshQuad.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#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(mi.vertices.size()); mi.submesh_lengths.push_back(mi.vertices.size());
mi.material_names.push_back(""); mi.material_names.push_back("");
mi.format = KRENGINE_MODEL_FORMAT_STRIP; mi.format = KRENGINE_MODEL_FORMAT_STRIP;
LoadData(mi, true, true); LoadData(mi, true, true);
} }
KRMeshQuad::~KRMeshQuad() KRMeshQuad::~KRMeshQuad()
{ {
} }

View File

@@ -1,135 +1,135 @@
// //
// KRMeshSphere.cpp // KRMeshSphere.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#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; KRMesh::mesh_info mi;
// Create a triangular facet approximation to a sphere // Create a triangular facet approximation to a sphere
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/ // Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
int iterations = 3; int iterations = 3;
int facet_count = pow(4, iterations) * 8; int facet_count = pow(4, iterations) * 8;
class Facet3 { class Facet3 {
public: public:
Facet3() { Facet3() {
} }
~Facet3() { ~Facet3() {
} }
Vector3 p1; Vector3 p1;
Vector3 p2; Vector3 p2;
Vector3 p3; Vector3 p3;
}; };
std::vector<Facet3> f = std::vector<Facet3>(facet_count); std::vector<Facet3> f = std::vector<Facet3>(facet_count);
int i,it; int i,it;
float a; float a;
Vector3 p[6] = { Vector3 p[6] = {
Vector3::Create(0,0,1), Vector3::Create(0,0,1),
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::Create(1,1,0), Vector3::Create(1,1,0),
Vector3::Create(-1,1,0) Vector3::Create(-1,1,0)
}; };
Vector3 pa,pb,pc; Vector3 pa,pb,pc;
int nt = 0,ntold; int nt = 0,ntold;
/* Create the level 0 object */ /* Create the level 0 object */
a = 1 / sqrt(2.0); a = 1 / sqrt(2.0);
for (i=0;i<6;i++) { for (i=0;i<6;i++) {
p[i].x *= a; p[i].x *= a;
p[i].y *= a; p[i].y *= a;
} }
f[0].p1 = p[0]; f[0].p2 = p[3]; f[0].p3 = p[4]; 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[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[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[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[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[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[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]; f[7].p1 = p[1]; f[7].p2 = p[3]; f[7].p3 = p[2];
nt = 8; nt = 8;
/* Bisect each edge and move to the surface of a unit sphere */ /* Bisect each edge and move to the surface of a unit sphere */
for (it=0;it<iterations;it++) { for (it=0;it<iterations;it++) {
ntold = nt; ntold = nt;
for (i=0;i<ntold;i++) { for (i=0;i<ntold;i++) {
pa.x = (f[i].p1.x + f[i].p2.x) / 2; pa.x = (f[i].p1.x + f[i].p2.x) / 2;
pa.y = (f[i].p1.y + f[i].p2.y) / 2; pa.y = (f[i].p1.y + f[i].p2.y) / 2;
pa.z = (f[i].p1.z + f[i].p2.z) / 2; pa.z = (f[i].p1.z + f[i].p2.z) / 2;
pb.x = (f[i].p2.x + f[i].p3.x) / 2; pb.x = (f[i].p2.x + f[i].p3.x) / 2;
pb.y = (f[i].p2.y + f[i].p3.y) / 2; pb.y = (f[i].p2.y + f[i].p3.y) / 2;
pb.z = (f[i].p2.z + f[i].p3.z) / 2; pb.z = (f[i].p2.z + f[i].p3.z) / 2;
pc.x = (f[i].p3.x + f[i].p1.x) / 2; pc.x = (f[i].p3.x + f[i].p1.x) / 2;
pc.y = (f[i].p3.y + f[i].p1.y) / 2; pc.y = (f[i].p3.y + f[i].p1.y) / 2;
pc.z = (f[i].p3.z + f[i].p1.z) / 2; pc.z = (f[i].p3.z + f[i].p1.z) / 2;
pa.normalize(); pa.normalize();
pb.normalize(); pb.normalize();
pc.normalize(); pc.normalize();
f[nt].p1 = f[i].p1; f[nt].p2 = pa; f[nt].p3 = pc; nt++; 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 = 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[nt].p1 = pb; f[nt].p2 = f[i].p3; f[nt].p3 = pc; nt++;
f[i].p1 = pa; f[i].p1 = pa;
f[i].p2 = pb; f[i].p2 = pb;
f[i].p3 = pc; f[i].p3 = pc;
} }
} }
for(int facet_index=0; facet_index < facet_count; facet_index++) { for(int facet_index=0; facet_index < facet_count; facet_index++) {
mi.vertices.push_back(f[facet_index].p1); mi.vertices.push_back(f[facet_index].p1);
mi.vertices.push_back(f[facet_index].p2); mi.vertices.push_back(f[facet_index].p2);
mi.vertices.push_back(f[facet_index].p3); mi.vertices.push_back(f[facet_index].p3);
} }
mi.submesh_starts.push_back(0); mi.submesh_starts.push_back(0);
mi.submesh_lengths.push_back(mi.vertices.size()); mi.submesh_lengths.push_back(mi.vertices.size());
mi.material_names.push_back(""); mi.material_names.push_back("");
mi.format = KRENGINE_MODEL_FORMAT_TRIANGLES; mi.format = KRENGINE_MODEL_FORMAT_TRIANGLES;
LoadData(mi, true, true); LoadData(mi, true, true);
} }
KRMeshSphere::~KRMeshSphere() KRMeshSphere::~KRMeshSphere()
{ {
} }

View File

@@ -1,263 +1,263 @@
// //
// KRModel.cpp // KRModel.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRModel.h" #include "KRModel.h"
#include "KRContext.h" #include "KRContext.h"
#include "KRMesh.h" #include "KRMesh.h"
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_lightMap = light_map;
m_pLightMap = NULL; m_pLightMap = NULL;
m_model_name = model_name; m_model_name = model_name;
m_min_lod_coverage = lod_min_coverage; m_min_lod_coverage = lod_min_coverage;
m_receivesShadow = receives_shadow; m_receivesShadow = receives_shadow;
m_faces_camera = faces_camera; m_faces_camera = faces_camera;
m_rim_color = rim_color; m_rim_color = rim_color;
m_rim_power = rim_power; m_rim_power = rim_power;
m_boundsCachedMat.c[0] = -1.0f; m_boundsCachedMat.c[0] = -1.0f;
m_boundsCachedMat.c[1] = -1.0f; m_boundsCachedMat.c[1] = -1.0f;
m_boundsCachedMat.c[2] = -1.0f; m_boundsCachedMat.c[2] = -1.0f;
m_boundsCachedMat.c[3] = -1.0f; m_boundsCachedMat.c[3] = -1.0f;
m_boundsCachedMat.c[4] = -1.0f; m_boundsCachedMat.c[4] = -1.0f;
m_boundsCachedMat.c[5] = -1.0f; m_boundsCachedMat.c[5] = -1.0f;
m_boundsCachedMat.c[6] = -1.0f; m_boundsCachedMat.c[6] = -1.0f;
m_boundsCachedMat.c[7] = -1.0f; m_boundsCachedMat.c[7] = -1.0f;
m_boundsCachedMat.c[8] = -1.0f; m_boundsCachedMat.c[8] = -1.0f;
m_boundsCachedMat.c[9] = -1.0f; m_boundsCachedMat.c[9] = -1.0f;
m_boundsCachedMat.c[10] = -1.0f; m_boundsCachedMat.c[10] = -1.0f;
m_boundsCachedMat.c[11] = -1.0f; m_boundsCachedMat.c[11] = -1.0f;
m_boundsCachedMat.c[12] = -1.0f; m_boundsCachedMat.c[12] = -1.0f;
m_boundsCachedMat.c[13] = -1.0f; m_boundsCachedMat.c[13] = -1.0f;
m_boundsCachedMat.c[14] = -1.0f; m_boundsCachedMat.c[14] = -1.0f;
m_boundsCachedMat.c[15] = -1.0f; m_boundsCachedMat.c[15] = -1.0f;
} }
KRModel::~KRModel() { KRModel::~KRModel() {
} }
std::string KRModel::getElementName() { std::string KRModel::getElementName() {
return "model"; return "model";
} }
tinyxml2::XMLElement *KRModel::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRModel::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("mesh", m_model_name.c_str()); e->SetAttribute("mesh", m_model_name.c_str());
e->SetAttribute("light_map", m_lightMap.c_str()); e->SetAttribute("light_map", m_lightMap.c_str());
e->SetAttribute("lod_min_coverage", m_min_lod_coverage); e->SetAttribute("lod_min_coverage", m_min_lod_coverage);
e->SetAttribute("receives_shadow", m_receivesShadow ? "true" : "false"); e->SetAttribute("receives_shadow", m_receivesShadow ? "true" : "false");
e->SetAttribute("faces_camera", m_faces_camera ? "true" : "false"); e->SetAttribute("faces_camera", m_faces_camera ? "true" : "false");
kraken::setXMLAttribute("rim_color", e, m_rim_color, Vector3::Zero()); kraken::setXMLAttribute("rim_color", e, m_rim_color, Vector3::Zero());
e->SetAttribute("rim_power", m_rim_power); e->SetAttribute("rim_power", m_rim_power);
return e; return e;
} }
void KRModel::setRimColor(const Vector3 &rim_color) void KRModel::setRimColor(const Vector3 &rim_color)
{ {
m_rim_color = 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) { 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 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; unordered_map<KRMesh *, std::vector<KRBone *> > bones;
if(models.size() > 0) { if(models.size() > 0) {
bool all_bones_found = true; bool all_bones_found = true;
for(std::vector<KRMesh *>::iterator model_itr = models.begin(); model_itr != models.end(); model_itr++) { for(std::vector<KRMesh *>::iterator model_itr = models.begin(); model_itr != models.end(); model_itr++) {
KRMesh *model = *model_itr; KRMesh *model = *model_itr;
std::vector<KRBone *> model_bones; std::vector<KRBone *> model_bones;
int bone_count = model->getBoneCount(); int bone_count = model->getBoneCount();
for(int bone_index=0; bone_index < bone_count; bone_index++) { 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))); KRBone *matching_bone = dynamic_cast<KRBone *>(getScene().getRootNode()->find<KRNode>(model->getBoneName(bone_index)));
if(matching_bone) { if(matching_bone) {
model_bones.push_back(matching_bone); model_bones.push_back(matching_bone);
} else { } else {
all_bones_found = false; // Reject when there are any missing bones or multiple matches all_bones_found = false; // Reject when there are any missing bones or multiple matches
} }
} }
bones[model] = model_bones; bones[model] = model_bones;
} }
if(all_bones_found) { if(all_bones_found) {
m_models = models; m_models = models;
m_bones = bones; m_bones = bones;
getScene().notify_sceneGraphModify(this); getScene().notify_sceneGraphModify(this);
} }
invalidateBounds(); invalidateBounds();
} }
} }
} }
void KRModel::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { void KRModel::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) { if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) {
preStream(viewport); preStream(viewport);
} }
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && renderPass != KRNode::RENDER_PASS_PRESTREAM) { if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && renderPass != KRNode::RENDER_PASS_PRESTREAM) {
loadModel(); loadModel();
if(m_models.size() > 0) { if(m_models.size() > 0) {
// Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied // Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied
/* /*
float lod_coverage = 0.0f; float lod_coverage = 0.0f;
if(m_models.size() > 1) { if(m_models.size() > 1) {
lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
} else if(viewport.visible(getBounds())) { } else if(viewport.visible(getBounds())) {
lod_coverage = 1.0f; lod_coverage = 1.0f;
} }
*/ */
float lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling float lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
if(lod_coverage > m_min_lod_coverage) { if(lod_coverage > m_min_lod_coverage) {
// ---===--- Select the best LOD model based on screen coverage ---===--- // ---===--- Select the best LOD model based on screen coverage ---===---
std::vector<KRMesh *>::iterator itr=m_models.begin(); std::vector<KRMesh *>::iterator itr=m_models.begin();
KRMesh *pModel = *itr++; KRMesh *pModel = *itr++;
while(itr != m_models.end()) { while(itr != m_models.end()) {
KRMesh *pLODModel = *itr++; KRMesh *pLODModel = *itr++;
if((float)pLODModel->getLODCoverage() / 100.0f > lod_coverage && pLODModel->getLODCoverage() < pModel->getLODCoverage()) { if((float)pLODModel->getLODCoverage() / 100.0f > lod_coverage && pLODModel->getLODCoverage() < pModel->getLODCoverage()) {
pModel = pLODModel; pModel = pLODModel;
} else { } else {
break; break;
} }
} }
if(m_pLightMap == NULL && m_lightMap.size()) { if(m_pLightMap == NULL && m_lightMap.size()) {
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap); m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
} }
if(m_pLightMap && pCamera->settings.bEnableLightMap && renderPass != RENDER_PASS_SHADOWMAP && renderPass != RENDER_PASS_GENERATE_SHADOWMAPS) { if(m_pLightMap && pCamera->settings.bEnableLightMap && renderPass != RENDER_PASS_SHADOWMAP && renderPass != RENDER_PASS_GENERATE_SHADOWMAPS) {
m_pContext->getTextureManager()->selectTexture(5, m_pLightMap, lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP); m_pContext->getTextureManager()->selectTexture(5, m_pLightMap, lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
} }
Matrix4 matModel = getModelMatrix(); Matrix4 matModel = getModelMatrix();
if(m_faces_camera) { if(m_faces_camera) {
Vector3 model_center = Matrix4::Dot(matModel, Vector3::Zero()); Vector3 model_center = Matrix4::Dot(matModel, Vector3::Zero());
Vector3 camera_pos = viewport.getCameraPosition(); Vector3 camera_pos = viewport.getCameraPosition();
matModel = Quaternion::Create(Vector3::Forward(), Vector3::Normalize(camera_pos - model_center)).rotationMatrix() * matModel; matModel = Quaternion::Create(Vector3::Forward(), Vector3::Normalize(camera_pos - model_center)).rotationMatrix() * matModel;
} }
pModel->render(getName(), pCamera, point_lights, directional_lights, spot_lights, viewport, matModel, m_pLightMap, renderPass, m_bones[pModel], m_rim_color, m_rim_power, lod_coverage); pModel->render(getName(), pCamera, point_lights, directional_lights, spot_lights, viewport, matModel, m_pLightMap, renderPass, m_bones[pModel], m_rim_color, m_rim_power, lod_coverage);
} }
} }
} }
} }
void KRModel::preStream(const KRViewport &viewport) void KRModel::preStream(const KRViewport &viewport)
{ {
loadModel(); loadModel();
float lod_coverage = viewport.coverage(getBounds()); float lod_coverage = viewport.coverage(getBounds());
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) { for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
(*itr)->preStream(lod_coverage); (*itr)->preStream(lod_coverage);
} }
if(m_pLightMap == NULL && m_lightMap.size()) { if(m_pLightMap == NULL && m_lightMap.size()) {
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap); m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
} }
if(m_pLightMap) { if(m_pLightMap) {
m_pLightMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP); m_pLightMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
} }
} }
kraken_stream_level KRModel::getStreamLevel(const KRViewport &viewport) kraken_stream_level KRModel::getStreamLevel(const KRViewport &viewport)
{ {
kraken_stream_level stream_level = KRNode::getStreamLevel(viewport); kraken_stream_level stream_level = KRNode::getStreamLevel(viewport);
loadModel(); loadModel();
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) { for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
stream_level = KRMIN(stream_level, (*itr)->getStreamLevel()); stream_level = KRMIN(stream_level, (*itr)->getStreamLevel());
} }
return stream_level; return stream_level;
} }
AABB KRModel::getBounds() { AABB KRModel::getBounds() {
loadModel(); loadModel();
if(m_models.size() > 0) { if(m_models.size() > 0) {
if(m_faces_camera) { if(m_faces_camera) {
AABB normal_bounds = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix()); AABB normal_bounds = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
float max_dimension = normal_bounds.longest_radius(); float max_dimension = normal_bounds.longest_radius();
return AABB::Create(normal_bounds.center()-Vector3::Create(max_dimension), normal_bounds.center() + Vector3::Create(max_dimension)); return AABB::Create(normal_bounds.center()-Vector3::Create(max_dimension), normal_bounds.center() + Vector3::Create(max_dimension));
} else { } else {
if(!(m_boundsCachedMat == getModelMatrix())) { if(!(m_boundsCachedMat == getModelMatrix())) {
m_boundsCachedMat = getModelMatrix(); m_boundsCachedMat = getModelMatrix();
m_boundsCached = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix()); m_boundsCached = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
} }
return m_boundsCached; return m_boundsCached;
} }
} else { } else {
return AABB::Infinite(); return AABB::Infinite();
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,156 +1,156 @@
// //
// KROctree.cpp // KROctree.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-08-29. // Created by Kearwood Gilbert on 2012-08-29.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "public/kraken.h" #include "public/kraken.h"
#include "KROctree.h" #include "KROctree.h"
#include "KRNode.h" #include "KRNode.h"
#include "KRCollider.h" #include "KRCollider.h"
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 { } else {
// Keep encapsulating the root node until the new root contains the inserted node // Keep encapsulating the root node until the new root contains the inserted node
bool bInsideRoot = false; bool bInsideRoot = false;
while(!bInsideRoot) { while(!bInsideRoot) {
AABB rootBounds = m_pRootNode->getBounds(); AABB rootBounds = m_pRootNode->getBounds();
Vector3 rootSize = rootBounds.size(); Vector3 rootSize = rootBounds.size();
if(nodeBounds.min.x < rootBounds.min.x || nodeBounds.min.y < rootBounds.min.y || nodeBounds.min.z < rootBounds.min.z) { 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); 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) { } 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); m_pRootNode = new KROctreeNode(NULL, AABB::Create(rootBounds.min, rootBounds.max + rootSize), 0, m_pRootNode);
} else { } else {
bInsideRoot = true; 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++) { 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((*itr)->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
} }
if(m_pRootNode) { if(m_pRootNode) {
if(m_pRootNode->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true; 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) {
if(m_pRootNode->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true; 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++) { 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((*itr)->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
} }
if(m_pRootNode) { if(m_pRootNode) {
if(m_pRootNode->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true; if(m_pRootNode->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
} }
return hit_found; return hit_found;
} }

View File

@@ -1,290 +1,290 @@
// //
// KROctreeNode.cpp // KROctreeNode.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-08-29. // Created by Kearwood Gilbert on 2012-08-29.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KROctreeNode.h" #include "KROctreeNode.h"
#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_occlusionQuery = 0;
m_occlusionTested = false; m_occlusionTested = false;
m_activeQuery = 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[i] = NULL;
m_children[iChild] = pChild; m_children[iChild] = pChild;
pChild->m_parent = this; pChild->m_parent = this;
m_occlusionQuery = 0; m_occlusionQuery = 0;
m_occlusionTested = false; m_occlusionTested = false;
m_activeQuery = 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++) { for(int i=0; i<8; i++) {
if(m_children[i]) { if(m_children[i]) {
if(m_children[i]->lineCast(v0, v1, hitinfo, layer_mask)) { if(m_children[i]->lineCast(v0, v1, hitinfo, layer_mask)) {
hit_found = true; hit_found = true;
} }
} }
} }
} }
} }
return hit_found; return hit_found;
} }
bool KROctreeNode::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask) bool KROctreeNode::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
{ {
bool hit_found = false; bool hit_found = false;
if(hitinfo.didHit()) { if(hitinfo.didHit()) {
// 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); // Note: This is purposefully lineCast as opposed to RayCast hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask); // Note: This is purposefully lineCast as opposed to RayCast
} else { } else {
if(getBounds().intersectsRay(v0, dir)) { if(getBounds().intersectsRay(v0, dir)) {
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->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true; if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
} }
} }
for(int i=0; i<8; i++) { for(int i=0; i<8; i++) {
if(m_children[i]) { if(m_children[i]) {
if(m_children[i]->rayCast(v0, dir, hitinfo, layer_mask)) { if(m_children[i]->rayCast(v0, dir, hitinfo, layer_mask)) {
hit_found = true; 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 KROctreeNode::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
{ {
bool hit_found = false; bool hit_found = false;
/* /*
// FINDME, TODO - Adapt this optimization to work with sphereCasts // FINDME, TODO - Adapt this optimization to work with sphereCasts
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 = sphereCast(v0, hitinfo.getPosition(), radius, hitinfo, layer_mask); hit_found = sphereCast(v0, hitinfo.getPosition(), radius, hitinfo, layer_mask);
} else { } 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)); 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)) {" // FINDME, TODO - Investigate AABB - swept sphere intersections or OBB - AABB intersections: "if(getBounds().intersectsSweptSphere(v0, v1, radius)) {"
if(getBounds().intersects(swept_bounds)) { if(getBounds().intersects(swept_bounds)) {
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->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true; if(collider->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
} }
} }
for(int i=0; i<8; i++) { for(int i=0; i<8; i++) {
if(m_children[i]) { if(m_children[i]) {
if(m_children[i]->sphereCast(v0, v1, radius, hitinfo, layer_mask)) { if(m_children[i]->sphereCast(v0, v1, radius, hitinfo, layer_mask)) {
hit_found = true; hit_found = true;
} }
} }
} }
} }
// } // }
return hit_found; return hit_found;
} }

View File

@@ -1,89 +1,89 @@
// //
// KRParticleSystemNewtonian.cpp // KRParticleSystemNewtonian.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-11-02. // Created by Kearwood Gilbert on 2012-11-02.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRParticleSystemNewtonian.h" #include "KRParticleSystemNewtonian.h"
#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(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { void KRParticleSystemNewtonian::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
if(viewport.visible(getBounds())) { if(viewport.visible(getBounds())) {
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
KRTexture *pParticleTexture = m_pContext->getTextureManager()->getTexture("flare"); KRTexture *pParticleTexture = m_pContext->getTextureManager()->getTexture("flare");
m_pContext->getTextureManager()->selectTexture(0, pParticleTexture, 0.0f, KRTexture::TEXTURE_USAGE_PARTICLE); m_pContext->getTextureManager()->selectTexture(0, pParticleTexture, 0.0f, KRTexture::TEXTURE_USAGE_PARTICLE);
int particle_count = 10000; int particle_count = 10000;
KRShader *pParticleShader = m_pContext->getShaderManager()->getShader("dust_particle", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRShader *pParticleShader = m_pContext->getShaderManager()->getShader("dust_particle", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
Vector3 rim_color; Vector4 fade_color; Vector3 rim_color; Vector4 fade_color;
if(getContext().getShaderManager()->selectShader(*pCamera, pParticleShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getShaderManager()->selectShader(*pCamera, pParticleShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, 1.0f); pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, 1.0f);
KRDataBlock index_data; KRDataBlock index_data;
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getRandomParticles(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), false, 1.0f); m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getRandomParticles(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), false, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3)); GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
} }
} }
} }
} }

View File

@@ -1,226 +1,226 @@
// //
// KRPointLight.cpp // KRPointLight.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-04-05. // Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRPointLight.h" #include "KRPointLight.h"
#include "KRCamera.h" #include "KRCamera.h"
#include "KRContext.h" #include "KRContext.h"
#include "KRStockGeometry.h" #include "KRStockGeometry.h"
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); float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
if(influence_radius < m_flareOcclusionSize) { if(influence_radius < m_flareOcclusionSize) {
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(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) void KRPointLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
{ {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
bool bVisualize = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.bShowDeferred; bool bVisualize = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.bShowDeferred;
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS || bVisualize) { if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS || bVisualize) {
// Lights are rendered on the second pass of the deferred renderer // Lights are rendered on the second pass of the deferred renderer
std::vector<KRPointLight *> this_light; std::vector<KRPointLight *> this_light;
this_light.push_back(this); this_light.push_back(this);
Vector3 light_position = getLocalTranslation(); Vector3 light_position = getLocalTranslation();
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE); float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
Matrix4 sphereModelMatrix = Matrix4(); Matrix4 sphereModelMatrix = Matrix4();
sphereModelMatrix.scale(influence_radius); sphereModelMatrix.scale(influence_radius);
sphereModelMatrix.translate(light_position.x, light_position.y, light_position.z); sphereModelMatrix.translate(light_position.x, light_position.y, light_position.z);
if(viewport.visible(getBounds())) { // Cull out any lights not within the view frustrum if(viewport.visible(getBounds())) { // Cull out any lights not within the view frustrum
Vector3 view_light_position = Matrix4::Dot(viewport.getViewMatrix(), light_position); Vector3 view_light_position = Matrix4::Dot(viewport.getViewMatrix(), light_position);
bool bInsideLight = view_light_position.sqrMagnitude() <= (influence_radius + pCamera->settings.getPerspectiveNearZ()) * (influence_radius + pCamera->settings.getPerspectiveNearZ()); bool bInsideLight = view_light_position.sqrMagnitude() <= (influence_radius + pCamera->settings.getPerspectiveNearZ()) * (influence_radius + pCamera->settings.getPerspectiveNearZ());
KRShader *pShader = getContext().getShaderManager()->getShader(bVisualize ? "visualize_overlay" : (bInsideLight ? "light_point_inside" : "light_point"), pCamera, this_light, std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRShader *pShader = getContext().getShaderManager()->getShader(bVisualize ? "visualize_overlay" : (bInsideLight ? "light_point_inside" : "light_point"), pCamera, this_light, std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, this_light, std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, this_light, std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color); pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f); pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_DECAY_START, getDecayStart()); pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_DECAY_START, getDecayStart());
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_CUTOFF, KRLIGHT_MIN_INFLUENCE); pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_CUTOFF, KRLIGHT_MIN_INFLUENCE);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_POSITION, light_position); pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_POSITION, light_position);
if(bVisualize) { if(bVisualize) {
// Enable additive blending // Enable additive blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
} }
// Disable z-buffer write // Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE)); GLDEBUG(glDepthMask(GL_FALSE));
if(bInsideLight) { if(bInsideLight) {
// Disable z-buffer test // Disable z-buffer test
GLDEBUG(glDisable(GL_DEPTH_TEST)); GLDEBUG(glDisable(GL_DEPTH_TEST));
// Render a full screen quad // Render a full screen quad
m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f); m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
} else { } else {
#if GL_OES_vertex_array_object #if GL_OES_vertex_array_object
GLDEBUG(glBindVertexArrayOES(0)); GLDEBUG(glBindVertexArrayOES(0));
#endif #endif
m_pContext->getMeshManager()->configureAttribs(1 << KRMesh::KRENGINE_ATTRIB_VERTEX); m_pContext->getMeshManager()->configureAttribs(1 << KRMesh::KRENGINE_ATTRIB_VERTEX);
// Render sphere of light's influence // Render sphere of light's influence
generateMesh(); generateMesh();
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LEQUAL)); GLDEBUG(glDepthFunc(GL_LEQUAL));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_VERTEX, 3, GL_FLOAT, 0, 0, m_sphereVertices)); GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_VERTEX, 3, GL_FLOAT, 0, 0, m_sphereVertices));
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, m_cVertices)); GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, m_cVertices));
} }
} }
if(bVisualize) { if(bVisualize) {
// Enable alpha blending // Enable alpha blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
} }
} }
} }
} }
void KRPointLight::generateMesh() { void KRPointLight::generateMesh() {
// Create a triangular facet approximation to a sphere // Create a triangular facet approximation to a sphere
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/ // Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
int iterations = 3; int iterations = 3;
int facet_count = pow(4, iterations) * 8; int facet_count = pow(4, iterations) * 8;
if(m_cVertices != facet_count * 3) { if(m_cVertices != facet_count * 3) {
if(m_sphereVertices) { if(m_sphereVertices) {
free(m_sphereVertices); free(m_sphereVertices);
m_sphereVertices = NULL; m_sphereVertices = NULL;
} }
m_cVertices = facet_count * 3; m_cVertices = facet_count * 3;
class Facet3 { class Facet3 {
public: public:
Facet3() { Facet3() {
} }
~Facet3() { ~Facet3() {
} }
Vector3 p1; Vector3 p1;
Vector3 p2; Vector3 p2;
Vector3 p3; Vector3 p3;
}; };
std::vector<Facet3> f = std::vector<Facet3>(facet_count); std::vector<Facet3> f = std::vector<Facet3>(facet_count);
int i,it; int i,it;
float a; float a;
Vector3 p[6] = { Vector3 p[6] = {
Vector3::Create(0,0,1), Vector3::Create(0,0,1),
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::Create(1,1,0), Vector3::Create(1,1,0),
Vector3::Create(-1,1,0) Vector3::Create(-1,1,0)
}; };
Vector3 pa,pb,pc; Vector3 pa,pb,pc;
int nt = 0,ntold; int nt = 0,ntold;
/* Create the level 0 object */ /* Create the level 0 object */
a = 1.0f / sqrtf(2.0f); a = 1.0f / sqrtf(2.0f);
for (i=0;i<6;i++) { for (i=0;i<6;i++) {
p[i].x *= a; p[i].x *= a;
p[i].y *= a; p[i].y *= a;
} }
f[0].p1 = p[0]; f[0].p2 = p[3]; f[0].p3 = p[4]; 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[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[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[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[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[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[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]; f[7].p1 = p[1]; f[7].p2 = p[3]; f[7].p3 = p[2];
nt = 8; nt = 8;
/* Bisect each edge and move to the surface of a unit sphere */ /* Bisect each edge and move to the surface of a unit sphere */
for (it=0;it<iterations;it++) { for (it=0;it<iterations;it++) {
ntold = nt; ntold = nt;
for (i=0;i<ntold;i++) { for (i=0;i<ntold;i++) {
pa.x = (f[i].p1.x + f[i].p2.x) / 2; pa.x = (f[i].p1.x + f[i].p2.x) / 2;
pa.y = (f[i].p1.y + f[i].p2.y) / 2; pa.y = (f[i].p1.y + f[i].p2.y) / 2;
pa.z = (f[i].p1.z + f[i].p2.z) / 2; pa.z = (f[i].p1.z + f[i].p2.z) / 2;
pb.x = (f[i].p2.x + f[i].p3.x) / 2; pb.x = (f[i].p2.x + f[i].p3.x) / 2;
pb.y = (f[i].p2.y + f[i].p3.y) / 2; pb.y = (f[i].p2.y + f[i].p3.y) / 2;
pb.z = (f[i].p2.z + f[i].p3.z) / 2; pb.z = (f[i].p2.z + f[i].p3.z) / 2;
pc.x = (f[i].p3.x + f[i].p1.x) / 2; pc.x = (f[i].p3.x + f[i].p1.x) / 2;
pc.y = (f[i].p3.y + f[i].p1.y) / 2; pc.y = (f[i].p3.y + f[i].p1.y) / 2;
pc.z = (f[i].p3.z + f[i].p1.z) / 2; pc.z = (f[i].p3.z + f[i].p1.z) / 2;
pa.normalize(); pa.normalize();
pb.normalize(); pb.normalize();
pc.normalize(); pc.normalize();
f[nt].p1 = f[i].p1; f[nt].p2 = pa; f[nt].p3 = pc; nt++; 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 = 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[nt].p1 = pb; f[nt].p2 = f[i].p3; f[nt].p3 = pc; nt++;
f[i].p1 = pa; f[i].p1 = pa;
f[i].p2 = pb; f[i].p2 = pb;
f[i].p3 = pc; f[i].p3 = pc;
} }
} }
m_sphereVertices = (GLfloat *)malloc(sizeof(GLfloat) * m_cVertices * 3); m_sphereVertices = (GLfloat *)malloc(sizeof(GLfloat) * m_cVertices * 3);
assert(m_sphereVertices != NULL); assert(m_sphereVertices != NULL);
GLfloat *pDest = m_sphereVertices; GLfloat *pDest = m_sphereVertices;
for(int facet_index=0; facet_index < facet_count; facet_index++) { for(int facet_index=0; facet_index < facet_count; facet_index++) {
*pDest++ = f[facet_index].p1.x; *pDest++ = f[facet_index].p1.x;
*pDest++ = f[facet_index].p1.y; *pDest++ = f[facet_index].p1.y;
*pDest++ = f[facet_index].p1.z; *pDest++ = f[facet_index].p1.z;
*pDest++ = f[facet_index].p2.x; *pDest++ = f[facet_index].p2.x;
*pDest++ = f[facet_index].p2.y; *pDest++ = f[facet_index].p2.y;
*pDest++ = f[facet_index].p2.z; *pDest++ = f[facet_index].p2.z;
*pDest++ = f[facet_index].p3.x; *pDest++ = f[facet_index].p3.x;
*pDest++ = f[facet_index].p3.y; *pDest++ = f[facet_index].p3.y;
*pDest++ = f[facet_index].p3.z; *pDest++ = f[facet_index].p3.z;
} }
} }
} }

View File

@@ -1,204 +1,204 @@
// //
// KRRenderSettings.cpp // KRRenderSettings.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-12-20. // Created by Kearwood Gilbert on 2012-12-20.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KRRenderSettings.h" #include "KRRenderSettings.h"
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

@@ -1,341 +1,341 @@
// //
// KRResource_obj.cpp // KRResource_obj.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-03-22. // Created by Kearwood Gilbert on 12-03-22.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRResource.h" #include "KRResource.h"
#include "KRMesh.h" #include "KRMesh.h"
std::vector<KRResource *> KRResource::LoadObj(KRContext &context, const std::string& path) std::vector<KRResource *> KRResource::LoadObj(KRContext &context, const std::string& path)
{ {
std::vector<KRResource *> resources; std::vector<KRResource *> resources;
KRMesh *new_mesh = new KRMesh(context, KRResource::GetFileBase(path)); KRMesh *new_mesh = new KRMesh(context, KRResource::GetFileBase(path));
resources.push_back(new_mesh); resources.push_back(new_mesh);
KRMesh::mesh_info mi; KRMesh::mesh_info mi;
std::vector<std::string> material_names_t; std::vector<std::string> material_names_t;
KRDataBlock data; KRDataBlock data;
char szSymbol[500][256]; char szSymbol[500][256];
int *pFaces = NULL; int *pFaces = NULL;
vector<KRMesh::pack_material *> m_materials; vector<KRMesh::pack_material *> m_materials;
if(data.load(path)) { if(data.load(path)) {
// -----=====----- Get counts -----=====----- // -----=====----- Get counts -----=====-----
int cVertexData = 0; int cVertexData = 0;
int cFaces = 1; int cFaces = 1;
int cMaterialFaceStart = 1; int cMaterialFaceStart = 1;
char *pScan = (char *)data.getStart(); char *pScan = (char *)data.getStart();
char *pEnd = (char *)data.getEnd(); char *pEnd = (char *)data.getEnd();
while(pScan < pEnd) { while(pScan < pEnd) {
// Scan through whitespace // Scan through whitespace
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) { while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
pScan++; pScan++;
} }
if(*pScan == '#') { if(*pScan == '#') {
// Line is a comment line // Line is a comment line
// Scan to the end of the line // Scan to the end of the line
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') { while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
pScan++; pScan++;
} }
} else { } else {
int cSymbols = 0; int cSymbols = 0;
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') { while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
char *pDest = szSymbol[cSymbols++]; char *pDest = szSymbol[cSymbols++];
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') { while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
*pDest++ = *pScan++; *pDest++ = *pScan++;
} }
*pDest = '\0'; *pDest = '\0';
// Scan through whitespace, but don't advance to next line // Scan through whitespace, but don't advance to next line
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) { while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
pScan++; pScan++;
} }
} }
if(strcmp(szSymbol[0], "v") == 0) { if(strcmp(szSymbol[0], "v") == 0) {
// Vertex (v) // Vertex (v)
} else if(strcmp(szSymbol[0], "vt") == 0) { } else if(strcmp(szSymbol[0], "vt") == 0) {
// Vertex Texture UV Coordinate (vt) // Vertex Texture UV Coordinate (vt)
} else if(strcmp(szSymbol[0], "vn") == 0) { } else if(strcmp(szSymbol[0], "vn") == 0) {
// Vertex Normal (vn) // Vertex Normal (vn)
} else if(strcmp(szSymbol[0], "f") == 0) { } else if(strcmp(szSymbol[0], "f") == 0) {
// Face (f) // Face (f)
int cFaceVertexes = (cSymbols - 3) * 3; // 3 vertexes per triangle. Triangles have 4 symbols. Quads have 5 symbols and generate two triangles. int cFaceVertexes = (cSymbols - 3) * 3; // 3 vertexes per triangle. Triangles have 4 symbols. Quads have 5 symbols and generate two triangles.
cVertexData += cFaceVertexes; cVertexData += cFaceVertexes;
cFaces += cFaceVertexes * 3 + 1; // Allocate space for count of vertices, Vertex Index, Texture Coordinate Index, and Normal Index cFaces += cFaceVertexes * 3 + 1; // Allocate space for count of vertices, Vertex Index, Texture Coordinate Index, and Normal Index
} else if(strcmp(szSymbol[0], "usemtl") == 0) { } else if(strcmp(szSymbol[0], "usemtl") == 0) {
// Use Material (usemtl) // Use Material (usemtl)
if(cMaterialFaceStart - cFaces > 0) { if(cMaterialFaceStart - cFaces > 0) {
cFaces++; cFaces++;
} }
material_names_t.push_back(std::string(szSymbol[1])); material_names_t.push_back(std::string(szSymbol[1]));
} }
} }
} }
// -----=====----- Populate vertexes and faces -----=====----- // -----=====----- Populate vertexes and faces -----=====-----
int *pFaces = (int *)malloc(sizeof(int) * (cFaces + 1)); int *pFaces = (int *)malloc(sizeof(int) * (cFaces + 1));
assert(pFaces != NULL); assert(pFaces != NULL);
std::vector<Vector3> indexed_vertices; std::vector<Vector3> indexed_vertices;
std::vector<Vector2> indexed_uva; std::vector<Vector2> indexed_uva;
std::vector<Vector3> indexed_normals; std::vector<Vector3> indexed_normals;
int *pFace = pFaces; int *pFace = pFaces;
int *pMaterialFaces = pFace++; int *pMaterialFaces = pFace++;
*pMaterialFaces = 0; *pMaterialFaces = 0;
// -------- // --------
pScan = (char *)data.getStart(); pScan = (char *)data.getStart();
while(pScan < pEnd) { while(pScan < pEnd) {
// Scan through whitespace // Scan through whitespace
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) { while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
pScan++; pScan++;
} }
if(*pScan == '#') { if(*pScan == '#') {
// Line is a comment line // Line is a comment line
// Scan to the end of the line // Scan to the end of the line
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') { while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
pScan++; pScan++;
} }
} else { } else {
int cSymbols = 0; int cSymbols = 0;
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') { while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
char *pDest = szSymbol[cSymbols++]; char *pDest = szSymbol[cSymbols++];
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') { while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
*pDest++ = *pScan++; *pDest++ = *pScan++;
} }
*pDest = '\0'; *pDest = '\0';
// Scan through whitespace, but don't advance to next line // Scan through whitespace, but don't advance to next line
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) { while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
pScan++; pScan++;
} }
} }
if(strcmp(szSymbol[0], "v") == 0) { if(strcmp(szSymbol[0], "v") == 0) {
// Vertex (v) // Vertex (v)
float x, y, z; float x, y, z;
char *pChar = szSymbol[1]; char *pChar = szSymbol[1];
x = strtof(pChar, &pChar); x = strtof(pChar, &pChar);
pChar = szSymbol[2]; pChar = szSymbol[2];
y = strtof(pChar, &pChar); y = strtof(pChar, &pChar);
pChar = szSymbol[3]; pChar = szSymbol[3];
z = strtof(pChar, &pChar); z = strtof(pChar, &pChar);
indexed_vertices.push_back(Vector3::Create(x,y,z)); indexed_vertices.push_back(Vector3::Create(x,y,z));
} else if(strcmp(szSymbol[0], "vt") == 0) { } else if(strcmp(szSymbol[0], "vt") == 0) {
// Vertex Texture UV Coordinate (vt) // Vertex Texture UV Coordinate (vt)
char *pChar = szSymbol[1]; char *pChar = szSymbol[1];
float u,v; float u,v;
u = strtof(pChar, &pChar); u = strtof(pChar, &pChar);
pChar = szSymbol[2]; pChar = szSymbol[2];
v = strtof(pChar, &pChar); v = strtof(pChar, &pChar);
indexed_uva.push_back(Vector2::Create(u,v)); indexed_uva.push_back(Vector2::Create(u,v));
} else if(strcmp(szSymbol[0], "vn") == 0) { } else if(strcmp(szSymbol[0], "vn") == 0) {
// Vertex Normal (vn) // Vertex Normal (vn)
float x,y,z; float x,y,z;
char *pChar = szSymbol[1]; char *pChar = szSymbol[1];
x = strtof(pChar, &pChar); x = strtof(pChar, &pChar);
pChar = szSymbol[2]; pChar = szSymbol[2];
y = strtof(pChar, &pChar); y = strtof(pChar, &pChar);
pChar = szSymbol[3]; pChar = szSymbol[3];
z = strtof(pChar, &pChar); z = strtof(pChar, &pChar);
indexed_normals.push_back(Vector3::Create(x,y,z)); indexed_normals.push_back(Vector3::Create(x,y,z));
} else if(strcmp(szSymbol[0], "f") == 0) { } else if(strcmp(szSymbol[0], "f") == 0) {
// Face (f) // Face (f)
int cFaceVertices = cSymbols - 1; int cFaceVertices = cSymbols - 1;
*pFace++ = cFaceVertices; *pFace++ = cFaceVertices;
for(int iSymbol=1; iSymbol < cSymbols; iSymbol++) { for(int iSymbol=1; iSymbol < cSymbols; iSymbol++) {
char *pChar = szSymbol[iSymbol]; char *pChar = szSymbol[iSymbol];
if(*pChar == '.' || (*pChar >= '0' && *pChar <= '9')) { if(*pChar == '.' || (*pChar >= '0' && *pChar <= '9')) {
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Vertex Index *pFace++ = strtol(pChar, &pChar, 10) - 1; // Vertex Index
if(*pChar == '/') { if(*pChar == '/') {
pChar++; pChar++;
if(*pChar == '/') { if(*pChar == '/') {
*pFace++ = -1; *pFace++ = -1;
} else { } else {
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Texture Coordinate Index *pFace++ = strtol(pChar, &pChar, 10) - 1; // Texture Coordinate Index
} }
} else { } else {
*pFace++ = -1; *pFace++ = -1;
} }
if(*pChar == '/') { if(*pChar == '/') {
pChar++; pChar++;
if(*pChar == '/') { if(*pChar == '/') {
*pFace++ = -1; *pFace++ = -1;
} else { } else {
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Normal Index *pFace++ = strtol(pChar, &pChar, 10) - 1; // Normal Index
} }
} else { } else {
*pFace++ = -1; *pFace++ = -1;
} }
while(*pChar == '/') { while(*pChar == '/') {
pChar++; pChar++;
strtol(pChar, &pChar, 10); strtol(pChar, &pChar, 10);
} }
} }
} }
} else if(strcmp(szSymbol[0], "usemtl") == 0) { } else if(strcmp(szSymbol[0], "usemtl") == 0) {
// Use Material (usemtl) // Use Material (usemtl)
if(pFace - pMaterialFaces > 1) { if(pFace - pMaterialFaces > 1) {
*pMaterialFaces = pFace - pMaterialFaces - 1; *pMaterialFaces = pFace - pMaterialFaces - 1;
pMaterialFaces = pFace++; pMaterialFaces = pFace++;
} }
} }
} }
} }
*pMaterialFaces = pFace - pMaterialFaces - 1; *pMaterialFaces = pFace - pMaterialFaces - 1;
*pFace++ = 0; *pFace++ = 0;
int iVertex = 0; int iVertex = 0;
std::vector<std::string>::iterator material_itr = material_names_t.begin(); std::vector<std::string>::iterator material_itr = material_names_t.begin();
KRMesh::pack_material *pMaterial = new KRMesh::pack_material(); KRMesh::pack_material *pMaterial = new KRMesh::pack_material();
pMaterial->start_vertex = iVertex; pMaterial->start_vertex = iVertex;
pMaterial->vertex_count = 0; pMaterial->vertex_count = 0;
memset(pMaterial->szName, 256, 0); memset(pMaterial->szName, 256, 0);
if(material_itr < material_names_t.end()) { if(material_itr < material_names_t.end()) {
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256); strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
} }
m_materials.push_back(pMaterial); m_materials.push_back(pMaterial);
pFace = pFaces; pFace = pFaces;
while(*pFace != 0 && iVertex < cVertexData) { while(*pFace != 0 && iVertex < cVertexData) {
pMaterial->start_vertex = iVertex; pMaterial->start_vertex = iVertex;
int *pMaterialEndFace = pFace + *pFace; int *pMaterialEndFace = pFace + *pFace;
++pFace; ++pFace;
while(pFace < pMaterialEndFace && iVertex < cVertexData) { while(pFace < pMaterialEndFace && iVertex < cVertexData) {
int cFaceVertexes = *pFace; int cFaceVertexes = *pFace;
Vector3 firstFaceVertex; Vector3 firstFaceVertex;
Vector3 prevFaceVertex; Vector3 prevFaceVertex;
Vector3 firstFaceNormal; Vector3 firstFaceNormal;
Vector3 prevFaceNormal; Vector3 prevFaceNormal;
Vector2 firstFaceUva; Vector2 firstFaceUva;
Vector2 prevFaceUva; Vector2 prevFaceUva;
for(int iFaceVertex=0; iFaceVertex < cFaceVertexes; iFaceVertex++) { for(int iFaceVertex=0; iFaceVertex < cFaceVertexes; iFaceVertex++) {
if(iFaceVertex > 2) { if(iFaceVertex > 2) {
// There have already been 3 vertices. Now we need to split the quad into a second triangle composed of the 1st, 3rd, and 4th vertices // There have already been 3 vertices. Now we need to split the quad into a second triangle composed of the 1st, 3rd, and 4th vertices
iVertex+=2; iVertex+=2;
mi.vertices.push_back(firstFaceVertex); mi.vertices.push_back(firstFaceVertex);
mi.uva.push_back(firstFaceUva); mi.uva.push_back(firstFaceUva);
mi.normals.push_back(firstFaceNormal); mi.normals.push_back(firstFaceNormal);
mi.vertices.push_back(prevFaceVertex); mi.vertices.push_back(prevFaceVertex);
mi.uva.push_back(prevFaceUva); mi.uva.push_back(prevFaceUva);
mi.normals.push_back(prevFaceNormal); mi.normals.push_back(prevFaceNormal);
} }
Vector3 vertex = indexed_vertices[pFace[iFaceVertex*3+1]]; Vector3 vertex = indexed_vertices[pFace[iFaceVertex*3+1]];
Vector2 new_uva; Vector2 new_uva;
if(pFace[iFaceVertex*3+2] >= 0) { if(pFace[iFaceVertex*3+2] >= 0) {
new_uva = indexed_uva[pFace[iFaceVertex*3+2]]; new_uva = indexed_uva[pFace[iFaceVertex*3+2]];
} }
Vector3 normal; Vector3 normal;
if(pFace[iFaceVertex*3+3] >= 0){ if(pFace[iFaceVertex*3+3] >= 0){
Vector3 normal = indexed_normals[pFace[iFaceVertex*3+3]]; Vector3 normal = indexed_normals[pFace[iFaceVertex*3+3]];
} }
mi.vertices.push_back(vertex); mi.vertices.push_back(vertex);
mi.uva.push_back(new_uva); mi.uva.push_back(new_uva);
mi.normals.push_back(normal); mi.normals.push_back(normal);
if(iFaceVertex==0) { if(iFaceVertex==0) {
firstFaceVertex = vertex; firstFaceVertex = vertex;
firstFaceUva = new_uva; firstFaceUva = new_uva;
firstFaceNormal = normal; firstFaceNormal = normal;
} }
prevFaceVertex = vertex; prevFaceVertex = vertex;
prevFaceUva = new_uva; prevFaceUva = new_uva;
prevFaceNormal = normal; prevFaceNormal = normal;
iVertex++; iVertex++;
} }
pFace += cFaceVertexes * 3 + 1; pFace += cFaceVertexes * 3 + 1;
} }
pMaterial->vertex_count = iVertex - pMaterial->start_vertex; pMaterial->vertex_count = iVertex - pMaterial->start_vertex;
if(*pFace != 0) { if(*pFace != 0) {
pMaterial = new KRMesh::pack_material(); pMaterial = new KRMesh::pack_material();
pMaterial->start_vertex = iVertex; pMaterial->start_vertex = iVertex;
pMaterial->vertex_count = 0; pMaterial->vertex_count = 0;
memset(pMaterial->szName, 256, 0); memset(pMaterial->szName, 256, 0);
if(material_itr < material_names_t.end()) { if(material_itr < material_names_t.end()) {
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256); strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
} }
m_materials.push_back(pMaterial); m_materials.push_back(pMaterial);
} }
} }
for(int iMaterial=0; iMaterial < m_materials.size(); iMaterial++) { for(int iMaterial=0; iMaterial < m_materials.size(); iMaterial++) {
KRMesh::pack_material *pNewMaterial = m_materials[iMaterial]; KRMesh::pack_material *pNewMaterial = m_materials[iMaterial];
if(pNewMaterial->vertex_count > 0) { if(pNewMaterial->vertex_count > 0) {
mi.material_names.push_back(std::string(pNewMaterial->szName)); mi.material_names.push_back(std::string(pNewMaterial->szName));
mi.submesh_starts.push_back(pNewMaterial->start_vertex); mi.submesh_starts.push_back(pNewMaterial->start_vertex);
mi.submesh_lengths.push_back(pNewMaterial->vertex_count); mi.submesh_lengths.push_back(pNewMaterial->vertex_count);
} }
delete pNewMaterial; delete pNewMaterial;
} }
// TODO: Bones not yet supported for OBJ // TODO: Bones not yet supported for OBJ
// std::vector<std::string> bone_names; // std::vector<std::string> bone_names;
// std::vector<Matrix4> bone_bind_poses; // std::vector<Matrix4> bone_bind_poses;
// std::vector<std::vector<int> > bone_indexes; // std::vector<std::vector<int> > bone_indexes;
// std::vector<std::vector<float> > bone_weights; // std::vector<std::vector<float> > bone_weights;
// //
// std::vector<__uint16_t> vertex_indexes; // std::vector<__uint16_t> vertex_indexes;
// std::vector<std::pair<int, int> > vertex_index_bases; // std::vector<std::pair<int, int> > vertex_index_bases;
mi.format = KRMesh::KRENGINE_MODEL_FORMAT_TRIANGLES; mi.format = KRMesh::KRENGINE_MODEL_FORMAT_TRIANGLES;
new_mesh->LoadData(mi, true, false); new_mesh->LoadData(mi, true, false);
} }
if(pFaces) { if(pFaces) {
free(pFaces); free(pFaces);
} }
return resources; return resources;
} }

View File

@@ -1,166 +1,166 @@
// //
// KRReverbZone.cpp // KRReverbZone.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-12-06. // Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KRReverbZone.h" #include "KRReverbZone.h"
#include "KRContext.h" #include "KRContext.h"
KRReverbZone::KRReverbZone(KRScene &scene, std::string name) : KRNode(scene, name) KRReverbZone::KRReverbZone(KRScene &scene, std::string name) : KRNode(scene, name)
{ {
m_reverb = ""; m_reverb = "";
m_reverb_gain = 1.0f; m_reverb_gain = 1.0f;
m_gradient_distance = 0.25f; m_gradient_distance = 0.25f;
} }
KRReverbZone::~KRReverbZone() KRReverbZone::~KRReverbZone()
{ {
} }
std::string KRReverbZone::getElementName() { std::string KRReverbZone::getElementName() {
return "reverb_zone"; return "reverb_zone";
} }
tinyxml2::XMLElement *KRReverbZone::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRReverbZone::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("zone", m_zone.c_str()); e->SetAttribute("zone", m_zone.c_str());
e->SetAttribute("sample", m_reverb.c_str()); e->SetAttribute("sample", m_reverb.c_str());
e->SetAttribute("gain", m_reverb_gain); e->SetAttribute("gain", m_reverb_gain);
e->SetAttribute("gradient", m_gradient_distance); e->SetAttribute("gradient", m_gradient_distance);
return e; return e;
} }
void KRReverbZone::loadXML(tinyxml2::XMLElement *e) void KRReverbZone::loadXML(tinyxml2::XMLElement *e)
{ {
KRNode::loadXML(e); KRNode::loadXML(e);
m_zone = e->Attribute("zone"); 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) { if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
m_gradient_distance = 0.25f; m_gradient_distance = 0.25f;
} }
m_reverb = e->Attribute("sample"); m_reverb = e->Attribute("sample");
m_reverb_gain = 1.0f; m_reverb_gain = 1.0f;
if(e->QueryFloatAttribute("gain", &m_reverb_gain) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("gain", &m_reverb_gain) != tinyxml2::XML_SUCCESS) {
m_reverb_gain = 1.0f; m_reverb_gain = 1.0f;
} }
} }
std::string KRReverbZone::getReverb() std::string KRReverbZone::getReverb()
{ {
return m_reverb; return m_reverb;
} }
void KRReverbZone::setReverb(const std::string &reverb) void KRReverbZone::setReverb(const std::string &reverb)
{ {
m_reverb = reverb; m_reverb = reverb;
} }
float KRReverbZone::getReverbGain() float KRReverbZone::getReverbGain()
{ {
return m_reverb_gain; return m_reverb_gain;
} }
void KRReverbZone::setReverbGain(float reverb_gain) void KRReverbZone::setReverbGain(float reverb_gain)
{ {
m_reverb_gain = reverb_gain; m_reverb_gain = reverb_gain;
} }
std::string KRReverbZone::getZone() std::string KRReverbZone::getZone()
{ {
return m_zone; return m_zone;
} }
void KRReverbZone::setZone(const std::string &zone) void KRReverbZone::setZone(const std::string &zone)
{ {
m_zone = zone; m_zone = zone;
} }
void KRReverbZone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) void KRReverbZone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
{ {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_REVERB_ZONES; bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_REVERB_ZONES;
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) { if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
Matrix4 sphereModelMatrix = getModelMatrix(); Matrix4 sphereModelMatrix = getModelMatrix();
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
// Enable additive blending // Enable additive blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
// Disable z-buffer write // Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE)); GLDEBUG(glDepthMask(GL_FALSE));
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LEQUAL)); GLDEBUG(glDepthFunc(GL_LEQUAL));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere"); std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
if(sphereModels.size()) { if(sphereModels.size()) {
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) { for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f); sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
} }
} }
// Enable alpha blending // Enable alpha blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
} }
} }
} }
float KRReverbZone::getGradientDistance() float KRReverbZone::getGradientDistance()
{ {
return m_gradient_distance; return m_gradient_distance;
} }
void KRReverbZone::setGradientDistance(float gradient_distance) void KRReverbZone::setGradientDistance(float gradient_distance)
{ {
m_gradient_distance = gradient_distance; m_gradient_distance = gradient_distance;
} }
AABB KRReverbZone::getBounds() { AABB KRReverbZone::getBounds() {
// Reverb zones always have a -1, -1, -1 to 1, 1, 1 bounding box // Reverb zones always have a -1, -1, -1 to 1, 1, 1 bounding box
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix()); return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
} }
float KRReverbZone::getContainment(const Vector3 &pos) float KRReverbZone::getContainment(const Vector3 &pos)
{ {
AABB bounds = getBounds(); AABB bounds = getBounds();
if(bounds.contains(pos)) { if(bounds.contains(pos)) {
Vector3 size = bounds.size(); Vector3 size = bounds.size();
Vector3 diff = pos - bounds.center(); Vector3 diff = pos - bounds.center();
diff = diff * 2.0f; diff = diff * 2.0f;
diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z); diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z);
float d = diff.magnitude(); float d = diff.magnitude();
if(m_gradient_distance <= 0.0f) { if(m_gradient_distance <= 0.0f) {
// Avoid division by zero // Avoid division by zero
d = d > 1.0f ? 0.0f : 1.0f; d = d > 1.0f ? 0.0f : 1.0f;
} else { } else {
d = (1.0f - d) / m_gradient_distance; d = (1.0f - d) / m_gradient_distance;
d = KRCLAMP(d, 0.0f, 1.0f); d = KRCLAMP(d, 0.0f, 1.0f);
} }
return d; return d;
} else { } else {
return 0.0f; return 0.0f;
} }
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,61 +1,61 @@
// //
// KRSpotLight.cpp // KRSpotLight.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-04-05. // Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRSpotLight.h" #include "KRSpotLight.h"
KRSpotLight::KRSpotLight(KRScene &scene, std::string name) : KRLight(scene, name) KRSpotLight::KRSpotLight(KRScene &scene, std::string name) : KRLight(scene, name)
{ {
} }
KRSpotLight::~KRSpotLight() KRSpotLight::~KRSpotLight()
{ {
} }
std::string KRSpotLight::getElementName() { std::string KRSpotLight::getElementName() {
return "spot_light"; return "spot_light";
} }
tinyxml2::XMLElement *KRSpotLight::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRSpotLight::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRLight::saveXML(parent); tinyxml2::XMLElement *e = KRLight::saveXML(parent);
e->SetAttribute("inner_angle", m_innerAngle); e->SetAttribute("inner_angle", m_innerAngle);
e->SetAttribute("outer_angle", m_outerAngle); e->SetAttribute("outer_angle", m_outerAngle);
return e; return e;
} }
void KRSpotLight::loadXML(tinyxml2::XMLElement *e) { void KRSpotLight::loadXML(tinyxml2::XMLElement *e) {
KRLight::loadXML(e); KRLight::loadXML(e);
e->QueryFloatAttribute("inner_angle", &m_innerAngle); e->QueryFloatAttribute("inner_angle", &m_innerAngle);
e->QueryFloatAttribute("outer_angle", &m_outerAngle); e->QueryFloatAttribute("outer_angle", &m_outerAngle);
} }
float KRSpotLight::getInnerAngle() { float KRSpotLight::getInnerAngle() {
return m_innerAngle; return m_innerAngle;
} }
float KRSpotLight::getOuterAngle() { float KRSpotLight::getOuterAngle() {
return m_outerAngle; return m_outerAngle;
} }
void KRSpotLight::setInnerAngle(float innerAngle) { void KRSpotLight::setInnerAngle(float innerAngle) {
m_innerAngle = innerAngle; m_innerAngle = innerAngle;
} }
void KRSpotLight::setOuterAngle(float outerAngle) { void KRSpotLight::setOuterAngle(float outerAngle) {
m_outerAngle = outerAngle; m_outerAngle = outerAngle;
} }
AABB KRSpotLight::getBounds() { AABB KRSpotLight::getBounds() {
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE); float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
if(influence_radius < m_flareOcclusionSize) { if(influence_radius < m_flareOcclusionSize) {
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());
} }

View File

@@ -1,141 +1,141 @@
// //
// KRSprite.cpp // KRSprite.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-04-05. // Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRSprite.h" #include "KRSprite.h"
#include "KRNode.h" #include "KRNode.h"
#include "KRCamera.h" #include "KRCamera.h"
#include "KRContext.h" #include "KRContext.h"
#include "KRShaderManager.h" #include "KRShaderManager.h"
#include "KRShader.h" #include "KRShader.h"
#include "KRStockGeometry.h" #include "KRStockGeometry.h"
#include "KRDirectionalLight.h" #include "KRDirectionalLight.h"
#include "KRSpotLight.h" #include "KRSpotLight.h"
#include "KRPointLight.h" #include "KRPointLight.h"
KRSprite::KRSprite(KRScene &scene, std::string name) : KRNode(scene, name) KRSprite::KRSprite(KRScene &scene, std::string name) : KRNode(scene, name)
{ {
m_spriteTexture = ""; m_spriteTexture = "";
m_pSpriteTexture = NULL; m_pSpriteTexture = NULL;
m_spriteAlpha = 1.0f; m_spriteAlpha = 1.0f;
} }
KRSprite::~KRSprite() KRSprite::~KRSprite()
{ {
} }
std::string KRSprite::getElementName() { std::string KRSprite::getElementName() {
return "sprite"; return "sprite";
} }
tinyxml2::XMLElement *KRSprite::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRSprite::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("sprite_texture", m_spriteTexture.c_str()); e->SetAttribute("sprite_texture", m_spriteTexture.c_str());
e->SetAttribute("sprite_alpha", m_spriteAlpha); e->SetAttribute("sprite_alpha", m_spriteAlpha);
return e; return e;
} }
void KRSprite::loadXML(tinyxml2::XMLElement *e) { void KRSprite::loadXML(tinyxml2::XMLElement *e) {
KRNode::loadXML(e); KRNode::loadXML(e);
if(e->QueryFloatAttribute("sprite_alpha", &m_spriteAlpha) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("sprite_alpha", &m_spriteAlpha) != tinyxml2::XML_SUCCESS) {
m_spriteAlpha = 1.0f; m_spriteAlpha = 1.0f;
} }
const char *szSpriteTexture = e->Attribute("sprite_texture"); const char *szSpriteTexture = e->Attribute("sprite_texture");
if(szSpriteTexture) { if(szSpriteTexture) {
m_spriteTexture = szSpriteTexture; m_spriteTexture = szSpriteTexture;
} else { } else {
m_spriteTexture = ""; m_spriteTexture = "";
} }
m_pSpriteTexture = NULL; m_pSpriteTexture = NULL;
} }
void KRSprite::setSpriteTexture(std::string sprite_texture) { void KRSprite::setSpriteTexture(std::string sprite_texture) {
m_spriteTexture = sprite_texture; m_spriteTexture = sprite_texture;
m_pSpriteTexture = NULL; m_pSpriteTexture = NULL;
} }
void KRSprite::setSpriteAlpha(float alpha) void KRSprite::setSpriteAlpha(float alpha)
{ {
m_spriteAlpha = alpha; m_spriteAlpha = alpha;
} }
float KRSprite::getSpriteAlpha() const float KRSprite::getSpriteAlpha() const
{ {
return m_spriteAlpha; return m_spriteAlpha;
} }
AABB KRSprite::getBounds() { AABB KRSprite::getBounds() {
return AABB::Create(-Vector3::One() * 0.5f, Vector3::One() * 0.5f, getModelMatrix()); return AABB::Create(-Vector3::One() * 0.5f, Vector3::One() * 0.5f, getModelMatrix());
} }
void KRSprite::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { void KRSprite::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) { if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) {
// Pre-stream sprites, even if the alpha is zero // Pre-stream sprites, even if the alpha is zero
if(m_spriteTexture.size() && m_pSpriteTexture == NULL) { if(m_spriteTexture.size() && m_pSpriteTexture == NULL) {
if(!m_pSpriteTexture && m_spriteTexture.size()) { if(!m_pSpriteTexture && m_spriteTexture.size()) {
m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture); m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture);
} }
} }
if(m_pSpriteTexture) { if(m_pSpriteTexture) {
m_pSpriteTexture->resetPoolExpiry(0.0f, KRTexture::TEXTURE_USAGE_SPRITE); m_pSpriteTexture->resetPoolExpiry(0.0f, KRTexture::TEXTURE_USAGE_SPRITE);
} }
} }
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
if(m_spriteTexture.size() && m_spriteAlpha > 0.0f) { if(m_spriteTexture.size() && m_spriteAlpha > 0.0f) {
if(!m_pSpriteTexture && m_spriteTexture.size()) { if(!m_pSpriteTexture && m_spriteTexture.size()) {
m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture); m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture);
} }
if(m_pSpriteTexture) { if(m_pSpriteTexture) {
/* /*
// Enable additive blending // Enable additive blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
// Disable z-buffer write // Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE)); GLDEBUG(glDepthMask(GL_FALSE));
*/ */
// TODO - Sprites are currently additive only. Need to expose this and allow for multiple blending modes // TODO - Sprites are currently additive only. Need to expose this and allow for multiple blending modes
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LEQUAL)); GLDEBUG(glDepthFunc(GL_LEQUAL));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
// Render light sprite on transparency pass // Render light sprite on transparency pass
KRShader *pShader = getContext().getShaderManager()->getShader("sprite", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRShader *pShader = getContext().getShaderManager()->getShader("sprite", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_spriteAlpha); pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_spriteAlpha);
m_pContext->getTextureManager()->selectTexture(0, m_pSpriteTexture, 0.0f, KRTexture::TEXTURE_USAGE_SPRITE); m_pContext->getTextureManager()->selectTexture(0, m_pSpriteTexture, 0.0f, KRTexture::TEXTURE_USAGE_SPRITE);
m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f); m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
} }
} }
} }
} }
} }

View File

@@ -1,62 +1,62 @@
// //
// KRStreamer.cpp // KRStreamer.cpp
// Kraken // Kraken
// //
// Created by Kearwood Gilbert on 11/1/2013. // Created by Kearwood Gilbert on 11/1/2013.
// Copyright (c) 2013 Kearwood Software. All rights reserved. // Copyright (c) 2013 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRStreamer.h" #include "KRStreamer.h"
#include "KRContext.h" #include "KRContext.h"
#include <chrono> #include <chrono>
KRStreamer::KRStreamer(KRContext &context) : m_context(context) KRStreamer::KRStreamer(KRContext &context) : m_context(context)
{ {
m_running = false; m_running = false;
m_stop = false; m_stop = false;
} }
void KRStreamer::startStreamer() void KRStreamer::startStreamer()
{ {
if(!m_running) { if(!m_running) {
m_running = true; m_running = true;
KRContext::activateStreamerContext(); KRContext::activateStreamerContext();
m_thread = std::thread(&KRStreamer::run, this); m_thread = std::thread(&KRStreamer::run, this);
} }
} }
KRStreamer::~KRStreamer() KRStreamer::~KRStreamer()
{ {
if(m_running) { if(m_running) {
m_stop = true; m_stop = true;
m_thread.join(); m_thread.join();
m_running = false; m_running = false;
} }
} }
void KRStreamer::run() void KRStreamer::run()
{ {
#if defined(ANDROID) #if defined(ANDROID)
// TODO - Set thread names on Android // TODO - Set thread names on Android
#elif defined(_WIN32) || defined(_WIN64) #elif defined(_WIN32) || defined(_WIN64)
// TODO - Set thread names on windows // TODO - Set thread names on windows
#else #else
pthread_setname_np("Kraken - Streamer"); pthread_setname_np("Kraken - Streamer");
#endif #endif
std::chrono::microseconds sleep_duration( 15000 ); std::chrono::microseconds sleep_duration( 15000 );
KRContext::activateStreamerContext(); KRContext::activateStreamerContext();
while(!m_stop) while(!m_stop)
{ {
m_context.doStreaming(); m_context.doStreaming();
std::this_thread::sleep_for( sleep_duration ); std::this_thread::sleep_for( sleep_duration );
} }
} }

View File

@@ -1,399 +1,399 @@
// //
// KRTextureTGA.cpp // KRTextureTGA.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-10-23. // Created by Kearwood Gilbert on 2012-10-23.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KRTextureTGA.h" #include "KRTextureTGA.h"
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRContext.h" #include "KRContext.h"
#include "KRTextureKTX.h" #include "KRTextureKTX.h"
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
#pragma pack(1) #pragma pack(1)
typedef struct { typedef struct {
char idlength; char idlength;
char colourmaptype; char colourmaptype;
char imagetype; char imagetype;
short int colourmaporigin; short int colourmaporigin;
short int colourmaplength; short int colourmaplength;
char colourmapdepth; char colourmapdepth;
short int x_origin; short int x_origin;
short int y_origin; short int y_origin;
short width; short width;
short height; short height;
char bitsperpixel; char bitsperpixel;
char imagedescriptor; char imagedescriptor;
} TGA_HEADER; } TGA_HEADER;
#pragma pack() #pragma pack()
#else #else
typedef struct { typedef struct {
char idlength; char idlength;
char colourmaptype; char colourmaptype;
char imagetype; char imagetype;
short int colourmaporigin; short int colourmaporigin;
short int colourmaplength; short int colourmaplength;
char colourmapdepth; char colourmapdepth;
short int x_origin; short int x_origin;
short int y_origin; short int y_origin;
short width; short width;
short height; short height;
char bitsperpixel; char bitsperpixel;
char imagedescriptor; char imagedescriptor;
} __attribute__((packed)) TGA_HEADER; } __attribute__((packed)) TGA_HEADER;
#endif #endif
KRTextureTGA::KRTextureTGA(KRContext &context, KRDataBlock *data, std::string name) : KRTexture2D(context, data, name) KRTextureTGA::KRTextureTGA(KRContext &context, KRDataBlock *data, std::string name) : KRTexture2D(context, data, name)
{ {
data->lock(); data->lock();
TGA_HEADER *pHeader = (TGA_HEADER *)data->getStart(); TGA_HEADER *pHeader = (TGA_HEADER *)data->getStart();
m_max_lod_max_dim = pHeader->width > pHeader->height ? pHeader->width : pHeader->height; m_max_lod_max_dim = pHeader->width > pHeader->height ? pHeader->width : pHeader->height;
m_min_lod_max_dim = m_max_lod_max_dim; // Mipmaps not yet supported for TGA images m_min_lod_max_dim = m_max_lod_max_dim; // Mipmaps not yet supported for TGA images
switch(pHeader->imagetype) { switch(pHeader->imagetype) {
case 2: // rgb case 2: // rgb
case 10: // rgb + rle case 10: // rgb + rle
switch(pHeader->bitsperpixel) { switch(pHeader->bitsperpixel) {
case 24: case 24:
{ {
m_imageSize = pHeader->width * pHeader->height * 4; m_imageSize = pHeader->width * pHeader->height * 4;
} }
break; break;
case 32: case 32:
{ {
m_imageSize = pHeader->width * pHeader->height * 4; m_imageSize = pHeader->width * pHeader->height * 4;
} }
break; break;
default: default:
{ {
assert(false); assert(false);
} }
break; break;
} }
break; break;
default: default:
{ {
assert(false); assert(false);
break; break;
} }
} }
data->unlock(); data->unlock();
} }
KRTextureTGA::~KRTextureTGA() KRTextureTGA::~KRTextureTGA()
{ {
} }
bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, bool compress, bool premultiply_alpha) bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, bool compress, bool premultiply_alpha)
{ {
m_pData->lock(); m_pData->lock();
TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart(); TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart();
unsigned char *pData = (unsigned char *)pHeader + (long)pHeader->idlength + (long)pHeader->colourmaplength * (long)pHeader->colourmaptype + sizeof(TGA_HEADER); unsigned char *pData = (unsigned char *)pHeader + (long)pHeader->idlength + (long)pHeader->colourmaplength * (long)pHeader->colourmaptype + sizeof(TGA_HEADER);
GLenum internal_format = GL_RGBA; GLenum internal_format = GL_RGBA;
#if !TARGET_OS_IPHONE && !defined(ANDROID) #if !TARGET_OS_IPHONE && !defined(ANDROID)
if(compress) { if(compress) {
internal_format = pHeader->bitsperpixel == 24 ? GL_COMPRESSED_RGB_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; internal_format = pHeader->bitsperpixel == 24 ? GL_COMPRESSED_RGB_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
} }
#endif #endif
if(pHeader->colourmaptype != 0) { if(pHeader->colourmaptype != 0) {
m_pData->unlock(); m_pData->unlock();
return false; // Mapped colors not supported return false; // Mapped colors not supported
} }
switch(pHeader->imagetype) { switch(pHeader->imagetype) {
case 2: // rgb case 2: // rgb
switch(pHeader->bitsperpixel) { switch(pHeader->bitsperpixel) {
case 24: case 24:
{ {
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4); unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
//#ifdef __APPLE__ //#ifdef __APPLE__
// vImage_Buffer source_image = { pData, pHeader->height, pHeader->width, pHeader->width*3 }; // vImage_Buffer source_image = { pData, pHeader->height, pHeader->width, pHeader->width*3 };
// vImage_Buffer dest_image = { converted_image, pHeader->height, pHeader->width, pHeader->width*4 }; // vImage_Buffer dest_image = { converted_image, pHeader->height, pHeader->width, pHeader->width*4 };
// vImageConvert_RGB888toRGBA8888(&source_image, NULL, 0xff, &dest_image, false, kvImageDoNotTile); // vImageConvert_RGB888toRGBA8888(&source_image, NULL, 0xff, &dest_image, false, kvImageDoNotTile);
//#else //#else
unsigned char *pSource = pData; unsigned char *pSource = pData;
unsigned char *pDest = converted_image; unsigned char *pDest = converted_image;
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3; unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
while(pSource < pEnd) { while(pSource < pEnd) {
*pDest++ = pSource[2]; *pDest++ = pSource[2];
*pDest++ = pSource[1]; *pDest++ = pSource[1];
*pDest++ = pSource[0]; *pDest++ = pSource[0];
*pDest++ = 0xff; *pDest++ = 0xff;
pSource += 3; pSource += 3;
} }
assert(pSource <= m_pData->getEnd()); assert(pSource <= m_pData->getEnd());
//#endif //#endif
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image)); GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
GLDEBUG(glFinish()); GLDEBUG(glFinish());
free(converted_image); free(converted_image);
current_lod_max_dim = m_max_lod_max_dim; current_lod_max_dim = m_max_lod_max_dim;
} }
break; break;
case 32: case 32:
{ {
if(premultiply_alpha) { if(premultiply_alpha) {
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4); unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
unsigned char *pSource = pData; unsigned char *pSource = pData;
unsigned char *pDest = converted_image; unsigned char *pDest = converted_image;
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3; unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
while(pSource < pEnd) { while(pSource < pEnd) {
*pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff; *pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff;
*pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff; *pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff;
*pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff; *pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff;
*pDest++ = pSource[3]; *pDest++ = pSource[3];
pSource += 4; pSource += 4;
} }
assert(pSource <= m_pData->getEnd()); assert(pSource <= m_pData->getEnd());
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image)); GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
GLDEBUG(glFinish()); GLDEBUG(glFinish());
free(converted_image); free(converted_image);
} else { } else {
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4); unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
unsigned char *pSource = pData; unsigned char *pSource = pData;
unsigned char *pDest = converted_image; unsigned char *pDest = converted_image;
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3; unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
while(pSource < pEnd) { while(pSource < pEnd) {
*pDest++ = (__uint32_t)pSource[2]; *pDest++ = (__uint32_t)pSource[2];
*pDest++ = (__uint32_t)pSource[1]; *pDest++ = (__uint32_t)pSource[1];
*pDest++ = (__uint32_t)pSource[0]; *pDest++ = (__uint32_t)pSource[0];
*pDest++ = pSource[3]; *pDest++ = pSource[3];
pSource += 4; pSource += 4;
} }
assert(pSource <= m_pData->getEnd()); assert(pSource <= m_pData->getEnd());
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)pData)); GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)pData));
GLDEBUG(glFinish()); GLDEBUG(glFinish());
free(converted_image); free(converted_image);
} }
current_lod_max_dim = m_max_lod_max_dim; current_lod_max_dim = m_max_lod_max_dim;
} }
break; break;
default: default:
m_pData->unlock(); m_pData->unlock();
return false; // 16-bit images not yet supported return false; // 16-bit images not yet supported
} }
break; break;
case 10: // rgb + rle case 10: // rgb + rle
switch(pHeader->bitsperpixel) { switch(pHeader->bitsperpixel) {
case 32: case 32:
{ {
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4); unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
unsigned char *pSource = pData; unsigned char *pSource = pData;
unsigned char *pDest = converted_image; unsigned char *pDest = converted_image;
unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4; unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4;
if(premultiply_alpha) { if(premultiply_alpha) {
while(pDest < pEnd) { while(pDest < pEnd) {
int count = (*pSource & 0x7f) + 1; int count = (*pSource & 0x7f) + 1;
if(*pSource & 0x80) { if(*pSource & 0x80) {
// RLE Packet // RLE Packet
pSource++; pSource++;
while(count--) { while(count--) {
*pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff; *pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff;
*pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff; *pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff;
*pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff; *pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff;
*pDest++ = pSource[3]; *pDest++ = pSource[3];
} }
pSource += 4; pSource += 4;
} else { } else {
// RAW Packet // RAW Packet
pSource++; pSource++;
while(count--) { while(count--) {
*pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff; *pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff;
*pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff; *pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff;
*pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff; *pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff;
*pDest++ = pSource[3]; *pDest++ = pSource[3];
pSource += 4; pSource += 4;
} }
} }
} }
assert(pSource <= m_pData->getEnd()); assert(pSource <= m_pData->getEnd());
assert(pDest == pEnd); assert(pDest == pEnd);
} else { } else {
while(pDest < pEnd) { while(pDest < pEnd) {
int count = (*pSource & 0x7f) + 1; int count = (*pSource & 0x7f) + 1;
if(*pSource & 0x80) { if(*pSource & 0x80) {
// RLE Packet // RLE Packet
pSource++; pSource++;
while(count--) { while(count--) {
*pDest++ = pSource[2]; *pDest++ = pSource[2];
*pDest++ = pSource[1]; *pDest++ = pSource[1];
*pDest++ = pSource[0]; *pDest++ = pSource[0];
*pDest++ = pSource[3]; *pDest++ = pSource[3];
} }
pSource += 4; pSource += 4;
} else { } else {
// RAW Packet // RAW Packet
pSource++; pSource++;
while(count--) { while(count--) {
*pDest++ = pSource[2]; *pDest++ = pSource[2];
*pDest++ = pSource[1]; *pDest++ = pSource[1];
*pDest++ = pSource[0]; *pDest++ = pSource[0];
*pDest++ = pSource[3]; *pDest++ = pSource[3];
pSource += 4; pSource += 4;
} }
} }
} }
assert(pSource <= m_pData->getEnd()); assert(pSource <= m_pData->getEnd());
assert(pDest == pEnd); assert(pDest == pEnd);
} }
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image)); GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
GLDEBUG(glFinish()); GLDEBUG(glFinish());
free(converted_image); free(converted_image);
current_lod_max_dim = m_max_lod_max_dim; current_lod_max_dim = m_max_lod_max_dim;
} }
break; break;
case 24: case 24:
{ {
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4); unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
unsigned char *pSource = pData; unsigned char *pSource = pData;
unsigned char *pDest = converted_image; unsigned char *pDest = converted_image;
unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4; unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4;
while(pDest < pEnd) { while(pDest < pEnd) {
int count = (*pSource & 0x7f) + 1; int count = (*pSource & 0x7f) + 1;
if(*pSource & 0x80) { if(*pSource & 0x80) {
// RLE Packet // RLE Packet
pSource++; pSource++;
while(count--) { while(count--) {
*pDest++ = pSource[2]; *pDest++ = pSource[2];
*pDest++ = pSource[1]; *pDest++ = pSource[1];
*pDest++ = pSource[0]; *pDest++ = pSource[0];
*pDest++ = 0xff; *pDest++ = 0xff;
} }
pSource += 3; pSource += 3;
} else { } else {
// RAW Packet // RAW Packet
pSource++; pSource++;
while(count--) { while(count--) {
*pDest++ = pSource[2]; *pDest++ = pSource[2];
*pDest++ = pSource[1]; *pDest++ = pSource[1];
*pDest++ = pSource[0]; *pDest++ = pSource[0];
*pDest++ = 0xff; *pDest++ = 0xff;
pSource += 3; pSource += 3;
} }
} }
} }
assert(pSource <= m_pData->getEnd()); assert(pSource <= m_pData->getEnd());
assert(pDest == pEnd); assert(pDest == pEnd);
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image)); GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
GLDEBUG(glFinish()); GLDEBUG(glFinish());
free(converted_image); free(converted_image);
current_lod_max_dim = m_max_lod_max_dim; current_lod_max_dim = m_max_lod_max_dim;
} }
break; break;
default: default:
m_pData->unlock(); m_pData->unlock();
return false; // 16-bit images not yet supported return false; // 16-bit images not yet supported
} }
break; break;
default: default:
m_pData->unlock(); m_pData->unlock();
return false; // Image type not yet supported return false; // Image type not yet supported
} }
m_pData->unlock(); m_pData->unlock();
return true; return true;
} }
#if !TARGET_OS_IPHONE && !defined(ANDROID) #if !TARGET_OS_IPHONE && !defined(ANDROID)
KRTexture *KRTextureTGA::compress(bool premultiply_alpha) KRTexture *KRTextureTGA::compress(bool premultiply_alpha)
{ {
m_pData->lock(); m_pData->lock();
std::list<KRDataBlock *> blocks; std::list<KRDataBlock *> blocks;
getContext().getTextureManager()->_setActiveTexture(0); getContext().getTextureManager()->_setActiveTexture(0);
GLuint compressed_handle = 0; GLuint compressed_handle = 0;
GLDEBUG(glGenTextures(1, &compressed_handle)); GLDEBUG(glGenTextures(1, &compressed_handle));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compressed_handle)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, compressed_handle));
int current_max_dim = 0; int current_max_dim = 0;
if(!uploadTexture(GL_TEXTURE_2D, m_max_lod_max_dim, current_max_dim, true, premultiply_alpha)) { if(!uploadTexture(GL_TEXTURE_2D, m_max_lod_max_dim, current_max_dim, true, premultiply_alpha)) {
assert(false); // Failed to upload the texture assert(false); // Failed to upload the texture
} }
GLDEBUG(glGenerateMipmap(GL_TEXTURE_2D)); GLDEBUG(glGenerateMipmap(GL_TEXTURE_2D));
GLint width = 0, height = 0, internal_format, base_internal_format; GLint width = 0, height = 0, internal_format, base_internal_format;
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width)); GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width));
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height)); GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height));
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format)); GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format));
/* /*
int texture_base_level = 0; int texture_base_level = 0;
int texture_max_level = 0; int texture_max_level = 0;
GLDEBUG(glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, &texture_base_level)); GLDEBUG(glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, &texture_base_level));
GLDEBUG(glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, &texture_max_level)); GLDEBUG(glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, &texture_max_level));
*/ */
switch(internal_format) switch(internal_format)
{ {
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
base_internal_format = GL_BGRA; base_internal_format = GL_BGRA;
break; break;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
base_internal_format = GL_BGRA; base_internal_format = GL_BGRA;
break; break;
default: default:
assert(false); // Not yet supported assert(false); // Not yet supported
break; break;
} }
GLuint lod_level = 0; GLuint lod_level = 0;
GLint compressed_size = 0; GLint compressed_size = 0;
int lod_width = width; int lod_width = width;
while(lod_width > 1) { while(lod_width > 1) {
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, lod_level, GL_TEXTURE_WIDTH, &lod_width)); GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, lod_level, GL_TEXTURE_WIDTH, &lod_width));
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, lod_level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compressed_size)); GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, lod_level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compressed_size));
KRDataBlock *new_block = new KRDataBlock(); KRDataBlock *new_block = new KRDataBlock();
new_block->expand(compressed_size); new_block->expand(compressed_size);
new_block->lock(); new_block->lock();
GLDEBUG(glGetCompressedTexImage(GL_TEXTURE_2D, lod_level, new_block->getStart())); GLDEBUG(glGetCompressedTexImage(GL_TEXTURE_2D, lod_level, new_block->getStart()));
new_block->unlock(); new_block->unlock();
blocks.push_back(new_block); blocks.push_back(new_block);
lod_level++; lod_level++;
} }
assert(lod_width == 1); assert(lod_width == 1);
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
getContext().getTextureManager()->selectTexture(0, NULL, 0.0f, KRTexture::TEXTURE_USAGE_NONE); getContext().getTextureManager()->selectTexture(0, NULL, 0.0f, KRTexture::TEXTURE_USAGE_NONE);
GLDEBUG(glDeleteTextures(1, &compressed_handle)); GLDEBUG(glDeleteTextures(1, &compressed_handle));
KRTextureKTX *new_texture = new KRTextureKTX(getContext(), getName(), internal_format, base_internal_format, width, height, blocks); KRTextureKTX *new_texture = new KRTextureKTX(getContext(), getName(), internal_format, base_internal_format, width, height, blocks);
m_pData->unlock(); m_pData->unlock();
for(auto block_itr = blocks.begin(); block_itr != blocks.end(); block_itr++) { for(auto block_itr = blocks.begin(); block_itr != blocks.end(); block_itr++) {
KRDataBlock *block = *block_itr; KRDataBlock *block = *block_itr;
delete block; delete block;
} }
return new_texture; return new_texture;
} }
#endif #endif
long KRTextureTGA::getMemRequiredForSize(int max_dim) long KRTextureTGA::getMemRequiredForSize(int max_dim)
{ {
return m_imageSize; return m_imageSize;
} }
std::string KRTextureTGA::getExtension() std::string KRTextureTGA::getExtension()
{ {
return "tga"; return "tga";
} }

View File

@@ -1,264 +1,264 @@
// //
// KRViewport.cpp // KRViewport.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-10-25. // Created by Kearwood Gilbert on 2012-10-25.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#define KRENGINE_SWAP_INT(x,y) {int t;t=x;x=y;y=t;} #define KRENGINE_SWAP_INT(x,y) {int t;t=x;x=y;y=t;}
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRViewport.h" #include "KRViewport.h"
KRViewport::KRViewport() KRViewport::KRViewport()
{ {
m_size = Vector2::One(); m_size = Vector2::One();
m_matProjection = Matrix4(); m_matProjection = Matrix4();
m_matView = Matrix4(); m_matView = Matrix4();
m_lodBias = 0.0f; m_lodBias = 0.0f;
calculateDerivedValues(); calculateDerivedValues();
} }
KRViewport::KRViewport(const Vector2 &size, const Matrix4 &matView, const Matrix4 &matProjection) KRViewport::KRViewport(const Vector2 &size, const Matrix4 &matView, const Matrix4 &matProjection)
{ {
m_size = size; m_size = size;
m_matView = matView; m_matView = matView;
m_matProjection = matProjection; m_matProjection = matProjection;
calculateDerivedValues(); calculateDerivedValues();
} }
KRViewport& KRViewport::operator=(const KRViewport &v) { KRViewport& KRViewport::operator=(const KRViewport &v) {
if(this != &v) { // Prevent self-assignment. if(this != &v) { // Prevent self-assignment.
m_size = v.m_size; m_size = v.m_size;
m_matProjection = v.m_matProjection; m_matProjection = v.m_matProjection;
m_matView = v.m_matView; m_matView = v.m_matView;
m_lodBias = v.m_lodBias; m_lodBias = v.m_lodBias;
calculateDerivedValues(); calculateDerivedValues();
} }
return *this; return *this;
} }
KRViewport::~KRViewport() KRViewport::~KRViewport()
{ {
} }
const Vector2 &KRViewport::getSize() const const Vector2 &KRViewport::getSize() const
{ {
return m_size; return m_size;
} }
const Matrix4 &KRViewport::getViewMatrix() const const Matrix4 &KRViewport::getViewMatrix() const
{ {
return m_matView; return m_matView;
} }
const Matrix4 &KRViewport::getProjectionMatrix() const const Matrix4 &KRViewport::getProjectionMatrix() const
{ {
return m_matProjection; return m_matProjection;
} }
void KRViewport::setSize(const Vector2 &size) void KRViewport::setSize(const Vector2 &size)
{ {
m_size = size; m_size = size;
} }
void KRViewport::setViewMatrix(const Matrix4 &matView) void KRViewport::setViewMatrix(const Matrix4 &matView)
{ {
m_matView = matView; m_matView = matView;
calculateDerivedValues(); calculateDerivedValues();
} }
void KRViewport::setProjectionMatrix(const Matrix4 &matProjection) void KRViewport::setProjectionMatrix(const Matrix4 &matProjection)
{ {
m_matProjection = matProjection; m_matProjection = matProjection;
calculateDerivedValues(); calculateDerivedValues();
} }
const Matrix4 &KRViewport::KRViewport::getViewProjectionMatrix() const const Matrix4 &KRViewport::KRViewport::getViewProjectionMatrix() const
{ {
return m_matViewProjection; return m_matViewProjection;
} }
const Matrix4 &KRViewport::getInverseViewMatrix() const const Matrix4 &KRViewport::getInverseViewMatrix() const
{ {
return m_matInverseView; return m_matInverseView;
} }
const Matrix4 &KRViewport::getInverseProjectionMatrix() const const Matrix4 &KRViewport::getInverseProjectionMatrix() const
{ {
return m_matInverseProjection; return m_matInverseProjection;
} }
const Vector3 &KRViewport::getCameraDirection() const const Vector3 &KRViewport::getCameraDirection() const
{ {
return m_cameraDirection; return m_cameraDirection;
} }
const Vector3 &KRViewport::getCameraPosition() const const Vector3 &KRViewport::getCameraPosition() const
{ {
return m_cameraPosition; return m_cameraPosition;
} }
const int *KRViewport::getFrontToBackOrder() const const int *KRViewport::getFrontToBackOrder() const
{ {
return &m_frontToBackOrder[0]; return &m_frontToBackOrder[0];
} }
const int *KRViewport::getBackToFrontOrder() const const int *KRViewport::getBackToFrontOrder() const
{ {
return &m_backToFrontOrder[0]; return &m_backToFrontOrder[0];
} }
void KRViewport::calculateDerivedValues() void KRViewport::calculateDerivedValues()
{ {
m_matViewProjection = m_matView * m_matProjection; m_matViewProjection = m_matView * m_matProjection;
m_matInverseView = Matrix4::Invert(m_matView); m_matInverseView = Matrix4::Invert(m_matView);
m_matInverseProjection = Matrix4::Invert(m_matProjection); m_matInverseProjection = Matrix4::Invert(m_matProjection);
m_cameraPosition = Matrix4::Dot(m_matInverseView, Vector3::Zero()); m_cameraPosition = Matrix4::Dot(m_matInverseView, Vector3::Zero());
m_cameraDirection = Matrix4::Dot(m_matInverseView, Vector3::Create(0.0, 0.0, 1.0)) - Matrix4::Dot(m_matInverseView, Vector3::Create(0.0, 0.0, 0.0)); m_cameraDirection = Matrix4::Dot(m_matInverseView, Vector3::Create(0.0, 0.0, 1.0)) - Matrix4::Dot(m_matInverseView, Vector3::Create(0.0, 0.0, 0.0));
for(int i=0; i<8; i++) { for(int i=0; i<8; i++) {
m_frontToBackOrder[i] = i; m_frontToBackOrder[i] = i;
} }
if(m_cameraDirection.x > 0.0) { if(m_cameraDirection.x > 0.0) {
KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[1]); KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[1]);
KRENGINE_SWAP_INT(m_frontToBackOrder[2], m_frontToBackOrder[3]); KRENGINE_SWAP_INT(m_frontToBackOrder[2], m_frontToBackOrder[3]);
KRENGINE_SWAP_INT(m_frontToBackOrder[4], m_frontToBackOrder[5]); KRENGINE_SWAP_INT(m_frontToBackOrder[4], m_frontToBackOrder[5]);
KRENGINE_SWAP_INT(m_frontToBackOrder[6], m_frontToBackOrder[7]); KRENGINE_SWAP_INT(m_frontToBackOrder[6], m_frontToBackOrder[7]);
} }
if(m_cameraDirection.y > 0.0) { if(m_cameraDirection.y > 0.0) {
KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[2]); KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[2]);
KRENGINE_SWAP_INT(m_frontToBackOrder[1], m_frontToBackOrder[3]); KRENGINE_SWAP_INT(m_frontToBackOrder[1], m_frontToBackOrder[3]);
KRENGINE_SWAP_INT(m_frontToBackOrder[4], m_frontToBackOrder[6]); KRENGINE_SWAP_INT(m_frontToBackOrder[4], m_frontToBackOrder[6]);
KRENGINE_SWAP_INT(m_frontToBackOrder[5], m_frontToBackOrder[7]); KRENGINE_SWAP_INT(m_frontToBackOrder[5], m_frontToBackOrder[7]);
} }
if(m_cameraDirection.z > 0.0) { if(m_cameraDirection.z > 0.0) {
KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[4]); KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[4]);
KRENGINE_SWAP_INT(m_frontToBackOrder[1], m_frontToBackOrder[5]); KRENGINE_SWAP_INT(m_frontToBackOrder[1], m_frontToBackOrder[5]);
KRENGINE_SWAP_INT(m_frontToBackOrder[2], m_frontToBackOrder[6]); KRENGINE_SWAP_INT(m_frontToBackOrder[2], m_frontToBackOrder[6]);
KRENGINE_SWAP_INT(m_frontToBackOrder[3], m_frontToBackOrder[7]); KRENGINE_SWAP_INT(m_frontToBackOrder[3], m_frontToBackOrder[7]);
} }
for(int i=0; i<8; i++) { for(int i=0; i<8; i++) {
m_backToFrontOrder[i] = m_frontToBackOrder[7-i]; m_backToFrontOrder[i] = m_frontToBackOrder[7-i];
} }
} }
unordered_map<AABB, int> &KRViewport::getVisibleBounds() unordered_map<AABB, int> &KRViewport::getVisibleBounds()
{ {
return m_visibleBounds; return m_visibleBounds;
} }
float KRViewport::getLODBias() const float KRViewport::getLODBias() const
{ {
return m_lodBias; return m_lodBias;
} }
void KRViewport::setLODBias(float lod_bias) void KRViewport::setLODBias(float lod_bias)
{ {
m_lodBias = lod_bias; m_lodBias = lod_bias;
} }
float KRViewport::coverage(const AABB &b) const float KRViewport::coverage(const AABB &b) const
{ {
if(!visible(b)) { if(!visible(b)) {
return 0.0f; // Culled out by view frustrum return 0.0f; // Culled out by view frustrum
} else { } else {
Vector3 nearest_point = b.nearestPoint(getCameraPosition()); Vector3 nearest_point = b.nearestPoint(getCameraPosition());
float distance = (nearest_point - getCameraPosition()).magnitude(); float distance = (nearest_point - getCameraPosition()).magnitude();
Vector3 v = Matrix4::DotWDiv(m_matProjection, getCameraPosition() + getCameraDirection() * distance); Vector3 v = Matrix4::DotWDiv(m_matProjection, getCameraPosition() + getCameraDirection() * distance);
float screen_depth = distance / 1000.0f; float screen_depth = distance / 1000.0f;
return KRCLAMP(1.0f - screen_depth, 0.01f, 1.0f); return KRCLAMP(1.0f - screen_depth, 0.01f, 1.0f);
/* /*
Vector2 screen_min; Vector2 screen_min;
Vector2 screen_max; Vector2 screen_max;
// Loop through all corners and transform them to screen space // Loop through all corners and transform them to screen space
for(int i=0; i<8; i++) { for(int i=0; i<8; i++) {
Vector3 screen_pos = Matrix4::DotWDiv(m_matViewProjection, Vector3(i & 1 ? b.min.x : b.max.x, i & 2 ? b.min.y : b.max.y, i & 4 ? b.min.z : b.max.z)); Vector3 screen_pos = Matrix4::DotWDiv(m_matViewProjection, Vector3(i & 1 ? b.min.x : b.max.x, i & 2 ? b.min.y : b.max.y, i & 4 ? b.min.z : b.max.z));
if(i==0) { if(i==0) {
screen_min = screen_pos.xy(); screen_min = screen_pos.xy();
screen_max = screen_pos.xy(); screen_max = screen_pos.xy();
} else { } else {
if(screen_pos.x < screen_min.x) screen_min.x = screen_pos.x; if(screen_pos.x < screen_min.x) screen_min.x = screen_pos.x;
if(screen_pos.y < screen_min.y) screen_min.y = screen_pos.y; if(screen_pos.y < screen_min.y) screen_min.y = screen_pos.y;
if(screen_pos.x > screen_max.x) screen_max.x = screen_pos.x; if(screen_pos.x > screen_max.x) screen_max.x = screen_pos.x;
if(screen_pos.y > screen_max.y) screen_max.y = screen_pos.y; if(screen_pos.y > screen_max.y) screen_max.y = screen_pos.y;
} }
} }
screen_min.x = KRCLAMP(screen_min.x, 0.0f, 1.0f); screen_min.x = KRCLAMP(screen_min.x, 0.0f, 1.0f);
screen_min.y = KRCLAMP(screen_min.y, 0.0f, 1.0f); screen_min.y = KRCLAMP(screen_min.y, 0.0f, 1.0f);
screen_max.x = KRCLAMP(screen_max.x, 0.0f, 1.0f); screen_max.x = KRCLAMP(screen_max.x, 0.0f, 1.0f);
screen_max.y = KRCLAMP(screen_max.y, 0.0f, 1.0f); screen_max.y = KRCLAMP(screen_max.y, 0.0f, 1.0f);
float c = (screen_max.x - screen_min.x) * (screen_max.y - screen_min.y); float c = (screen_max.x - screen_min.x) * (screen_max.y - screen_min.y);
return KRCLAMP(c, 0.01f, 1.0f); return KRCLAMP(c, 0.01f, 1.0f);
*/ */
} }
} }
bool KRViewport::visible(const AABB &b) const bool KRViewport::visible(const AABB &b) const
{ {
// test if bounding box would be within the visible range of the clip space transformed by matViewProjection // test if bounding box would be within the visible range of the clip space transformed by matViewProjection
// This is used for view frustrum culling // This is used for view frustrum culling
int outside_count[6] = {0, 0, 0, 0, 0, 0}; int outside_count[6] = {0, 0, 0, 0, 0, 0};
for(int iCorner=0; iCorner<8; iCorner++) { for(int iCorner=0; iCorner<8; iCorner++) {
Vector4 sourceCornerVertex = Vector4::Create( Vector4 sourceCornerVertex = Vector4::Create(
(iCorner & 1) == 0 ? b.min.x : b.max.x, (iCorner & 1) == 0 ? b.min.x : b.max.x,
(iCorner & 2) == 0 ? b.min.y : b.max.y, (iCorner & 2) == 0 ? b.min.y : b.max.y,
(iCorner & 4) == 0 ? b.min.z : b.max.z, 1.0f); (iCorner & 4) == 0 ? b.min.z : b.max.z, 1.0f);
Vector4 cornerVertex = Matrix4::Dot4(m_matViewProjection, sourceCornerVertex); Vector4 cornerVertex = Matrix4::Dot4(m_matViewProjection, sourceCornerVertex);
if(cornerVertex.x < -cornerVertex.w) { if(cornerVertex.x < -cornerVertex.w) {
outside_count[0]++; outside_count[0]++;
} }
if(cornerVertex.y < -cornerVertex.w) { if(cornerVertex.y < -cornerVertex.w) {
outside_count[1]++; outside_count[1]++;
} }
if(cornerVertex.z < -cornerVertex.w) { if(cornerVertex.z < -cornerVertex.w) {
outside_count[2]++; outside_count[2]++;
} }
if(cornerVertex.x > cornerVertex.w) { if(cornerVertex.x > cornerVertex.w) {
outside_count[3]++; outside_count[3]++;
} }
if(cornerVertex.y > cornerVertex.w) { if(cornerVertex.y > cornerVertex.w) {
outside_count[4]++; outside_count[4]++;
} }
if(cornerVertex.z > cornerVertex.w) { if(cornerVertex.z > cornerVertex.w) {
outside_count[5]++; outside_count[5]++;
} }
} }
bool is_visible = true; bool is_visible = true;
for(int iFace=0; iFace < 6; iFace++) { for(int iFace=0; iFace < 6; iFace++) {
if(outside_count[iFace] == 8) { if(outside_count[iFace] == 8) {
is_visible = false; is_visible = false;
} }
} }
return is_visible; return is_visible;
} }