dos2unix crlf conversion and fix warnings
This commit is contained in:
@@ -1,167 +1,167 @@
|
||||
//
|
||||
// KRAmbientZone.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-06.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRAmbientZone.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRAmbientZone::KRAmbientZone(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_ambient = "";
|
||||
m_ambient_gain = 1.0f;
|
||||
|
||||
m_gradient_distance = 0.25f;
|
||||
|
||||
}
|
||||
|
||||
KRAmbientZone::~KRAmbientZone()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRAmbientZone::getElementName() {
|
||||
return "ambient_zone";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRAmbientZone::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("zone", m_zone.c_str());
|
||||
e->SetAttribute("sample", m_ambient.c_str());
|
||||
e->SetAttribute("gain", m_ambient_gain);
|
||||
e->SetAttribute("gradient", m_gradient_distance);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRAmbientZone::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRNode::loadXML(e);
|
||||
|
||||
m_zone = e->Attribute("zone");
|
||||
|
||||
m_gradient_distance = 0.25f;
|
||||
if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
|
||||
m_gradient_distance = 0.25f;
|
||||
}
|
||||
|
||||
m_ambient = e->Attribute("sample");
|
||||
|
||||
m_ambient_gain = 1.0f;
|
||||
if(e->QueryFloatAttribute("gain", &m_ambient_gain) != tinyxml2::XML_SUCCESS) {
|
||||
m_ambient_gain = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
std::string KRAmbientZone::getAmbient()
|
||||
{
|
||||
return m_ambient;
|
||||
}
|
||||
|
||||
void KRAmbientZone::setAmbient(const std::string &ambient)
|
||||
{
|
||||
m_ambient = ambient;
|
||||
}
|
||||
|
||||
float KRAmbientZone::getAmbientGain()
|
||||
{
|
||||
return m_ambient_gain;
|
||||
}
|
||||
|
||||
void KRAmbientZone::setAmbientGain(float ambient_gain)
|
||||
{
|
||||
m_ambient_gain = ambient_gain;
|
||||
}
|
||||
|
||||
std::string KRAmbientZone::getZone()
|
||||
{
|
||||
return m_zone;
|
||||
}
|
||||
|
||||
void KRAmbientZone::setZone(const std::string &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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_AMBIENT_ZONES;
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
||||
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);
|
||||
|
||||
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
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
||||
if(sphereModels.size()) {
|
||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float KRAmbientZone::getGradientDistance()
|
||||
{
|
||||
return m_gradient_distance;
|
||||
}
|
||||
|
||||
void KRAmbientZone::setGradientDistance(float gradient_distance)
|
||||
{
|
||||
m_gradient_distance = gradient_distance;
|
||||
}
|
||||
|
||||
AABB KRAmbientZone::getBounds() {
|
||||
// Ambient zones always have a -1, -1, -1 to 1, 1, 1 bounding box
|
||||
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
|
||||
}
|
||||
|
||||
float KRAmbientZone::getContainment(const Vector3 &pos)
|
||||
{
|
||||
AABB bounds = getBounds();
|
||||
if(bounds.contains(pos)) {
|
||||
Vector3 size = bounds.size();
|
||||
Vector3 diff = pos - bounds.center();
|
||||
diff = diff * 2.0f;
|
||||
diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z);
|
||||
float d = diff.magnitude();
|
||||
|
||||
if(m_gradient_distance <= 0.0f) {
|
||||
// Avoid division by zero
|
||||
d = d > 1.0f ? 0.0f : 1.0f;
|
||||
} else {
|
||||
d = (1.0f - d) / m_gradient_distance;
|
||||
d = KRCLAMP(d, 0.0f, 1.0f);
|
||||
}
|
||||
return d;
|
||||
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
//
|
||||
// KRAmbientZone.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-06.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRAmbientZone.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRAmbientZone::KRAmbientZone(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_ambient = "";
|
||||
m_ambient_gain = 1.0f;
|
||||
|
||||
m_gradient_distance = 0.25f;
|
||||
|
||||
}
|
||||
|
||||
KRAmbientZone::~KRAmbientZone()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRAmbientZone::getElementName() {
|
||||
return "ambient_zone";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRAmbientZone::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("zone", m_zone.c_str());
|
||||
e->SetAttribute("sample", m_ambient.c_str());
|
||||
e->SetAttribute("gain", m_ambient_gain);
|
||||
e->SetAttribute("gradient", m_gradient_distance);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRAmbientZone::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRNode::loadXML(e);
|
||||
|
||||
m_zone = e->Attribute("zone");
|
||||
|
||||
m_gradient_distance = 0.25f;
|
||||
if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
|
||||
m_gradient_distance = 0.25f;
|
||||
}
|
||||
|
||||
m_ambient = e->Attribute("sample");
|
||||
|
||||
m_ambient_gain = 1.0f;
|
||||
if(e->QueryFloatAttribute("gain", &m_ambient_gain) != tinyxml2::XML_SUCCESS) {
|
||||
m_ambient_gain = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
std::string KRAmbientZone::getAmbient()
|
||||
{
|
||||
return m_ambient;
|
||||
}
|
||||
|
||||
void KRAmbientZone::setAmbient(const std::string &ambient)
|
||||
{
|
||||
m_ambient = ambient;
|
||||
}
|
||||
|
||||
float KRAmbientZone::getAmbientGain()
|
||||
{
|
||||
return m_ambient_gain;
|
||||
}
|
||||
|
||||
void KRAmbientZone::setAmbientGain(float ambient_gain)
|
||||
{
|
||||
m_ambient_gain = ambient_gain;
|
||||
}
|
||||
|
||||
std::string KRAmbientZone::getZone()
|
||||
{
|
||||
return m_zone;
|
||||
}
|
||||
|
||||
void KRAmbientZone::setZone(const std::string &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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_AMBIENT_ZONES;
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
||||
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);
|
||||
|
||||
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
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
||||
if(sphereModels.size()) {
|
||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float KRAmbientZone::getGradientDistance()
|
||||
{
|
||||
return m_gradient_distance;
|
||||
}
|
||||
|
||||
void KRAmbientZone::setGradientDistance(float gradient_distance)
|
||||
{
|
||||
m_gradient_distance = gradient_distance;
|
||||
}
|
||||
|
||||
AABB KRAmbientZone::getBounds() {
|
||||
// Ambient zones always have a -1, -1, -1 to 1, 1, 1 bounding box
|
||||
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
|
||||
}
|
||||
|
||||
float KRAmbientZone::getContainment(const Vector3 &pos)
|
||||
{
|
||||
AABB bounds = getBounds();
|
||||
if(bounds.contains(pos)) {
|
||||
Vector3 size = bounds.size();
|
||||
Vector3 diff = pos - bounds.center();
|
||||
diff = diff * 2.0f;
|
||||
diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z);
|
||||
float d = diff.magnitude();
|
||||
|
||||
if(m_gradient_distance <= 0.0f) {
|
||||
// Avoid division by zero
|
||||
d = d > 1.0f ? 0.0f : 1.0f;
|
||||
} else {
|
||||
d = (1.0f - d) / m_gradient_distance;
|
||||
d = KRCLAMP(d, 0.0f, 1.0f);
|
||||
}
|
||||
return d;
|
||||
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,97 +1,97 @@
|
||||
//
|
||||
// KRBone.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-06.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRBone.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRBone::KRBone(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
setScaleCompensation(true);
|
||||
}
|
||||
|
||||
KRBone::~KRBone()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRBone::getElementName() {
|
||||
return "bone";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRBone::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRBone::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRNode::loadXML(e);
|
||||
setScaleCompensation(true);
|
||||
}
|
||||
|
||||
AABB KRBone::getBounds() {
|
||||
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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_BONES;
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
||||
Matrix4 sphereModelMatrix = getModelMatrix();
|
||||
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Disable z-buffer 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);
|
||||
|
||||
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");
|
||||
if(sphereModels.size()) {
|
||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KRBone::setBindPose(const Matrix4 &pose)
|
||||
{
|
||||
m_bind_pose = pose;
|
||||
}
|
||||
const Matrix4 &KRBone::getBindPose()
|
||||
{
|
||||
return m_bind_pose;
|
||||
}
|
||||
//
|
||||
// KRBone.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-06.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRBone.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRBone::KRBone(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
setScaleCompensation(true);
|
||||
}
|
||||
|
||||
KRBone::~KRBone()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRBone::getElementName() {
|
||||
return "bone";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRBone::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRBone::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRNode::loadXML(e);
|
||||
setScaleCompensation(true);
|
||||
}
|
||||
|
||||
AABB KRBone::getBounds() {
|
||||
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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_BONES;
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
||||
Matrix4 sphereModelMatrix = getModelMatrix();
|
||||
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Disable z-buffer 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);
|
||||
|
||||
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");
|
||||
if(sphereModels.size()) {
|
||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KRBone::setBindPose(const Matrix4 &pose)
|
||||
{
|
||||
m_bind_pose = pose;
|
||||
}
|
||||
const Matrix4 &KRBone::getBindPose()
|
||||
{
|
||||
return m_bind_pose;
|
||||
}
|
||||
|
||||
2246
kraken/KRCamera.cpp
2246
kraken/KRCamera.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,229 +1,229 @@
|
||||
//
|
||||
// KRCollider.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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
|
||||
// provided with the distribution.
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// 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
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRCollider.h"
|
||||
#include "KRContext.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) {
|
||||
m_model_name = model_name;
|
||||
m_layer_mask = layer_mask;
|
||||
m_audio_occlusion = audio_occlusion;
|
||||
}
|
||||
|
||||
KRCollider::~KRCollider() {
|
||||
|
||||
}
|
||||
|
||||
std::string KRCollider::getElementName() {
|
||||
return "collider";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRCollider::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("mesh", m_model_name.c_str());
|
||||
e->SetAttribute("layer_mask", m_layer_mask);
|
||||
e->SetAttribute("audio_occlusion", m_audio_occlusion);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRCollider::loadXML(tinyxml2::XMLElement *e) {
|
||||
KRNode::loadXML(e);
|
||||
|
||||
m_model_name = e->Attribute("mesh");
|
||||
|
||||
m_layer_mask = 65535;
|
||||
if(e->QueryUnsignedAttribute("layer_mask", &m_layer_mask) != tinyxml2::XML_SUCCESS) {
|
||||
m_layer_mask = 65535;
|
||||
}
|
||||
|
||||
m_audio_occlusion = 1.0f;
|
||||
if(e->QueryFloatAttribute("audio_occlusion", &m_audio_occlusion) != tinyxml2::XML_SUCCESS) {
|
||||
m_audio_occlusion = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void KRCollider::loadModel() {
|
||||
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
|
||||
if(m_models.size() > 0) {
|
||||
getScene().notify_sceneGraphModify(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AABB KRCollider::getBounds() {
|
||||
loadModel();
|
||||
if(m_models.size() > 0) {
|
||||
return AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||
} else {
|
||||
return AABB::Infinite();
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
loadModel();
|
||||
if(m_models.size()) {
|
||||
if(getBounds().intersectsLine(v0, v1)) {
|
||||
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
|
||||
Vector3 v1_model_space = Matrix4::Dot(getInverseModelMatrix(), v1);
|
||||
HitInfo hitinfo_model_space;
|
||||
if(hitinfo.didHit()) {
|
||||
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());
|
||||
}
|
||||
|
||||
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());
|
||||
hitinfo = HitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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
|
||||
loadModel();
|
||||
if(m_models.size()) {
|
||||
if(getBounds().intersectsRay(v0, dir)) {
|
||||
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
|
||||
Vector3 dir_model_space = Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), dir));
|
||||
HitInfo hitinfo_model_space;
|
||||
if(hitinfo.didHit()) {
|
||||
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());
|
||||
}
|
||||
|
||||
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());
|
||||
hitinfo = HitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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
|
||||
loadModel();
|
||||
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
|
||||
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)
|
||||
);
|
||||
|
||||
if(getBounds().intersects(sphereCastBounds)) {
|
||||
if(m_models[0]->sphereCast(getModelMatrix(), v0, v1, radius, hitinfo)) {
|
||||
hitinfo = HitInfo(hitinfo.getPosition(), hitinfo.getNormal(), hitinfo.getDistance(), this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int KRCollider::getLayerMask()
|
||||
{
|
||||
return m_layer_mask;
|
||||
}
|
||||
|
||||
void KRCollider::setLayerMask(unsigned int layer_mask)
|
||||
{
|
||||
m_layer_mask = layer_mask;
|
||||
}
|
||||
|
||||
float KRCollider::getAudioOcclusion()
|
||||
{
|
||||
return m_audio_occlusion;
|
||||
}
|
||||
|
||||
void KRCollider::setAudioOcclusion(float 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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
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) {
|
||||
loadModel();
|
||||
if(m_models.size()) {
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
|
||||
for(int i=0; i < m_models[0]->getSubmeshCount(); i++) {
|
||||
m_models[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||
}
|
||||
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
|
||||
GL_POP_GROUP_MARKER;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// KRCollider.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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
|
||||
// provided with the distribution.
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// 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
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRCollider.h"
|
||||
#include "KRContext.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) {
|
||||
m_model_name = model_name;
|
||||
m_layer_mask = layer_mask;
|
||||
m_audio_occlusion = audio_occlusion;
|
||||
}
|
||||
|
||||
KRCollider::~KRCollider() {
|
||||
|
||||
}
|
||||
|
||||
std::string KRCollider::getElementName() {
|
||||
return "collider";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRCollider::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("mesh", m_model_name.c_str());
|
||||
e->SetAttribute("layer_mask", m_layer_mask);
|
||||
e->SetAttribute("audio_occlusion", m_audio_occlusion);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRCollider::loadXML(tinyxml2::XMLElement *e) {
|
||||
KRNode::loadXML(e);
|
||||
|
||||
m_model_name = e->Attribute("mesh");
|
||||
|
||||
m_layer_mask = 65535;
|
||||
if(e->QueryUnsignedAttribute("layer_mask", &m_layer_mask) != tinyxml2::XML_SUCCESS) {
|
||||
m_layer_mask = 65535;
|
||||
}
|
||||
|
||||
m_audio_occlusion = 1.0f;
|
||||
if(e->QueryFloatAttribute("audio_occlusion", &m_audio_occlusion) != tinyxml2::XML_SUCCESS) {
|
||||
m_audio_occlusion = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void KRCollider::loadModel() {
|
||||
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
|
||||
if(m_models.size() > 0) {
|
||||
getScene().notify_sceneGraphModify(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AABB KRCollider::getBounds() {
|
||||
loadModel();
|
||||
if(m_models.size() > 0) {
|
||||
return AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||
} else {
|
||||
return AABB::Infinite();
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
loadModel();
|
||||
if(m_models.size()) {
|
||||
if(getBounds().intersectsLine(v0, v1)) {
|
||||
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
|
||||
Vector3 v1_model_space = Matrix4::Dot(getInverseModelMatrix(), v1);
|
||||
HitInfo hitinfo_model_space;
|
||||
if(hitinfo.didHit()) {
|
||||
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());
|
||||
}
|
||||
|
||||
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());
|
||||
hitinfo = HitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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
|
||||
loadModel();
|
||||
if(m_models.size()) {
|
||||
if(getBounds().intersectsRay(v0, dir)) {
|
||||
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
|
||||
Vector3 dir_model_space = Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), dir));
|
||||
HitInfo hitinfo_model_space;
|
||||
if(hitinfo.didHit()) {
|
||||
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());
|
||||
}
|
||||
|
||||
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());
|
||||
hitinfo = HitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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
|
||||
loadModel();
|
||||
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
|
||||
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)
|
||||
);
|
||||
|
||||
if(getBounds().intersects(sphereCastBounds)) {
|
||||
if(m_models[0]->sphereCast(getModelMatrix(), v0, v1, radius, hitinfo)) {
|
||||
hitinfo = HitInfo(hitinfo.getPosition(), hitinfo.getNormal(), hitinfo.getDistance(), this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int KRCollider::getLayerMask()
|
||||
{
|
||||
return m_layer_mask;
|
||||
}
|
||||
|
||||
void KRCollider::setLayerMask(unsigned int layer_mask)
|
||||
{
|
||||
m_layer_mask = layer_mask;
|
||||
}
|
||||
|
||||
float KRCollider::getAudioOcclusion()
|
||||
{
|
||||
return m_audio_occlusion;
|
||||
}
|
||||
|
||||
void KRCollider::setAudioOcclusion(float 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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
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) {
|
||||
loadModel();
|
||||
if(m_models.size()) {
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
|
||||
for(int i=0; i < m_models[0]->getSubmeshCount(); i++) {
|
||||
m_models[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||
}
|
||||
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
|
||||
GL_POP_GROUP_MARKER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,207 +1,207 @@
|
||||
//
|
||||
// KREngine.h
|
||||
// KREngine
|
||||
//
|
||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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
|
||||
// provided with the distribution.
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// 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
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#include "KRDSP.h"
|
||||
|
||||
#ifdef KRDSP_SLOW
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
namespace KRDSP {
|
||||
|
||||
FFTWorkspace::FFTWorkspace()
|
||||
{
|
||||
sin_table = nullptr;
|
||||
cos_table = nullptr;
|
||||
}
|
||||
|
||||
FFTWorkspace::~FFTWorkspace()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void FFTWorkspace::create(size_t length)
|
||||
{
|
||||
size_t size = (length / 2);
|
||||
cos_table = new float[size];
|
||||
sin_table = new float[size];
|
||||
for (int i = 0; i < size / 2; i++) {
|
||||
float a = 2.0f * M_PI * i / length;
|
||||
cos_table[i] = cos(a);
|
||||
sin_table[i] = sin(a);
|
||||
}
|
||||
}
|
||||
|
||||
void FFTWorkspace::destroy()
|
||||
{
|
||||
if (sin_table) {
|
||||
delete sin_table;
|
||||
sin_table = nullptr;
|
||||
}
|
||||
if (cos_table) {
|
||||
delete cos_table;
|
||||
cos_table = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
|
||||
{
|
||||
// Radix-2 Decimation in Time FFT Algorithm
|
||||
// http://en.dsplib.org/content/fft_dec_in_time.html
|
||||
|
||||
// Only power-of-two sizes supported
|
||||
assert((count & (count - 1)) == 0);
|
||||
|
||||
int levels = 0;
|
||||
while (1 << levels <= count) {
|
||||
levels++;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
size_t j = 0;
|
||||
for (int k = 0; k < levels; k++) {
|
||||
j <<= 1;
|
||||
j |= ((i >> k) & 1);
|
||||
}
|
||||
if (j > i) {
|
||||
float temp = src->realp[i];
|
||||
src->realp[i] = src->realp[j];
|
||||
src->realp[j] = temp;
|
||||
temp = src->imagp[i];
|
||||
src->imagp[i] = src->imagp[j];
|
||||
src->imagp[j] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t size = 2; size <= count; size *= 2) {
|
||||
size_t halfsize = size / 2;
|
||||
size_t step = count / size;
|
||||
for (size_t i = 0; i < count; i += size) {
|
||||
for (size_t j = i, k = 0; j < i + halfsize; j++, k += step) {
|
||||
float temp_real = src->realp[j + halfsize] * workspace.cos_table[k];
|
||||
temp_real += src->imagp[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];
|
||||
src->realp[j + halfsize] = src->realp[j] - temp_real;
|
||||
src->imagp[j + halfsize] = src->imagp[j] - temp_imag;
|
||||
src->realp[j] += temp_real;
|
||||
src->imagp[j] += temp_imag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
|
||||
{
|
||||
SplitComplex swapped;
|
||||
swapped.imagp = src->realp;
|
||||
swapped.realp = src->imagp;
|
||||
FFTForward(workspace, &swapped, count);
|
||||
}
|
||||
|
||||
void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destStride, size_t count)
|
||||
{
|
||||
const short *r = src;
|
||||
float *w = dest;
|
||||
while (w < dest + destStride * count) {
|
||||
*w = (float)*r;
|
||||
r += srcStride;
|
||||
w += destStride;
|
||||
}
|
||||
}
|
||||
|
||||
void Scale(float *buffer, float scale, size_t count)
|
||||
{
|
||||
float *w = buffer;
|
||||
while (w < buffer + count) {
|
||||
*w *= scale;
|
||||
w++;
|
||||
}
|
||||
}
|
||||
|
||||
void ScaleCopy(const float *src, float scale, float *dest, size_t count)
|
||||
{
|
||||
const float *r = src;
|
||||
float *w = dest;
|
||||
while (w < dest + count) {
|
||||
*w = *r * scale;
|
||||
w++;
|
||||
r++;
|
||||
}
|
||||
}
|
||||
|
||||
void ScaleCopy(const SplitComplex *src, float scale, SplitComplex *dest, size_t count)
|
||||
{
|
||||
ScaleCopy(src->realp, scale, dest->realp, count);
|
||||
ScaleCopy(src->imagp, scale, dest->imagp, count);
|
||||
}
|
||||
|
||||
void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count)
|
||||
{
|
||||
float *w = buffer;
|
||||
float s = scaleStart;
|
||||
while (w < buffer + count) {
|
||||
*w *= s;
|
||||
w++;
|
||||
s += scaleStep;
|
||||
}
|
||||
}
|
||||
|
||||
void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t buffer2Stride, size_t count)
|
||||
{
|
||||
float *w = buffer;
|
||||
const float *r = buffer2;
|
||||
while (w < buffer + bufferStride * count) {
|
||||
*w *= *r;
|
||||
w += bufferStride;
|
||||
r += buffer2Stride;
|
||||
}
|
||||
}
|
||||
|
||||
void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
buffer->imagp[i] += buffer2->imagp[i];
|
||||
buffer->realp[i] += buffer2->realp[i];
|
||||
}
|
||||
}
|
||||
|
||||
void Multiply(const SplitComplex *a, const SplitComplex *b, SplitComplex *c, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; 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];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KRDSP
|
||||
|
||||
#endif // KRDSP_SLOW
|
||||
//
|
||||
// KREngine.h
|
||||
// KREngine
|
||||
//
|
||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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
|
||||
// provided with the distribution.
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// 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
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#include "KRDSP.h"
|
||||
|
||||
#ifdef KRDSP_SLOW
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
namespace KRDSP {
|
||||
|
||||
FFTWorkspace::FFTWorkspace()
|
||||
{
|
||||
sin_table = nullptr;
|
||||
cos_table = nullptr;
|
||||
}
|
||||
|
||||
FFTWorkspace::~FFTWorkspace()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void FFTWorkspace::create(size_t length)
|
||||
{
|
||||
size_t size = (length / 2);
|
||||
cos_table = new float[size];
|
||||
sin_table = new float[size];
|
||||
for (int i = 0; i < size / 2; i++) {
|
||||
float a = 2.0f * (float)M_PI * i / length;
|
||||
cos_table[i] = cos(a);
|
||||
sin_table[i] = sin(a);
|
||||
}
|
||||
}
|
||||
|
||||
void FFTWorkspace::destroy()
|
||||
{
|
||||
if (sin_table) {
|
||||
delete sin_table;
|
||||
sin_table = nullptr;
|
||||
}
|
||||
if (cos_table) {
|
||||
delete cos_table;
|
||||
cos_table = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
|
||||
{
|
||||
// Radix-2 Decimation in Time FFT Algorithm
|
||||
// http://en.dsplib.org/content/fft_dec_in_time.html
|
||||
|
||||
// Only power-of-two sizes supported
|
||||
assert((count & (count - 1)) == 0);
|
||||
|
||||
unsigned int levels = 0;
|
||||
while (1 << levels <= count) {
|
||||
levels++;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
size_t j = 0;
|
||||
for (int k = 0; k < levels; k++) {
|
||||
j <<= 1;
|
||||
j |= ((i >> k) & 1);
|
||||
}
|
||||
if (j > i) {
|
||||
float temp = src->realp[i];
|
||||
src->realp[i] = src->realp[j];
|
||||
src->realp[j] = temp;
|
||||
temp = src->imagp[i];
|
||||
src->imagp[i] = src->imagp[j];
|
||||
src->imagp[j] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t size = 2; size <= count; size *= 2) {
|
||||
size_t halfsize = size / 2;
|
||||
size_t step = count / size;
|
||||
for (size_t i = 0; i < count; i += size) {
|
||||
for (size_t j = i, k = 0; j < i + halfsize; j++, k += step) {
|
||||
float temp_real = src->realp[j + halfsize] * workspace.cos_table[k];
|
||||
temp_real += src->imagp[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];
|
||||
src->realp[j + halfsize] = src->realp[j] - temp_real;
|
||||
src->imagp[j + halfsize] = src->imagp[j] - temp_imag;
|
||||
src->realp[j] += temp_real;
|
||||
src->imagp[j] += temp_imag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
|
||||
{
|
||||
SplitComplex swapped;
|
||||
swapped.imagp = src->realp;
|
||||
swapped.realp = src->imagp;
|
||||
FFTForward(workspace, &swapped, count);
|
||||
}
|
||||
|
||||
void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destStride, size_t count)
|
||||
{
|
||||
const short *r = src;
|
||||
float *w = dest;
|
||||
while (w < dest + destStride * count) {
|
||||
*w = (float)*r;
|
||||
r += srcStride;
|
||||
w += destStride;
|
||||
}
|
||||
}
|
||||
|
||||
void Scale(float *buffer, float scale, size_t count)
|
||||
{
|
||||
float *w = buffer;
|
||||
while (w < buffer + count) {
|
||||
*w *= scale;
|
||||
w++;
|
||||
}
|
||||
}
|
||||
|
||||
void ScaleCopy(const float *src, float scale, float *dest, size_t count)
|
||||
{
|
||||
const float *r = src;
|
||||
float *w = dest;
|
||||
while (w < dest + count) {
|
||||
*w = *r * scale;
|
||||
w++;
|
||||
r++;
|
||||
}
|
||||
}
|
||||
|
||||
void ScaleCopy(const SplitComplex *src, float scale, SplitComplex *dest, size_t count)
|
||||
{
|
||||
ScaleCopy(src->realp, scale, dest->realp, count);
|
||||
ScaleCopy(src->imagp, scale, dest->imagp, count);
|
||||
}
|
||||
|
||||
void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count)
|
||||
{
|
||||
float *w = buffer;
|
||||
float s = scaleStart;
|
||||
while (w < buffer + count) {
|
||||
*w *= s;
|
||||
w++;
|
||||
s += scaleStep;
|
||||
}
|
||||
}
|
||||
|
||||
void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t buffer2Stride, size_t count)
|
||||
{
|
||||
float *w = buffer;
|
||||
const float *r = buffer2;
|
||||
while (w < buffer + bufferStride * count) {
|
||||
*w *= *r;
|
||||
w += bufferStride;
|
||||
r += buffer2Stride;
|
||||
}
|
||||
}
|
||||
|
||||
void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
buffer->imagp[i] += buffer2->imagp[i];
|
||||
buffer->realp[i] += buffer2->realp[i];
|
||||
}
|
||||
}
|
||||
|
||||
void Multiply(const SplitComplex *a, const SplitComplex *b, SplitComplex *c, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; 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];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KRDSP
|
||||
|
||||
#endif // KRDSP_SLOW
|
||||
|
||||
@@ -1,135 +1,135 @@
|
||||
//
|
||||
// KRDirectionalLight.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRDirectionalLight.h"
|
||||
#include "KRShader.h"
|
||||
#include "KRContext.h"
|
||||
#include "assert.h"
|
||||
#include "KRStockGeometry.h"
|
||||
|
||||
KRDirectionalLight::KRDirectionalLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KRDirectionalLight::~KRDirectionalLight()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string KRDirectionalLight::getElementName() {
|
||||
return "directional_light";
|
||||
}
|
||||
|
||||
Vector3 KRDirectionalLight::getWorldLightDirection() {
|
||||
return Matrix4::Dot(getWorldRotation().rotationMatrix(), getLocalLightDirection());
|
||||
}
|
||||
|
||||
Vector3 KRDirectionalLight::getLocalLightDirection() {
|
||||
return Vector3::Up(); //&KRF HACK changed from Vector3::Forward(); - to compensate for the way Maya handles post rotation.
|
||||
}
|
||||
|
||||
|
||||
int KRDirectionalLight::configureShadowBufferViewports(const KRViewport &viewport) {
|
||||
|
||||
const float KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE = 1.25f; // Scale to apply to view frustrum bounds so that we don't need to refresh shadows on every frame
|
||||
int cShadows = 1;
|
||||
for(int iShadow=0; iShadow < cShadows; iShadow++) {
|
||||
/*
|
||||
TODO - Determine if we still need this...
|
||||
|
||||
GLfloat shadowMinDepths[3][3] = {{0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f},{0.0f, 0.05f, 0.3f}};
|
||||
GLfloat shadowMaxDepths[3][3] = {{0.0f, 0.0f, 1.0f},{0.1f, 0.0f, 0.0f},{0.1f, 0.3f, 1.0f}};
|
||||
|
||||
float min_depth = 0.0f;
|
||||
float max_depth = 1.0f;
|
||||
*/
|
||||
|
||||
AABB worldSpacefrustrumSliceBounds = AABB::Create(Vector3::Create(-1.0f, -1.0f, -1.0f), Vector3::Create(1.0f, 1.0f, 1.0f), Matrix4::Invert(viewport.getViewProjectionMatrix()));
|
||||
worldSpacefrustrumSliceBounds.scale(KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
|
||||
|
||||
Vector3 shadowLook = -Vector3::Normalize(getWorldLightDirection());
|
||||
|
||||
Vector3 shadowUp = Vector3::Create(0.0, 1.0, 0.0);
|
||||
if(Vector3::Dot(shadowUp, shadowLook) > 0.99f) shadowUp = Vector3::Create(0.0, 0.0, 1.0); // Ensure shadow look direction is not parallel with the shadowUp direction
|
||||
|
||||
// Matrix4 matShadowView = Matrix4::LookAt(viewport.getCameraPosition() - shadowLook, viewport.getCameraPosition(), shadowUp);
|
||||
// Matrix4 matShadowProjection = Matrix4();
|
||||
// matShadowProjection.scale(0.001, 0.001, 0.001);
|
||||
|
||||
Matrix4 matShadowView = Matrix4::LookAt(worldSpacefrustrumSliceBounds.center() - shadowLook, worldSpacefrustrumSliceBounds.center(), shadowUp);
|
||||
Matrix4 matShadowProjection = Matrix4();
|
||||
AABB shadowSpaceFrustrumSliceBounds = AABB::Create(worldSpacefrustrumSliceBounds.min, worldSpacefrustrumSliceBounds.max, Matrix4::Invert(matShadowProjection));
|
||||
AABB shadowSpaceSceneBounds = AABB::Create(getScene().getRootOctreeBounds().min, getScene().getRootOctreeBounds().max, Matrix4::Invert(matShadowProjection));
|
||||
if(shadowSpaceSceneBounds.min.z < shadowSpaceFrustrumSliceBounds.min.z) shadowSpaceFrustrumSliceBounds.min.z = shadowSpaceSceneBounds.min.z; // Include any potential shadow casters that are outside the view frustrum
|
||||
matShadowProjection.scale(1.0f / shadowSpaceFrustrumSliceBounds.size().x, 1.0f / shadowSpaceFrustrumSliceBounds.size().y, 1.0f / shadowSpaceFrustrumSliceBounds.size().z);
|
||||
|
||||
Matrix4 matBias;
|
||||
matBias.bias();
|
||||
matShadowProjection *= matBias;
|
||||
|
||||
KRViewport newShadowViewport = KRViewport(Vector2::Create(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection);
|
||||
AABB prevShadowBounds = AABB::Create(-Vector3::One(), Vector3::One(), Matrix4::Invert(m_shadowViewports[iShadow].getViewProjectionMatrix()));
|
||||
AABB minimumShadowBounds = AABB::Create(-Vector3::One(), Vector3::One(), Matrix4::Invert(newShadowViewport.getViewProjectionMatrix()));
|
||||
minimumShadowBounds.scale(1.0f / KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
|
||||
if(!prevShadowBounds.contains(minimumShadowBounds) || !shadowValid[iShadow] || true) { // FINDME, HACK - Re-generating the shadow map every frame. This should only be needed if the shadow contains non-static geometry
|
||||
m_shadowViewports[iShadow] = newShadowViewport;
|
||||
shadowValid[iShadow] = false;
|
||||
fprintf(stderr, "Kraken - Generate shadow maps...\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) {
|
||||
// Lights are rendered on the second pass of the deferred renderer
|
||||
|
||||
std::vector<KRDirectionalLight *> this_light;
|
||||
this_light.push_back(this);
|
||||
|
||||
Matrix4 matModelViewInverseTranspose = viewport.getViewMatrix() * getModelMatrix();
|
||||
matModelViewInverseTranspose.transpose();
|
||||
matModelViewInverseTranspose.invert();
|
||||
|
||||
Vector3 light_direction_view_space = getWorldLightDirection();
|
||||
light_direction_view_space = Matrix4::Dot(matModelViewInverseTranspose, light_direction_view_space);
|
||||
light_direction_view_space.normalize();
|
||||
|
||||
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())) {
|
||||
|
||||
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_INTENSITY, m_intensity * 0.01f);
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Disable z-buffer test
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
|
||||
// Render a full screen quad
|
||||
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AABB KRDirectionalLight::getBounds()
|
||||
{
|
||||
return AABB::Infinite();
|
||||
}
|
||||
//
|
||||
// KRDirectionalLight.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRDirectionalLight.h"
|
||||
#include "KRShader.h"
|
||||
#include "KRContext.h"
|
||||
#include "assert.h"
|
||||
#include "KRStockGeometry.h"
|
||||
|
||||
KRDirectionalLight::KRDirectionalLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KRDirectionalLight::~KRDirectionalLight()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string KRDirectionalLight::getElementName() {
|
||||
return "directional_light";
|
||||
}
|
||||
|
||||
Vector3 KRDirectionalLight::getWorldLightDirection() {
|
||||
return Matrix4::Dot(getWorldRotation().rotationMatrix(), getLocalLightDirection());
|
||||
}
|
||||
|
||||
Vector3 KRDirectionalLight::getLocalLightDirection() {
|
||||
return Vector3::Up(); //&KRF HACK changed from Vector3::Forward(); - to compensate for the way Maya handles post rotation.
|
||||
}
|
||||
|
||||
|
||||
int KRDirectionalLight::configureShadowBufferViewports(const KRViewport &viewport) {
|
||||
|
||||
const float KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE = 1.25f; // Scale to apply to view frustrum bounds so that we don't need to refresh shadows on every frame
|
||||
int cShadows = 1;
|
||||
for(int iShadow=0; iShadow < cShadows; iShadow++) {
|
||||
/*
|
||||
TODO - Determine if we still need this...
|
||||
|
||||
GLfloat shadowMinDepths[3][3] = {{0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f},{0.0f, 0.05f, 0.3f}};
|
||||
GLfloat shadowMaxDepths[3][3] = {{0.0f, 0.0f, 1.0f},{0.1f, 0.0f, 0.0f},{0.1f, 0.3f, 1.0f}};
|
||||
|
||||
float min_depth = 0.0f;
|
||||
float max_depth = 1.0f;
|
||||
*/
|
||||
|
||||
AABB worldSpacefrustrumSliceBounds = AABB::Create(Vector3::Create(-1.0f, -1.0f, -1.0f), Vector3::Create(1.0f, 1.0f, 1.0f), Matrix4::Invert(viewport.getViewProjectionMatrix()));
|
||||
worldSpacefrustrumSliceBounds.scale(KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
|
||||
|
||||
Vector3 shadowLook = -Vector3::Normalize(getWorldLightDirection());
|
||||
|
||||
Vector3 shadowUp = Vector3::Create(0.0, 1.0, 0.0);
|
||||
if(Vector3::Dot(shadowUp, shadowLook) > 0.99f) shadowUp = Vector3::Create(0.0, 0.0, 1.0); // Ensure shadow look direction is not parallel with the shadowUp direction
|
||||
|
||||
// Matrix4 matShadowView = Matrix4::LookAt(viewport.getCameraPosition() - shadowLook, viewport.getCameraPosition(), shadowUp);
|
||||
// Matrix4 matShadowProjection = Matrix4();
|
||||
// matShadowProjection.scale(0.001, 0.001, 0.001);
|
||||
|
||||
Matrix4 matShadowView = Matrix4::LookAt(worldSpacefrustrumSliceBounds.center() - shadowLook, worldSpacefrustrumSliceBounds.center(), shadowUp);
|
||||
Matrix4 matShadowProjection = Matrix4();
|
||||
AABB shadowSpaceFrustrumSliceBounds = AABB::Create(worldSpacefrustrumSliceBounds.min, worldSpacefrustrumSliceBounds.max, Matrix4::Invert(matShadowProjection));
|
||||
AABB shadowSpaceSceneBounds = AABB::Create(getScene().getRootOctreeBounds().min, getScene().getRootOctreeBounds().max, Matrix4::Invert(matShadowProjection));
|
||||
if(shadowSpaceSceneBounds.min.z < shadowSpaceFrustrumSliceBounds.min.z) shadowSpaceFrustrumSliceBounds.min.z = shadowSpaceSceneBounds.min.z; // Include any potential shadow casters that are outside the view frustrum
|
||||
matShadowProjection.scale(1.0f / shadowSpaceFrustrumSliceBounds.size().x, 1.0f / shadowSpaceFrustrumSliceBounds.size().y, 1.0f / shadowSpaceFrustrumSliceBounds.size().z);
|
||||
|
||||
Matrix4 matBias;
|
||||
matBias.bias();
|
||||
matShadowProjection *= matBias;
|
||||
|
||||
KRViewport newShadowViewport = KRViewport(Vector2::Create(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection);
|
||||
AABB prevShadowBounds = AABB::Create(-Vector3::One(), Vector3::One(), Matrix4::Invert(m_shadowViewports[iShadow].getViewProjectionMatrix()));
|
||||
AABB minimumShadowBounds = AABB::Create(-Vector3::One(), Vector3::One(), Matrix4::Invert(newShadowViewport.getViewProjectionMatrix()));
|
||||
minimumShadowBounds.scale(1.0f / KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
|
||||
if(!prevShadowBounds.contains(minimumShadowBounds) || !shadowValid[iShadow] || true) { // FINDME, HACK - Re-generating the shadow map every frame. This should only be needed if the shadow contains non-static geometry
|
||||
m_shadowViewports[iShadow] = newShadowViewport;
|
||||
shadowValid[iShadow] = false;
|
||||
fprintf(stderr, "Kraken - Generate shadow maps...\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) {
|
||||
// Lights are rendered on the second pass of the deferred renderer
|
||||
|
||||
std::vector<KRDirectionalLight *> this_light;
|
||||
this_light.push_back(this);
|
||||
|
||||
Matrix4 matModelViewInverseTranspose = viewport.getViewMatrix() * getModelMatrix();
|
||||
matModelViewInverseTranspose.transpose();
|
||||
matModelViewInverseTranspose.invert();
|
||||
|
||||
Vector3 light_direction_view_space = getWorldLightDirection();
|
||||
light_direction_view_space = Matrix4::Dot(matModelViewInverseTranspose, light_direction_view_space);
|
||||
light_direction_view_space.normalize();
|
||||
|
||||
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())) {
|
||||
|
||||
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_INTENSITY, m_intensity * 0.01f);
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Disable z-buffer test
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
|
||||
// Render a full screen quad
|
||||
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AABB KRDirectionalLight::getBounds()
|
||||
{
|
||||
return AABB::Infinite();
|
||||
}
|
||||
|
||||
@@ -1,173 +1,173 @@
|
||||
//
|
||||
// KRLODGroup.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-06.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRLODGroup.h"
|
||||
#include "KRLODSet.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRLODGroup::KRLODGroup(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_min_distance = 0.0f;
|
||||
m_max_distance = 0.0f;
|
||||
m_reference = AABB::Create(Vector3::Zero(), Vector3::Zero());
|
||||
m_use_world_units = true;
|
||||
}
|
||||
|
||||
KRLODGroup::~KRLODGroup()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRLODGroup::getElementName() {
|
||||
return "lod_group";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRLODGroup::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("min_distance", m_min_distance);
|
||||
e->SetAttribute("max_distance", m_max_distance);
|
||||
|
||||
e->SetAttribute("reference_min_x", m_reference.min.x);
|
||||
e->SetAttribute("reference_min_y", m_reference.min.y);
|
||||
e->SetAttribute("reference_min_z", m_reference.min.z);
|
||||
|
||||
|
||||
e->SetAttribute("reference_max_x", m_reference.max.x);
|
||||
e->SetAttribute("reference_max_y", m_reference.max.y);
|
||||
e->SetAttribute("reference_max_z", m_reference.max.z);
|
||||
|
||||
e->SetAttribute("use_world_units", m_use_world_units ? "true" : "false");
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRLODGroup::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRNode::loadXML(e);
|
||||
|
||||
m_min_distance = 0.0f;
|
||||
if(e->QueryFloatAttribute("min_distance", &m_min_distance) != tinyxml2::XML_SUCCESS) {
|
||||
m_min_distance = 0.0f;
|
||||
}
|
||||
|
||||
m_max_distance = 0.0f;
|
||||
if(e->QueryFloatAttribute("max_distance", &m_max_distance) != tinyxml2::XML_SUCCESS) {
|
||||
m_max_distance = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
float x=0.0f, y=0.0f, z=0.0f;
|
||||
if(e->QueryFloatAttribute("reference_min_x", &x) != tinyxml2::XML_SUCCESS) {
|
||||
x = 0.0f;
|
||||
}
|
||||
if(e->QueryFloatAttribute("reference_min_y", &y) != tinyxml2::XML_SUCCESS) {
|
||||
y = 0.0f;
|
||||
}
|
||||
if(e->QueryFloatAttribute("reference_min_z", &z) != tinyxml2::XML_SUCCESS) {
|
||||
z = 0.0f;
|
||||
}
|
||||
|
||||
m_reference.min = Vector3::Create(x,y,z);
|
||||
|
||||
x=0.0f; y=0.0f; z=0.0f;
|
||||
if(e->QueryFloatAttribute("reference_max_x", &x) != tinyxml2::XML_SUCCESS) {
|
||||
x = 0.0f;
|
||||
}
|
||||
if(e->QueryFloatAttribute("reference_max_y", &y) != tinyxml2::XML_SUCCESS) {
|
||||
y = 0.0f;
|
||||
}
|
||||
if(e->QueryFloatAttribute("reference_max_z", &z) != tinyxml2::XML_SUCCESS) {
|
||||
z = 0.0f;
|
||||
}
|
||||
m_reference.max = Vector3::Create(x,y,z);
|
||||
|
||||
m_use_world_units = true;
|
||||
if(e->QueryBoolAttribute("use_world_units", &m_use_world_units) != tinyxml2::XML_SUCCESS) {
|
||||
m_use_world_units = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const AABB &KRLODGroup::getReference() const
|
||||
{
|
||||
return m_reference;
|
||||
}
|
||||
|
||||
void KRLODGroup::setReference(const AABB &reference)
|
||||
{
|
||||
m_reference = reference;
|
||||
}
|
||||
|
||||
KRNode::LodVisibility KRLODGroup::calcLODVisibility(const KRViewport &viewport)
|
||||
{
|
||||
if(m_min_distance == 0 && m_max_distance == 0) {
|
||||
return LOD_VISIBILITY_VISIBLE;
|
||||
} else {
|
||||
float lod_bias = viewport.getLODBias();
|
||||
lod_bias = pow(2.0f, -lod_bias);
|
||||
|
||||
// Compare using squared distances as sqrt is expensive
|
||||
float sqr_distance;
|
||||
float sqr_prestream_distance;
|
||||
|
||||
Vector3 world_camera_position = viewport.getCameraPosition();
|
||||
Vector3 local_camera_position = worldToLocal(world_camera_position);
|
||||
Vector3 local_reference_point = m_reference.nearestPoint(local_camera_position);
|
||||
|
||||
if(m_use_world_units) {
|
||||
Vector3 world_reference_point = localToWorld(local_reference_point);
|
||||
sqr_distance = (world_camera_position - world_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
|
||||
sqr_prestream_distance = getContext().KRENGINE_PRESTREAM_DISTANCE * getContext().KRENGINE_PRESTREAM_DISTANCE;
|
||||
} else {
|
||||
sqr_distance = (local_camera_position - local_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
|
||||
|
||||
Vector3 world_reference_point = localToWorld(local_reference_point);
|
||||
sqr_prestream_distance = worldToLocal(Vector3::Normalize(world_reference_point - world_camera_position) * getContext().KRENGINE_PRESTREAM_DISTANCE).sqrMagnitude(); // TODO, FINDME - Optimize with precalc?
|
||||
|
||||
}
|
||||
|
||||
float sqr_min_visible_distance = m_min_distance * m_min_distance;
|
||||
float sqr_max_visible_distance = m_max_distance * m_max_distance;
|
||||
if((sqr_distance >= sqr_min_visible_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance || m_max_distance == 0)) {
|
||||
return LOD_VISIBILITY_VISIBLE;
|
||||
} else if((sqr_distance >= sqr_min_visible_distance - sqr_prestream_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance + sqr_prestream_distance || m_max_distance == 0)) {
|
||||
return LOD_VISIBILITY_PRESTREAM;
|
||||
} else {
|
||||
return LOD_VISIBILITY_HIDDEN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float KRLODGroup::getMinDistance()
|
||||
{
|
||||
return m_min_distance;
|
||||
}
|
||||
|
||||
float KRLODGroup::getMaxDistance()
|
||||
{
|
||||
return m_max_distance;
|
||||
}
|
||||
|
||||
void KRLODGroup::setMinDistance(float min_distance)
|
||||
{
|
||||
m_min_distance = min_distance;
|
||||
}
|
||||
|
||||
void KRLODGroup::setMaxDistance(float max_distance)
|
||||
{
|
||||
m_max_distance = max_distance;
|
||||
}
|
||||
|
||||
void KRLODGroup::setUseWorldUnits(bool use_world_units)
|
||||
{
|
||||
m_use_world_units = use_world_units;
|
||||
}
|
||||
|
||||
bool KRLODGroup::getUseWorldUnits() const
|
||||
{
|
||||
return m_use_world_units;
|
||||
}
|
||||
//
|
||||
// KRLODGroup.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-06.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRLODGroup.h"
|
||||
#include "KRLODSet.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRLODGroup::KRLODGroup(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_min_distance = 0.0f;
|
||||
m_max_distance = 0.0f;
|
||||
m_reference = AABB::Create(Vector3::Zero(), Vector3::Zero());
|
||||
m_use_world_units = true;
|
||||
}
|
||||
|
||||
KRLODGroup::~KRLODGroup()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRLODGroup::getElementName() {
|
||||
return "lod_group";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRLODGroup::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("min_distance", m_min_distance);
|
||||
e->SetAttribute("max_distance", m_max_distance);
|
||||
|
||||
e->SetAttribute("reference_min_x", m_reference.min.x);
|
||||
e->SetAttribute("reference_min_y", m_reference.min.y);
|
||||
e->SetAttribute("reference_min_z", m_reference.min.z);
|
||||
|
||||
|
||||
e->SetAttribute("reference_max_x", m_reference.max.x);
|
||||
e->SetAttribute("reference_max_y", m_reference.max.y);
|
||||
e->SetAttribute("reference_max_z", m_reference.max.z);
|
||||
|
||||
e->SetAttribute("use_world_units", m_use_world_units ? "true" : "false");
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRLODGroup::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRNode::loadXML(e);
|
||||
|
||||
m_min_distance = 0.0f;
|
||||
if(e->QueryFloatAttribute("min_distance", &m_min_distance) != tinyxml2::XML_SUCCESS) {
|
||||
m_min_distance = 0.0f;
|
||||
}
|
||||
|
||||
m_max_distance = 0.0f;
|
||||
if(e->QueryFloatAttribute("max_distance", &m_max_distance) != tinyxml2::XML_SUCCESS) {
|
||||
m_max_distance = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
float x=0.0f, y=0.0f, z=0.0f;
|
||||
if(e->QueryFloatAttribute("reference_min_x", &x) != tinyxml2::XML_SUCCESS) {
|
||||
x = 0.0f;
|
||||
}
|
||||
if(e->QueryFloatAttribute("reference_min_y", &y) != tinyxml2::XML_SUCCESS) {
|
||||
y = 0.0f;
|
||||
}
|
||||
if(e->QueryFloatAttribute("reference_min_z", &z) != tinyxml2::XML_SUCCESS) {
|
||||
z = 0.0f;
|
||||
}
|
||||
|
||||
m_reference.min = Vector3::Create(x,y,z);
|
||||
|
||||
x=0.0f; y=0.0f; z=0.0f;
|
||||
if(e->QueryFloatAttribute("reference_max_x", &x) != tinyxml2::XML_SUCCESS) {
|
||||
x = 0.0f;
|
||||
}
|
||||
if(e->QueryFloatAttribute("reference_max_y", &y) != tinyxml2::XML_SUCCESS) {
|
||||
y = 0.0f;
|
||||
}
|
||||
if(e->QueryFloatAttribute("reference_max_z", &z) != tinyxml2::XML_SUCCESS) {
|
||||
z = 0.0f;
|
||||
}
|
||||
m_reference.max = Vector3::Create(x,y,z);
|
||||
|
||||
m_use_world_units = true;
|
||||
if(e->QueryBoolAttribute("use_world_units", &m_use_world_units) != tinyxml2::XML_SUCCESS) {
|
||||
m_use_world_units = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const AABB &KRLODGroup::getReference() const
|
||||
{
|
||||
return m_reference;
|
||||
}
|
||||
|
||||
void KRLODGroup::setReference(const AABB &reference)
|
||||
{
|
||||
m_reference = reference;
|
||||
}
|
||||
|
||||
KRNode::LodVisibility KRLODGroup::calcLODVisibility(const KRViewport &viewport)
|
||||
{
|
||||
if(m_min_distance == 0 && m_max_distance == 0) {
|
||||
return LOD_VISIBILITY_VISIBLE;
|
||||
} else {
|
||||
float lod_bias = viewport.getLODBias();
|
||||
lod_bias = pow(2.0f, -lod_bias);
|
||||
|
||||
// Compare using squared distances as sqrt is expensive
|
||||
float sqr_distance;
|
||||
float sqr_prestream_distance;
|
||||
|
||||
Vector3 world_camera_position = viewport.getCameraPosition();
|
||||
Vector3 local_camera_position = worldToLocal(world_camera_position);
|
||||
Vector3 local_reference_point = m_reference.nearestPoint(local_camera_position);
|
||||
|
||||
if(m_use_world_units) {
|
||||
Vector3 world_reference_point = localToWorld(local_reference_point);
|
||||
sqr_distance = (world_camera_position - world_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
|
||||
sqr_prestream_distance = getContext().KRENGINE_PRESTREAM_DISTANCE * getContext().KRENGINE_PRESTREAM_DISTANCE;
|
||||
} else {
|
||||
sqr_distance = (local_camera_position - local_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
|
||||
|
||||
Vector3 world_reference_point = localToWorld(local_reference_point);
|
||||
sqr_prestream_distance = worldToLocal(Vector3::Normalize(world_reference_point - world_camera_position) * getContext().KRENGINE_PRESTREAM_DISTANCE).sqrMagnitude(); // TODO, FINDME - Optimize with precalc?
|
||||
|
||||
}
|
||||
|
||||
float sqr_min_visible_distance = m_min_distance * m_min_distance;
|
||||
float sqr_max_visible_distance = m_max_distance * m_max_distance;
|
||||
if((sqr_distance >= sqr_min_visible_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance || m_max_distance == 0)) {
|
||||
return LOD_VISIBILITY_VISIBLE;
|
||||
} else if((sqr_distance >= sqr_min_visible_distance - sqr_prestream_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance + sqr_prestream_distance || m_max_distance == 0)) {
|
||||
return LOD_VISIBILITY_PRESTREAM;
|
||||
} else {
|
||||
return LOD_VISIBILITY_HIDDEN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float KRLODGroup::getMinDistance()
|
||||
{
|
||||
return m_min_distance;
|
||||
}
|
||||
|
||||
float KRLODGroup::getMaxDistance()
|
||||
{
|
||||
return m_max_distance;
|
||||
}
|
||||
|
||||
void KRLODGroup::setMinDistance(float min_distance)
|
||||
{
|
||||
m_min_distance = min_distance;
|
||||
}
|
||||
|
||||
void KRLODGroup::setMaxDistance(float max_distance)
|
||||
{
|
||||
m_max_distance = max_distance;
|
||||
}
|
||||
|
||||
void KRLODGroup::setUseWorldUnits(bool use_world_units)
|
||||
{
|
||||
m_use_world_units = use_world_units;
|
||||
}
|
||||
|
||||
bool KRLODGroup::getUseWorldUnits() const
|
||||
{
|
||||
return m_use_world_units;
|
||||
}
|
||||
|
||||
@@ -1,485 +1,485 @@
|
||||
//
|
||||
// KRLight.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRLight.h"
|
||||
|
||||
#include "KRNode.h"
|
||||
#include "KRCamera.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
#include "KRShaderManager.h"
|
||||
#include "KRShader.h"
|
||||
#include "KRStockGeometry.h"
|
||||
#include "KRDirectionalLight.h"
|
||||
#include "KRSpotLight.h"
|
||||
#include "KRPointLight.h"
|
||||
|
||||
|
||||
KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_intensity = 1.0f;
|
||||
m_dust_particle_intensity = 1.0f;
|
||||
m_color = Vector3::One();
|
||||
m_flareTexture = "";
|
||||
m_pFlareTexture = NULL;
|
||||
m_flareSize = 0.0f;
|
||||
m_flareOcclusionSize = 0.05f;
|
||||
m_casts_shadow = true;
|
||||
m_light_shafts = true;
|
||||
m_dust_particle_density = 0.1f;
|
||||
m_dust_particle_size = 1.0f;
|
||||
m_occlusionQuery = 0;
|
||||
|
||||
// Initialize shadow buffers
|
||||
m_cShadowBuffers = 0;
|
||||
for(int iBuffer=0; iBuffer < KRENGINE_MAX_SHADOW_BUFFERS; iBuffer++) {
|
||||
shadowFramebuffer[iBuffer] = 0;
|
||||
shadowDepthTexture[iBuffer] = 0;
|
||||
shadowValid[iBuffer] = false;
|
||||
}
|
||||
}
|
||||
|
||||
KRLight::~KRLight()
|
||||
{
|
||||
if(m_occlusionQuery) {
|
||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
||||
m_occlusionQuery = 0;
|
||||
}
|
||||
allocateShadowBuffers(0);
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRLight::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("intensity", m_intensity);
|
||||
e->SetAttribute("color_r", m_color.x);
|
||||
e->SetAttribute("color_g", m_color.y);
|
||||
e->SetAttribute("color_b", m_color.z);
|
||||
e->SetAttribute("decay_start", m_decayStart);
|
||||
e->SetAttribute("flare_size", m_flareSize);
|
||||
e->SetAttribute("flare_occlusion_size", m_flareOcclusionSize);
|
||||
e->SetAttribute("flare_texture", m_flareTexture.c_str());
|
||||
e->SetAttribute("casts_shadow", m_casts_shadow ? "true" : "false");
|
||||
e->SetAttribute("light_shafts", m_light_shafts ? "true" : "false");
|
||||
e->SetAttribute("dust_particle_density", m_dust_particle_density);
|
||||
e->SetAttribute("dust_particle_size", m_dust_particle_size);
|
||||
e->SetAttribute("dust_particle_intensity", m_dust_particle_intensity);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRLight::loadXML(tinyxml2::XMLElement *e) {
|
||||
KRNode::loadXML(e);
|
||||
float x=1.0f,y=1.0f,z=1.0f;
|
||||
if(e->QueryFloatAttribute("color_r", &x) != tinyxml2::XML_SUCCESS) {
|
||||
x = 1.0;
|
||||
}
|
||||
if(e->QueryFloatAttribute("color_g", &y) != tinyxml2::XML_SUCCESS) {
|
||||
y = 1.0;
|
||||
}
|
||||
if(e->QueryFloatAttribute("color_b", &z) != tinyxml2::XML_SUCCESS) {
|
||||
z = 1.0;
|
||||
}
|
||||
m_color = Vector3::Create(x,y,z);
|
||||
|
||||
if(e->QueryFloatAttribute("intensity", &m_intensity) != tinyxml2::XML_SUCCESS) {
|
||||
m_intensity = 100.0;
|
||||
}
|
||||
|
||||
if(e->QueryFloatAttribute("decay_start", &m_decayStart) != tinyxml2::XML_SUCCESS) {
|
||||
m_decayStart = 0.0;
|
||||
}
|
||||
|
||||
if(e->QueryFloatAttribute("flare_size", &m_flareSize) != tinyxml2::XML_SUCCESS) {
|
||||
m_flareSize = 0.0;
|
||||
}
|
||||
|
||||
if(e->QueryFloatAttribute("flare_occlusion_size", &m_flareOcclusionSize) != tinyxml2::XML_SUCCESS) {
|
||||
m_flareOcclusionSize = 0.05f;
|
||||
}
|
||||
|
||||
if(e->QueryBoolAttribute("casts_shadow", &m_casts_shadow) != tinyxml2::XML_SUCCESS) {
|
||||
m_casts_shadow = true;
|
||||
}
|
||||
|
||||
if(e->QueryBoolAttribute("light_shafts", &m_light_shafts) != tinyxml2::XML_SUCCESS) {
|
||||
m_light_shafts = true;
|
||||
}
|
||||
|
||||
m_dust_particle_density = 0.1f;
|
||||
if(e->QueryFloatAttribute("dust_particle_density", &m_dust_particle_density) != tinyxml2::XML_SUCCESS) {
|
||||
m_dust_particle_density = 0.1f;
|
||||
}
|
||||
|
||||
m_dust_particle_size = 1.0f;
|
||||
if(e->QueryFloatAttribute("dust_particle_size", &m_dust_particle_size) != tinyxml2::XML_SUCCESS) {
|
||||
m_dust_particle_size = 1.0f;
|
||||
}
|
||||
|
||||
m_dust_particle_intensity = 1.0f;
|
||||
if(e->QueryFloatAttribute("dust_particle_intensity", &m_dust_particle_intensity) != tinyxml2::XML_SUCCESS) {
|
||||
m_dust_particle_intensity = 1.0f;
|
||||
}
|
||||
|
||||
const char *szFlareTexture = e->Attribute("flare_texture");
|
||||
if(szFlareTexture) {
|
||||
m_flareTexture = szFlareTexture;
|
||||
} else {
|
||||
m_flareTexture = "";
|
||||
}
|
||||
m_pFlareTexture = NULL;
|
||||
}
|
||||
|
||||
void KRLight::setFlareTexture(std::string flare_texture) {
|
||||
m_flareTexture = flare_texture;
|
||||
m_pFlareTexture = NULL;
|
||||
}
|
||||
|
||||
void KRLight::setFlareSize(float flare_size) {
|
||||
m_flareSize = flare_size;
|
||||
}
|
||||
|
||||
void KRLight::setFlareOcclusionSize(float occlusion_size) {
|
||||
m_flareOcclusionSize = occlusion_size;
|
||||
}
|
||||
|
||||
void KRLight::setIntensity(float intensity) {
|
||||
m_intensity = intensity;
|
||||
}
|
||||
float KRLight::getIntensity() {
|
||||
return m_intensity;
|
||||
}
|
||||
|
||||
const Vector3 &KRLight::getColor() {
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void KRLight::setColor(const Vector3 &color) {
|
||||
m_color = color;
|
||||
}
|
||||
|
||||
void KRLight::setDecayStart(float decayStart) {
|
||||
m_decayStart = decayStart;
|
||||
}
|
||||
|
||||
float KRLight::getDecayStart() {
|
||||
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) {
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
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))) {
|
||||
allocateShadowBuffers(configureShadowBufferViewports(viewport));
|
||||
renderShadowBuffers(pCamera);
|
||||
}
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES && pCamera->settings.dust_particle_enable) {
|
||||
// Render brownian particles for dust floating in air
|
||||
if(m_cShadowBuffers >= 1 && shadowValid[0] && m_dust_particle_density > 0.0f && m_dust_particle_size > 0.0f && m_dust_particle_intensity > 0.0f) {
|
||||
|
||||
if(viewport.visible(getBounds()) || true) { // FINDME, HACK need to remove "|| true"?
|
||||
|
||||
float particle_range = 600.0f;
|
||||
|
||||
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;
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
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.translate(viewport.getCameraPosition());
|
||||
|
||||
std::vector<KRDirectionalLight *> this_directional_light;
|
||||
std::vector<KRSpotLight *> this_spot_light;
|
||||
std::vector<KRPointLight *> this_point_light;
|
||||
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
|
||||
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
|
||||
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
|
||||
if(directional_light) {
|
||||
this_directional_light.push_back(directional_light);
|
||||
}
|
||||
if(spot_light) {
|
||||
this_spot_light.push_back(spot_light);
|
||||
}
|
||||
if(point_light) {
|
||||
this_point_light.push_back(point_light);
|
||||
}
|
||||
|
||||
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())) {
|
||||
|
||||
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_FLARE_SIZE, m_dust_particle_size);
|
||||
|
||||
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);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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::vector<KRDirectionalLight *> this_directional_light;
|
||||
std::vector<KRSpotLight *> this_spot_light;
|
||||
std::vector<KRPointLight *> this_point_light;
|
||||
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
|
||||
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
|
||||
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
|
||||
if(directional_light) {
|
||||
this_directional_light.push_back(directional_light);
|
||||
}
|
||||
if(spot_light) {
|
||||
this_spot_light.push_back(spot_light);
|
||||
}
|
||||
if(point_light) {
|
||||
this_point_light.push_back(point_light);
|
||||
}
|
||||
|
||||
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())) {
|
||||
int slice_count = (int)(pCamera->settings.volumetric_environment_quality * 495.0) + 5;
|
||||
|
||||
float slice_near = -pCamera->settings.getPerspectiveNearZ();
|
||||
float slice_far = -pCamera->settings.volumetric_environment_max_distance;
|
||||
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_LIGHT_COLOR, (m_color * pCamera->settings.volumetric_environment_intensity * m_intensity * -slice_spacing / 1000.0f));
|
||||
|
||||
KRDataBlock index_data;
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_PARTICLE_OCCLUSION) {
|
||||
if(m_flareTexture.size() && m_flareSize > 0.0f) {
|
||||
|
||||
|
||||
Matrix4 occlusion_test_sphere_matrix = Matrix4();
|
||||
occlusion_test_sphere_matrix.scale(m_localScale * m_flareOcclusionSize);
|
||||
occlusion_test_sphere_matrix.translate(m_localTranslation);
|
||||
if(m_parentNode) {
|
||||
occlusion_test_sphere_matrix *= m_parentNode->getModelMatrix();
|
||||
}
|
||||
|
||||
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));
|
||||
#if TARGET_OS_IPHONE || defined(ANDROID)
|
||||
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
|
||||
#else
|
||||
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
|
||||
#endif
|
||||
|
||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
||||
if(sphereModels.size()) {
|
||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "occlusion_test", 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_OS_IPHONE || defined(ANDROID)
|
||||
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
|
||||
#else
|
||||
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
|
||||
if(m_flareTexture.size() && m_flareSize > 0.0f) {
|
||||
|
||||
if(m_occlusionQuery) {
|
||||
GLuint params = 0;
|
||||
GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, ¶ms));
|
||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
||||
|
||||
if(params) {
|
||||
|
||||
if(!m_pFlareTexture && m_flareTexture.size()) {
|
||||
m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture);
|
||||
}
|
||||
|
||||
if(m_pFlareTexture) {
|
||||
// Disable z-buffer test
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
// 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);
|
||||
|
||||
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_FLARE_SIZE, m_flareSize);
|
||||
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);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void KRLight::allocateShadowBuffers(int cBuffers) {
|
||||
// First deallocate buffers no longer needed
|
||||
for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) {
|
||||
if (shadowDepthTexture[iShadow]) {
|
||||
GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow));
|
||||
shadowDepthTexture[iShadow] = 0;
|
||||
}
|
||||
|
||||
if (shadowFramebuffer[iShadow]) {
|
||||
GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow));
|
||||
shadowFramebuffer[iShadow] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate newly required buffers
|
||||
for(int iShadow = 0; iShadow < cBuffers; iShadow++) {
|
||||
Vector2 viewportSize = m_shadowViewports[iShadow].getSize();
|
||||
|
||||
if(!shadowDepthTexture[iShadow]) {
|
||||
shadowValid[iShadow] = false;
|
||||
|
||||
GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow));
|
||||
GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow));
|
||||
// ===== Create offscreen shadow framebuffer object =====
|
||||
|
||||
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
|
||||
|
||||
// ----- Create Depth Texture for shadowFramebuffer -----
|
||||
GLDEBUG( glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow]));
|
||||
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
||||
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
||||
m_pContext->getTextureManager()->_setWrapModeS(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
|
||||
m_pContext->getTextureManager()->_setWrapModeT(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
|
||||
#if GL_EXT_shadow_samplers
|
||||
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
|
||||
#endif
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
m_cShadowBuffers = cBuffers;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
allocateShadowBuffers(0);
|
||||
}
|
||||
|
||||
void KRLight::invalidateShadowBuffers()
|
||||
{
|
||||
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
|
||||
shadowValid[iShadow] = false;
|
||||
}
|
||||
}
|
||||
|
||||
int KRLight::configureShadowBufferViewports(const KRViewport &viewport)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KRLight::renderShadowBuffers(KRCamera *pCamera)
|
||||
{
|
||||
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
|
||||
if(!shadowValid[iShadow]) {
|
||||
shadowValid[iShadow] = true;
|
||||
|
||||
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
|
||||
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
|
||||
|
||||
GLDEBUG(glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y));
|
||||
|
||||
GLDEBUG(glClearDepthf(0.0f));
|
||||
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
|
||||
|
||||
GLDEBUG(glViewport(1, 1, m_shadowViewports[iShadow].getSize().x - 2, m_shadowViewports[iShadow].getSize().y - 2));
|
||||
|
||||
GLDEBUG(glClearDepthf(1.0f));
|
||||
|
||||
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
|
||||
|
||||
GLDEBUG(glDisable(GL_DITHER));
|
||||
|
||||
//GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts
|
||||
//GLDEBUG(glEnable(GL_CULL_FACE));
|
||||
GLDEBUG(glDisable(GL_CULL_FACE));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LESS));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
// Disable alpha blending as we are using alpha channel for packed depth info
|
||||
GLDEBUG(glDisable(GL_BLEND));
|
||||
|
||||
// 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);
|
||||
|
||||
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);
|
||||
|
||||
GLDEBUG(glEnable(GL_CULL_FACE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int KRLight::getShadowBufferCount()
|
||||
{
|
||||
int cBuffers=0;
|
||||
for(int iBuffer=0; iBuffer < m_cShadowBuffers; iBuffer++) {
|
||||
if(shadowValid[iBuffer]) {
|
||||
cBuffers++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cBuffers;
|
||||
}
|
||||
|
||||
GLuint *KRLight::getShadowTextures()
|
||||
{
|
||||
return shadowDepthTexture;
|
||||
}
|
||||
|
||||
KRViewport *KRLight::getShadowViewports()
|
||||
{
|
||||
return m_shadowViewports;
|
||||
}
|
||||
//
|
||||
// KRLight.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRLight.h"
|
||||
|
||||
#include "KRNode.h"
|
||||
#include "KRCamera.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
#include "KRShaderManager.h"
|
||||
#include "KRShader.h"
|
||||
#include "KRStockGeometry.h"
|
||||
#include "KRDirectionalLight.h"
|
||||
#include "KRSpotLight.h"
|
||||
#include "KRPointLight.h"
|
||||
|
||||
|
||||
KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_intensity = 1.0f;
|
||||
m_dust_particle_intensity = 1.0f;
|
||||
m_color = Vector3::One();
|
||||
m_flareTexture = "";
|
||||
m_pFlareTexture = NULL;
|
||||
m_flareSize = 0.0f;
|
||||
m_flareOcclusionSize = 0.05f;
|
||||
m_casts_shadow = true;
|
||||
m_light_shafts = true;
|
||||
m_dust_particle_density = 0.1f;
|
||||
m_dust_particle_size = 1.0f;
|
||||
m_occlusionQuery = 0;
|
||||
|
||||
// Initialize shadow buffers
|
||||
m_cShadowBuffers = 0;
|
||||
for(int iBuffer=0; iBuffer < KRENGINE_MAX_SHADOW_BUFFERS; iBuffer++) {
|
||||
shadowFramebuffer[iBuffer] = 0;
|
||||
shadowDepthTexture[iBuffer] = 0;
|
||||
shadowValid[iBuffer] = false;
|
||||
}
|
||||
}
|
||||
|
||||
KRLight::~KRLight()
|
||||
{
|
||||
if(m_occlusionQuery) {
|
||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
||||
m_occlusionQuery = 0;
|
||||
}
|
||||
allocateShadowBuffers(0);
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRLight::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("intensity", m_intensity);
|
||||
e->SetAttribute("color_r", m_color.x);
|
||||
e->SetAttribute("color_g", m_color.y);
|
||||
e->SetAttribute("color_b", m_color.z);
|
||||
e->SetAttribute("decay_start", m_decayStart);
|
||||
e->SetAttribute("flare_size", m_flareSize);
|
||||
e->SetAttribute("flare_occlusion_size", m_flareOcclusionSize);
|
||||
e->SetAttribute("flare_texture", m_flareTexture.c_str());
|
||||
e->SetAttribute("casts_shadow", m_casts_shadow ? "true" : "false");
|
||||
e->SetAttribute("light_shafts", m_light_shafts ? "true" : "false");
|
||||
e->SetAttribute("dust_particle_density", m_dust_particle_density);
|
||||
e->SetAttribute("dust_particle_size", m_dust_particle_size);
|
||||
e->SetAttribute("dust_particle_intensity", m_dust_particle_intensity);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRLight::loadXML(tinyxml2::XMLElement *e) {
|
||||
KRNode::loadXML(e);
|
||||
float x=1.0f,y=1.0f,z=1.0f;
|
||||
if(e->QueryFloatAttribute("color_r", &x) != tinyxml2::XML_SUCCESS) {
|
||||
x = 1.0;
|
||||
}
|
||||
if(e->QueryFloatAttribute("color_g", &y) != tinyxml2::XML_SUCCESS) {
|
||||
y = 1.0;
|
||||
}
|
||||
if(e->QueryFloatAttribute("color_b", &z) != tinyxml2::XML_SUCCESS) {
|
||||
z = 1.0;
|
||||
}
|
||||
m_color = Vector3::Create(x,y,z);
|
||||
|
||||
if(e->QueryFloatAttribute("intensity", &m_intensity) != tinyxml2::XML_SUCCESS) {
|
||||
m_intensity = 100.0;
|
||||
}
|
||||
|
||||
if(e->QueryFloatAttribute("decay_start", &m_decayStart) != tinyxml2::XML_SUCCESS) {
|
||||
m_decayStart = 0.0;
|
||||
}
|
||||
|
||||
if(e->QueryFloatAttribute("flare_size", &m_flareSize) != tinyxml2::XML_SUCCESS) {
|
||||
m_flareSize = 0.0;
|
||||
}
|
||||
|
||||
if(e->QueryFloatAttribute("flare_occlusion_size", &m_flareOcclusionSize) != tinyxml2::XML_SUCCESS) {
|
||||
m_flareOcclusionSize = 0.05f;
|
||||
}
|
||||
|
||||
if(e->QueryBoolAttribute("casts_shadow", &m_casts_shadow) != tinyxml2::XML_SUCCESS) {
|
||||
m_casts_shadow = true;
|
||||
}
|
||||
|
||||
if(e->QueryBoolAttribute("light_shafts", &m_light_shafts) != tinyxml2::XML_SUCCESS) {
|
||||
m_light_shafts = true;
|
||||
}
|
||||
|
||||
m_dust_particle_density = 0.1f;
|
||||
if(e->QueryFloatAttribute("dust_particle_density", &m_dust_particle_density) != tinyxml2::XML_SUCCESS) {
|
||||
m_dust_particle_density = 0.1f;
|
||||
}
|
||||
|
||||
m_dust_particle_size = 1.0f;
|
||||
if(e->QueryFloatAttribute("dust_particle_size", &m_dust_particle_size) != tinyxml2::XML_SUCCESS) {
|
||||
m_dust_particle_size = 1.0f;
|
||||
}
|
||||
|
||||
m_dust_particle_intensity = 1.0f;
|
||||
if(e->QueryFloatAttribute("dust_particle_intensity", &m_dust_particle_intensity) != tinyxml2::XML_SUCCESS) {
|
||||
m_dust_particle_intensity = 1.0f;
|
||||
}
|
||||
|
||||
const char *szFlareTexture = e->Attribute("flare_texture");
|
||||
if(szFlareTexture) {
|
||||
m_flareTexture = szFlareTexture;
|
||||
} else {
|
||||
m_flareTexture = "";
|
||||
}
|
||||
m_pFlareTexture = NULL;
|
||||
}
|
||||
|
||||
void KRLight::setFlareTexture(std::string flare_texture) {
|
||||
m_flareTexture = flare_texture;
|
||||
m_pFlareTexture = NULL;
|
||||
}
|
||||
|
||||
void KRLight::setFlareSize(float flare_size) {
|
||||
m_flareSize = flare_size;
|
||||
}
|
||||
|
||||
void KRLight::setFlareOcclusionSize(float occlusion_size) {
|
||||
m_flareOcclusionSize = occlusion_size;
|
||||
}
|
||||
|
||||
void KRLight::setIntensity(float intensity) {
|
||||
m_intensity = intensity;
|
||||
}
|
||||
float KRLight::getIntensity() {
|
||||
return m_intensity;
|
||||
}
|
||||
|
||||
const Vector3 &KRLight::getColor() {
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void KRLight::setColor(const Vector3 &color) {
|
||||
m_color = color;
|
||||
}
|
||||
|
||||
void KRLight::setDecayStart(float decayStart) {
|
||||
m_decayStart = decayStart;
|
||||
}
|
||||
|
||||
float KRLight::getDecayStart() {
|
||||
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) {
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
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))) {
|
||||
allocateShadowBuffers(configureShadowBufferViewports(viewport));
|
||||
renderShadowBuffers(pCamera);
|
||||
}
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES && pCamera->settings.dust_particle_enable) {
|
||||
// Render brownian particles for dust floating in air
|
||||
if(m_cShadowBuffers >= 1 && shadowValid[0] && m_dust_particle_density > 0.0f && m_dust_particle_size > 0.0f && m_dust_particle_intensity > 0.0f) {
|
||||
|
||||
if(viewport.visible(getBounds()) || true) { // FINDME, HACK need to remove "|| true"?
|
||||
|
||||
float particle_range = 600.0f;
|
||||
|
||||
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;
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
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.translate(viewport.getCameraPosition());
|
||||
|
||||
std::vector<KRDirectionalLight *> this_directional_light;
|
||||
std::vector<KRSpotLight *> this_spot_light;
|
||||
std::vector<KRPointLight *> this_point_light;
|
||||
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
|
||||
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
|
||||
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
|
||||
if(directional_light) {
|
||||
this_directional_light.push_back(directional_light);
|
||||
}
|
||||
if(spot_light) {
|
||||
this_spot_light.push_back(spot_light);
|
||||
}
|
||||
if(point_light) {
|
||||
this_point_light.push_back(point_light);
|
||||
}
|
||||
|
||||
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())) {
|
||||
|
||||
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_FLARE_SIZE, m_dust_particle_size);
|
||||
|
||||
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);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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::vector<KRDirectionalLight *> this_directional_light;
|
||||
std::vector<KRSpotLight *> this_spot_light;
|
||||
std::vector<KRPointLight *> this_point_light;
|
||||
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
|
||||
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
|
||||
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
|
||||
if(directional_light) {
|
||||
this_directional_light.push_back(directional_light);
|
||||
}
|
||||
if(spot_light) {
|
||||
this_spot_light.push_back(spot_light);
|
||||
}
|
||||
if(point_light) {
|
||||
this_point_light.push_back(point_light);
|
||||
}
|
||||
|
||||
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())) {
|
||||
int slice_count = (int)(pCamera->settings.volumetric_environment_quality * 495.0) + 5;
|
||||
|
||||
float slice_near = -pCamera->settings.getPerspectiveNearZ();
|
||||
float slice_far = -pCamera->settings.volumetric_environment_max_distance;
|
||||
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_LIGHT_COLOR, (m_color * pCamera->settings.volumetric_environment_intensity * m_intensity * -slice_spacing / 1000.0f));
|
||||
|
||||
KRDataBlock index_data;
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_PARTICLE_OCCLUSION) {
|
||||
if(m_flareTexture.size() && m_flareSize > 0.0f) {
|
||||
|
||||
|
||||
Matrix4 occlusion_test_sphere_matrix = Matrix4();
|
||||
occlusion_test_sphere_matrix.scale(m_localScale * m_flareOcclusionSize);
|
||||
occlusion_test_sphere_matrix.translate(m_localTranslation);
|
||||
if(m_parentNode) {
|
||||
occlusion_test_sphere_matrix *= m_parentNode->getModelMatrix();
|
||||
}
|
||||
|
||||
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));
|
||||
#if TARGET_OS_IPHONE || defined(ANDROID)
|
||||
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
|
||||
#else
|
||||
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
|
||||
#endif
|
||||
|
||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
||||
if(sphereModels.size()) {
|
||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "occlusion_test", 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_OS_IPHONE || defined(ANDROID)
|
||||
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
|
||||
#else
|
||||
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
|
||||
if(m_flareTexture.size() && m_flareSize > 0.0f) {
|
||||
|
||||
if(m_occlusionQuery) {
|
||||
GLuint params = 0;
|
||||
GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, ¶ms));
|
||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
||||
|
||||
if(params) {
|
||||
|
||||
if(!m_pFlareTexture && m_flareTexture.size()) {
|
||||
m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture);
|
||||
}
|
||||
|
||||
if(m_pFlareTexture) {
|
||||
// Disable z-buffer test
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
// 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);
|
||||
|
||||
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_FLARE_SIZE, m_flareSize);
|
||||
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);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void KRLight::allocateShadowBuffers(int cBuffers) {
|
||||
// First deallocate buffers no longer needed
|
||||
for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) {
|
||||
if (shadowDepthTexture[iShadow]) {
|
||||
GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow));
|
||||
shadowDepthTexture[iShadow] = 0;
|
||||
}
|
||||
|
||||
if (shadowFramebuffer[iShadow]) {
|
||||
GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow));
|
||||
shadowFramebuffer[iShadow] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate newly required buffers
|
||||
for(int iShadow = 0; iShadow < cBuffers; iShadow++) {
|
||||
Vector2 viewportSize = m_shadowViewports[iShadow].getSize();
|
||||
|
||||
if(!shadowDepthTexture[iShadow]) {
|
||||
shadowValid[iShadow] = false;
|
||||
|
||||
GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow));
|
||||
GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow));
|
||||
// ===== Create offscreen shadow framebuffer object =====
|
||||
|
||||
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
|
||||
|
||||
// ----- Create Depth Texture for shadowFramebuffer -----
|
||||
GLDEBUG( glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow]));
|
||||
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
||||
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
||||
m_pContext->getTextureManager()->_setWrapModeS(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
|
||||
m_pContext->getTextureManager()->_setWrapModeT(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
|
||||
#if GL_EXT_shadow_samplers
|
||||
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
|
||||
#endif
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
m_cShadowBuffers = cBuffers;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
allocateShadowBuffers(0);
|
||||
}
|
||||
|
||||
void KRLight::invalidateShadowBuffers()
|
||||
{
|
||||
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
|
||||
shadowValid[iShadow] = false;
|
||||
}
|
||||
}
|
||||
|
||||
int KRLight::configureShadowBufferViewports(const KRViewport &viewport)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KRLight::renderShadowBuffers(KRCamera *pCamera)
|
||||
{
|
||||
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
|
||||
if(!shadowValid[iShadow]) {
|
||||
shadowValid[iShadow] = true;
|
||||
|
||||
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
|
||||
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
|
||||
|
||||
GLDEBUG(glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y));
|
||||
|
||||
GLDEBUG(glClearDepthf(0.0f));
|
||||
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
|
||||
|
||||
GLDEBUG(glViewport(1, 1, m_shadowViewports[iShadow].getSize().x - 2, m_shadowViewports[iShadow].getSize().y - 2));
|
||||
|
||||
GLDEBUG(glClearDepthf(1.0f));
|
||||
|
||||
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
|
||||
|
||||
GLDEBUG(glDisable(GL_DITHER));
|
||||
|
||||
//GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts
|
||||
//GLDEBUG(glEnable(GL_CULL_FACE));
|
||||
GLDEBUG(glDisable(GL_CULL_FACE));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LESS));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
// Disable alpha blending as we are using alpha channel for packed depth info
|
||||
GLDEBUG(glDisable(GL_BLEND));
|
||||
|
||||
// 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);
|
||||
|
||||
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);
|
||||
|
||||
GLDEBUG(glEnable(GL_CULL_FACE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int KRLight::getShadowBufferCount()
|
||||
{
|
||||
int cBuffers=0;
|
||||
for(int iBuffer=0; iBuffer < m_cShadowBuffers; iBuffer++) {
|
||||
if(shadowValid[iBuffer]) {
|
||||
cBuffers++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cBuffers;
|
||||
}
|
||||
|
||||
GLuint *KRLight::getShadowTextures()
|
||||
{
|
||||
return shadowDepthTexture;
|
||||
}
|
||||
|
||||
KRViewport *KRLight::getShadowViewports()
|
||||
{
|
||||
return m_shadowViewports;
|
||||
}
|
||||
|
||||
@@ -1,422 +1,422 @@
|
||||
//
|
||||
// KRMaterial.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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
|
||||
// provided with the distribution.
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// 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
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRMaterial.h"
|
||||
#include "KRTextureManager.h"
|
||||
|
||||
#include "KRContext.h"
|
||||
|
||||
KRMaterial::KRMaterial(KRContext &context, const char *szName) : KRResource(context, szName) {
|
||||
m_name = szName;
|
||||
m_pAmbientMap = NULL;
|
||||
m_pDiffuseMap = NULL;
|
||||
m_pSpecularMap = NULL;
|
||||
m_pNormalMap = NULL;
|
||||
m_pReflectionMap = NULL;
|
||||
m_pReflectionCube = NULL;
|
||||
m_ambientColor = Vector3::Zero();
|
||||
m_diffuseColor = Vector3::One();
|
||||
m_specularColor = Vector3::One();
|
||||
m_reflectionColor = Vector3::Zero();
|
||||
m_tr = (GLfloat)1.0f;
|
||||
m_ns = (GLfloat)0.0f;
|
||||
m_ambientMap = "";
|
||||
m_diffuseMap = "";
|
||||
m_specularMap = "";
|
||||
m_normalMap = "";
|
||||
m_reflectionMap = "";
|
||||
m_reflectionCube = "";
|
||||
m_ambientMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||
m_specularMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||
m_diffuseMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||
m_ambientMapScale = Vector2::Create(1.0f, 1.0f);
|
||||
m_specularMapScale = Vector2::Create(1.0f, 1.0f);
|
||||
m_diffuseMapScale = Vector2::Create(1.0f, 1.0f);
|
||||
m_reflectionMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||
m_reflectionMapScale = Vector2::Create(1.0f, 1.0f);
|
||||
m_alpha_mode = KRMATERIAL_ALPHA_MODE_OPAQUE;
|
||||
}
|
||||
|
||||
KRMaterial::~KRMaterial() {
|
||||
|
||||
}
|
||||
|
||||
std::string KRMaterial::getExtension() {
|
||||
return "mtl";
|
||||
}
|
||||
|
||||
bool KRMaterial::needsVertexTangents()
|
||||
{
|
||||
return m_normalMap.size() > 0;
|
||||
}
|
||||
|
||||
bool KRMaterial::save(KRDataBlock &data) {
|
||||
std::stringstream stream;
|
||||
stream.precision(std::numeric_limits<long double>::digits10);
|
||||
stream.setf(std::ios::fixed,std::ios::floatfield);
|
||||
|
||||
stream << "newmtl " << m_name;
|
||||
stream << "\nka " << m_ambientColor.x << " " << m_ambientColor.y << " " << m_ambientColor.z;
|
||||
stream << "\nkd " << m_diffuseColor.x << " " << m_diffuseColor.y << " " << m_diffuseColor.z;
|
||||
stream << "\nks " << m_specularColor.x << " " << m_specularColor.y << " " << m_specularColor.z;
|
||||
stream << "\nkr " << m_reflectionColor.x << " " << m_reflectionColor.y << " " << m_reflectionColor.z;
|
||||
stream << "\nTr " << m_tr;
|
||||
stream << "\nNs " << m_ns;
|
||||
if(m_ambientMap.size()) {
|
||||
stream << "\nmap_Ka " << m_ambientMap << ".pvr -s " << m_ambientMapScale.x << " " << m_ambientMapScale.y << " -o " << m_ambientMapOffset.x << " " << m_ambientMapOffset.y;
|
||||
} else {
|
||||
stream << "\n# map_Ka filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_diffuseMap.size()) {
|
||||
stream << "\nmap_Kd " << m_diffuseMap << ".pvr -s " << m_diffuseMapScale.x << " " << m_diffuseMapScale.y << " -o " << m_diffuseMapOffset.x << " " << m_diffuseMapOffset.y;
|
||||
} else {
|
||||
stream << "\n# map_Kd filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_specularMap.size()) {
|
||||
stream << "\nmap_Ks " << m_specularMap << ".pvr -s " << m_specularMapScale.x << " " << m_specularMapScale.y << " -o " << m_specularMapOffset.x << " " << m_specularMapOffset.y << "\n";
|
||||
} else {
|
||||
stream << "\n# map_Ks filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_normalMap.size()) {
|
||||
stream << "\nmap_Normal " << m_normalMap << ".pvr -s " << m_normalMapScale.x << " " << m_normalMapScale.y << " -o " << m_normalMapOffset.x << " " << m_normalMapOffset.y;
|
||||
} else {
|
||||
stream << "\n# map_Normal filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_reflectionMap.size()) {
|
||||
stream << "\nmap_Reflection " << m_reflectionMap << ".pvr -s " << m_reflectionMapScale.x << " " << m_reflectionMapScale.y << " -o " << m_reflectionMapOffset.x << " " << m_reflectionMapOffset.y;
|
||||
} else {
|
||||
stream << "\n# map_Reflection filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_reflectionCube.size()) {
|
||||
stream << "\nmap_ReflectionCube " << m_reflectionCube << ".pvr";
|
||||
} else {
|
||||
stream << "\n# map_ReflectionCube cubemapname";
|
||||
}
|
||||
switch(m_alpha_mode) {
|
||||
case KRMATERIAL_ALPHA_MODE_OPAQUE:
|
||||
stream << "\nalpha_mode opaque";
|
||||
break;
|
||||
case KRMATERIAL_ALPHA_MODE_TEST:
|
||||
stream << "\nalpha_mode test";
|
||||
break;
|
||||
case KRMATERIAL_ALPHA_MODE_BLENDONESIDE:
|
||||
stream << "\nalpha_mode blendoneside";
|
||||
break;
|
||||
case KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE:
|
||||
stream << "\nalpha_mode blendtwoside";
|
||||
break;
|
||||
}
|
||||
stream << "\n# alpha_mode opaque, test, blendoneside, or blendtwoside";
|
||||
|
||||
stream << "\n";
|
||||
data.append(stream.str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void KRMaterial::setAmbientMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_ambientMap = texture_name;
|
||||
m_ambientMapScale = texture_scale;
|
||||
m_ambientMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setDiffuseMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_diffuseMap = texture_name;
|
||||
m_diffuseMapScale = texture_scale;
|
||||
m_diffuseMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setSpecularMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_specularMap = texture_name;
|
||||
m_specularMapScale = texture_scale;
|
||||
m_specularMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setNormalMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_normalMap = texture_name;
|
||||
m_normalMapScale = texture_scale;
|
||||
m_normalMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setReflectionMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_reflectionMap = texture_name;
|
||||
m_reflectionMapScale = texture_scale;
|
||||
m_reflectionMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setReflectionCube(std::string texture_name) {
|
||||
m_reflectionCube = texture_name;
|
||||
}
|
||||
|
||||
void KRMaterial::setAlphaMode(KRMaterial::alpha_mode_type alpha_mode) {
|
||||
m_alpha_mode = alpha_mode;
|
||||
}
|
||||
|
||||
KRMaterial::alpha_mode_type KRMaterial::getAlphaMode() {
|
||||
return m_alpha_mode;
|
||||
}
|
||||
|
||||
void KRMaterial::setAmbient(const Vector3 &c) {
|
||||
m_ambientColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setDiffuse(const Vector3 &c) {
|
||||
m_diffuseColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setSpecular(const Vector3 &c) {
|
||||
m_specularColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setReflection(const Vector3 &c) {
|
||||
m_reflectionColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setTransparency(GLfloat a) {
|
||||
if(a < 1.0f && m_alpha_mode == KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE) {
|
||||
setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
|
||||
}
|
||||
m_tr = a;
|
||||
}
|
||||
|
||||
void KRMaterial::setShininess(GLfloat s) {
|
||||
m_ns = s;
|
||||
}
|
||||
|
||||
bool KRMaterial::isTransparent() {
|
||||
return m_tr < 1.0 || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE;
|
||||
}
|
||||
|
||||
void KRMaterial::preStream(float lodCoverage)
|
||||
{
|
||||
getTextures();
|
||||
|
||||
if(m_pAmbientMap) {
|
||||
m_pAmbientMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_AMBIENT_MAP);
|
||||
}
|
||||
|
||||
if(m_pDiffuseMap) {
|
||||
m_pDiffuseMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
|
||||
}
|
||||
|
||||
if(m_pNormalMap) {
|
||||
m_pNormalMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
|
||||
}
|
||||
|
||||
if(m_pSpecularMap) {
|
||||
m_pSpecularMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
|
||||
}
|
||||
|
||||
if(m_pReflectionMap) {
|
||||
m_pReflectionMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
|
||||
}
|
||||
|
||||
if(m_pReflectionCube) {
|
||||
m_pReflectionCube->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
kraken_stream_level KRMaterial::getStreamLevel()
|
||||
{
|
||||
kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ;
|
||||
|
||||
getTextures();
|
||||
|
||||
if(m_pAmbientMap) {
|
||||
stream_level = KRMIN(stream_level, m_pAmbientMap->getStreamLevel(KRTexture::TEXTURE_USAGE_AMBIENT_MAP));
|
||||
}
|
||||
|
||||
if(m_pDiffuseMap) {
|
||||
stream_level = KRMIN(stream_level, m_pDiffuseMap->getStreamLevel(KRTexture::TEXTURE_USAGE_DIFFUSE_MAP));
|
||||
}
|
||||
|
||||
if(m_pNormalMap) {
|
||||
stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(KRTexture::TEXTURE_USAGE_NORMAL_MAP));
|
||||
}
|
||||
|
||||
if(m_pSpecularMap) {
|
||||
stream_level = KRMIN(stream_level, m_pSpecularMap->getStreamLevel(KRTexture::TEXTURE_USAGE_SPECULAR_MAP));
|
||||
}
|
||||
|
||||
if(m_pReflectionMap) {
|
||||
stream_level = KRMIN(stream_level, m_pReflectionMap->getStreamLevel(KRTexture::TEXTURE_USAGE_REFLECTION_MAP));
|
||||
}
|
||||
|
||||
if(m_pReflectionCube) {
|
||||
stream_level = KRMIN(stream_level, m_pReflectionCube->getStreamLevel(KRTexture::TEXTURE_USAGE_REFECTION_CUBE));
|
||||
}
|
||||
|
||||
return stream_level;
|
||||
}
|
||||
|
||||
void KRMaterial::getTextures()
|
||||
{
|
||||
if(!m_pAmbientMap && m_ambientMap.size()) {
|
||||
m_pAmbientMap = getContext().getTextureManager()->getTexture(m_ambientMap);
|
||||
}
|
||||
if(!m_pDiffuseMap && m_diffuseMap.size()) {
|
||||
m_pDiffuseMap = getContext().getTextureManager()->getTexture(m_diffuseMap);
|
||||
}
|
||||
if(!m_pNormalMap && m_normalMap.size()) {
|
||||
m_pNormalMap = getContext().getTextureManager()->getTexture(m_normalMap);
|
||||
}
|
||||
if(!m_pSpecularMap && m_specularMap.size()) {
|
||||
m_pSpecularMap = getContext().getTextureManager()->getTexture(m_specularMap);
|
||||
}
|
||||
if(!m_pReflectionMap && m_reflectionMap.size()) {
|
||||
m_pReflectionMap = getContext().getTextureManager()->getTexture(m_reflectionMap);
|
||||
}
|
||||
if(!m_pReflectionCube && m_reflectionCube.size()) {
|
||||
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 bLightMap = pLightMap && pCamera->settings.bEnableLightMap;
|
||||
|
||||
getTextures();
|
||||
|
||||
Vector2 default_scale = Vector2::One();
|
||||
Vector2 default_offset = Vector2::Zero();
|
||||
|
||||
bool bHasReflection = m_reflectionColor != Vector3::Zero();
|
||||
bool bDiffuseMap = m_pDiffuseMap != NULL && pCamera->settings.bEnableDiffuseMap;
|
||||
bool bNormalMap = m_pNormalMap != NULL && pCamera->settings.bEnableNormalMap;
|
||||
bool bSpecMap = m_pSpecularMap != NULL && pCamera->settings.bEnableSpecMap;
|
||||
bool bReflectionMap = m_pReflectionMap != NULL && pCamera->settings.bEnableReflectionMap && pCamera->settings.bEnableReflection && bHasReflection;
|
||||
bool bReflectionCubeMap = m_pReflectionCube != NULL && pCamera->settings.bEnableReflection && bHasReflection;
|
||||
bool bAlphaTest = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_TEST) && bDiffuseMap;
|
||||
bool bAlphaBlend = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE) || (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
|
||||
|
||||
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;
|
||||
if(!getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, matModel, point_lights, directional_lights, spot_lights, 0, renderPass, rim_color, rim_power, fade_color)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bind bones
|
||||
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
|
||||
GLfloat bone_mats[256 * 16];
|
||||
GLfloat *bone_mat_component = bone_mats;
|
||||
for(int bone_index=0; bone_index < bones.size(); bone_index++) {
|
||||
KRBone *bone = bones[bone_index];
|
||||
|
||||
// Vector3 initialRotation = bone->getInitialLocalRotation();
|
||||
// Vector3 rotation = bone->getLocalRotation();
|
||||
// Vector3 initialTranslation = bone->getInitialLocalTranslation();
|
||||
// Vector3 translation = bone->getLocalTranslation();
|
||||
// Vector3 initialScale = bone->getInitialLocalScale();
|
||||
// Vector3 scale = bone->getLocalScale();
|
||||
//
|
||||
//printf("%s - delta rotation: %.4f %.4f %.4f\n", bone->getName().c_str(), (rotation.x - initialRotation.x) * 180.0 / M_PI, (rotation.y - initialRotation.y) * 180.0 / M_PI, (rotation.z - initialRotation.z) * 180.0 / M_PI);
|
||||
//printf("%s - delta translation: %.4f %.4f %.4f\n", bone->getName().c_str(), translation.x - initialTranslation.x, translation.y - initialTranslation.y, translation.z - initialTranslation.z);
|
||||
// printf("%s - delta scale: %.4f %.4f %.4f\n", bone->getName().c_str(), scale.x - initialScale.x, scale.y - initialScale.y, scale.z - initialScale.z);
|
||||
|
||||
Matrix4 skin_bone_bind_pose = bind_poses[bone_index];
|
||||
Matrix4 active_mat = bone->getActivePoseMatrix();
|
||||
Matrix4 inv_bind_mat = bone->getInverseBindPoseMatrix();
|
||||
Matrix4 inv_bind_mat2 = Matrix4::Invert(bind_poses[bone_index]);
|
||||
Matrix4 t = (inv_bind_mat * active_mat);
|
||||
Matrix4 t2 = inv_bind_mat2 * bone->getModelMatrix();
|
||||
for(int i=0; i < 16; i++) {
|
||||
*bone_mat_component++ = t[i];
|
||||
}
|
||||
}
|
||||
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
|
||||
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);
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
|
||||
// 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));
|
||||
} else {
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, m_diffuseColor);
|
||||
}
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
|
||||
// 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));
|
||||
} else {
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SPECULAR, m_specularColor);
|
||||
}
|
||||
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SHININESS, m_ns);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_REFLECTION, m_reflectionColor);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_SCALE, m_diffuseMapScale);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_SCALE, m_specularMapScale);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_SCALE, m_reflectionMapScale);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_SCALE, m_normalMapScale);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_OFFSET, m_diffuseMapOffset);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_OFFSET, m_specularMapOffset);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_OFFSET, m_reflectionMapOffset);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_OFFSET, m_normalMapOffset);
|
||||
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_tr);
|
||||
|
||||
if(bDiffuseMap) {
|
||||
m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap, lod_coverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
|
||||
}
|
||||
|
||||
if(bSpecMap) {
|
||||
m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap, lod_coverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
|
||||
}
|
||||
|
||||
if(bNormalMap) {
|
||||
m_pContext->getTextureManager()->selectTexture(2, m_pNormalMap, lod_coverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
|
||||
}
|
||||
|
||||
if(bReflectionCubeMap && (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);
|
||||
}
|
||||
|
||||
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
|
||||
m_pContext->getTextureManager()->selectTexture(7, m_pReflectionMap, lod_coverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string &KRMaterial::getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
//
|
||||
// KRMaterial.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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
|
||||
// provided with the distribution.
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// 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
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRMaterial.h"
|
||||
#include "KRTextureManager.h"
|
||||
|
||||
#include "KRContext.h"
|
||||
|
||||
KRMaterial::KRMaterial(KRContext &context, const char *szName) : KRResource(context, szName) {
|
||||
m_name = szName;
|
||||
m_pAmbientMap = NULL;
|
||||
m_pDiffuseMap = NULL;
|
||||
m_pSpecularMap = NULL;
|
||||
m_pNormalMap = NULL;
|
||||
m_pReflectionMap = NULL;
|
||||
m_pReflectionCube = NULL;
|
||||
m_ambientColor = Vector3::Zero();
|
||||
m_diffuseColor = Vector3::One();
|
||||
m_specularColor = Vector3::One();
|
||||
m_reflectionColor = Vector3::Zero();
|
||||
m_tr = (GLfloat)1.0f;
|
||||
m_ns = (GLfloat)0.0f;
|
||||
m_ambientMap = "";
|
||||
m_diffuseMap = "";
|
||||
m_specularMap = "";
|
||||
m_normalMap = "";
|
||||
m_reflectionMap = "";
|
||||
m_reflectionCube = "";
|
||||
m_ambientMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||
m_specularMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||
m_diffuseMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||
m_ambientMapScale = Vector2::Create(1.0f, 1.0f);
|
||||
m_specularMapScale = Vector2::Create(1.0f, 1.0f);
|
||||
m_diffuseMapScale = Vector2::Create(1.0f, 1.0f);
|
||||
m_reflectionMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||
m_reflectionMapScale = Vector2::Create(1.0f, 1.0f);
|
||||
m_alpha_mode = KRMATERIAL_ALPHA_MODE_OPAQUE;
|
||||
}
|
||||
|
||||
KRMaterial::~KRMaterial() {
|
||||
|
||||
}
|
||||
|
||||
std::string KRMaterial::getExtension() {
|
||||
return "mtl";
|
||||
}
|
||||
|
||||
bool KRMaterial::needsVertexTangents()
|
||||
{
|
||||
return m_normalMap.size() > 0;
|
||||
}
|
||||
|
||||
bool KRMaterial::save(KRDataBlock &data) {
|
||||
std::stringstream stream;
|
||||
stream.precision(std::numeric_limits<long double>::digits10);
|
||||
stream.setf(std::ios::fixed,std::ios::floatfield);
|
||||
|
||||
stream << "newmtl " << m_name;
|
||||
stream << "\nka " << m_ambientColor.x << " " << m_ambientColor.y << " " << m_ambientColor.z;
|
||||
stream << "\nkd " << m_diffuseColor.x << " " << m_diffuseColor.y << " " << m_diffuseColor.z;
|
||||
stream << "\nks " << m_specularColor.x << " " << m_specularColor.y << " " << m_specularColor.z;
|
||||
stream << "\nkr " << m_reflectionColor.x << " " << m_reflectionColor.y << " " << m_reflectionColor.z;
|
||||
stream << "\nTr " << m_tr;
|
||||
stream << "\nNs " << m_ns;
|
||||
if(m_ambientMap.size()) {
|
||||
stream << "\nmap_Ka " << m_ambientMap << ".pvr -s " << m_ambientMapScale.x << " " << m_ambientMapScale.y << " -o " << m_ambientMapOffset.x << " " << m_ambientMapOffset.y;
|
||||
} else {
|
||||
stream << "\n# map_Ka filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_diffuseMap.size()) {
|
||||
stream << "\nmap_Kd " << m_diffuseMap << ".pvr -s " << m_diffuseMapScale.x << " " << m_diffuseMapScale.y << " -o " << m_diffuseMapOffset.x << " " << m_diffuseMapOffset.y;
|
||||
} else {
|
||||
stream << "\n# map_Kd filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_specularMap.size()) {
|
||||
stream << "\nmap_Ks " << m_specularMap << ".pvr -s " << m_specularMapScale.x << " " << m_specularMapScale.y << " -o " << m_specularMapOffset.x << " " << m_specularMapOffset.y << "\n";
|
||||
} else {
|
||||
stream << "\n# map_Ks filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_normalMap.size()) {
|
||||
stream << "\nmap_Normal " << m_normalMap << ".pvr -s " << m_normalMapScale.x << " " << m_normalMapScale.y << " -o " << m_normalMapOffset.x << " " << m_normalMapOffset.y;
|
||||
} else {
|
||||
stream << "\n# map_Normal filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_reflectionMap.size()) {
|
||||
stream << "\nmap_Reflection " << m_reflectionMap << ".pvr -s " << m_reflectionMapScale.x << " " << m_reflectionMapScale.y << " -o " << m_reflectionMapOffset.x << " " << m_reflectionMapOffset.y;
|
||||
} else {
|
||||
stream << "\n# map_Reflection filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_reflectionCube.size()) {
|
||||
stream << "\nmap_ReflectionCube " << m_reflectionCube << ".pvr";
|
||||
} else {
|
||||
stream << "\n# map_ReflectionCube cubemapname";
|
||||
}
|
||||
switch(m_alpha_mode) {
|
||||
case KRMATERIAL_ALPHA_MODE_OPAQUE:
|
||||
stream << "\nalpha_mode opaque";
|
||||
break;
|
||||
case KRMATERIAL_ALPHA_MODE_TEST:
|
||||
stream << "\nalpha_mode test";
|
||||
break;
|
||||
case KRMATERIAL_ALPHA_MODE_BLENDONESIDE:
|
||||
stream << "\nalpha_mode blendoneside";
|
||||
break;
|
||||
case KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE:
|
||||
stream << "\nalpha_mode blendtwoside";
|
||||
break;
|
||||
}
|
||||
stream << "\n# alpha_mode opaque, test, blendoneside, or blendtwoside";
|
||||
|
||||
stream << "\n";
|
||||
data.append(stream.str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void KRMaterial::setAmbientMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_ambientMap = texture_name;
|
||||
m_ambientMapScale = texture_scale;
|
||||
m_ambientMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setDiffuseMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_diffuseMap = texture_name;
|
||||
m_diffuseMapScale = texture_scale;
|
||||
m_diffuseMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setSpecularMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_specularMap = texture_name;
|
||||
m_specularMapScale = texture_scale;
|
||||
m_specularMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setNormalMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_normalMap = texture_name;
|
||||
m_normalMapScale = texture_scale;
|
||||
m_normalMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setReflectionMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_reflectionMap = texture_name;
|
||||
m_reflectionMapScale = texture_scale;
|
||||
m_reflectionMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setReflectionCube(std::string texture_name) {
|
||||
m_reflectionCube = texture_name;
|
||||
}
|
||||
|
||||
void KRMaterial::setAlphaMode(KRMaterial::alpha_mode_type alpha_mode) {
|
||||
m_alpha_mode = alpha_mode;
|
||||
}
|
||||
|
||||
KRMaterial::alpha_mode_type KRMaterial::getAlphaMode() {
|
||||
return m_alpha_mode;
|
||||
}
|
||||
|
||||
void KRMaterial::setAmbient(const Vector3 &c) {
|
||||
m_ambientColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setDiffuse(const Vector3 &c) {
|
||||
m_diffuseColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setSpecular(const Vector3 &c) {
|
||||
m_specularColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setReflection(const Vector3 &c) {
|
||||
m_reflectionColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setTransparency(GLfloat a) {
|
||||
if(a < 1.0f && m_alpha_mode == KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE) {
|
||||
setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
|
||||
}
|
||||
m_tr = a;
|
||||
}
|
||||
|
||||
void KRMaterial::setShininess(GLfloat s) {
|
||||
m_ns = s;
|
||||
}
|
||||
|
||||
bool KRMaterial::isTransparent() {
|
||||
return m_tr < 1.0 || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE;
|
||||
}
|
||||
|
||||
void KRMaterial::preStream(float lodCoverage)
|
||||
{
|
||||
getTextures();
|
||||
|
||||
if(m_pAmbientMap) {
|
||||
m_pAmbientMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_AMBIENT_MAP);
|
||||
}
|
||||
|
||||
if(m_pDiffuseMap) {
|
||||
m_pDiffuseMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
|
||||
}
|
||||
|
||||
if(m_pNormalMap) {
|
||||
m_pNormalMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
|
||||
}
|
||||
|
||||
if(m_pSpecularMap) {
|
||||
m_pSpecularMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
|
||||
}
|
||||
|
||||
if(m_pReflectionMap) {
|
||||
m_pReflectionMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
|
||||
}
|
||||
|
||||
if(m_pReflectionCube) {
|
||||
m_pReflectionCube->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
kraken_stream_level KRMaterial::getStreamLevel()
|
||||
{
|
||||
kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ;
|
||||
|
||||
getTextures();
|
||||
|
||||
if(m_pAmbientMap) {
|
||||
stream_level = KRMIN(stream_level, m_pAmbientMap->getStreamLevel(KRTexture::TEXTURE_USAGE_AMBIENT_MAP));
|
||||
}
|
||||
|
||||
if(m_pDiffuseMap) {
|
||||
stream_level = KRMIN(stream_level, m_pDiffuseMap->getStreamLevel(KRTexture::TEXTURE_USAGE_DIFFUSE_MAP));
|
||||
}
|
||||
|
||||
if(m_pNormalMap) {
|
||||
stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(KRTexture::TEXTURE_USAGE_NORMAL_MAP));
|
||||
}
|
||||
|
||||
if(m_pSpecularMap) {
|
||||
stream_level = KRMIN(stream_level, m_pSpecularMap->getStreamLevel(KRTexture::TEXTURE_USAGE_SPECULAR_MAP));
|
||||
}
|
||||
|
||||
if(m_pReflectionMap) {
|
||||
stream_level = KRMIN(stream_level, m_pReflectionMap->getStreamLevel(KRTexture::TEXTURE_USAGE_REFLECTION_MAP));
|
||||
}
|
||||
|
||||
if(m_pReflectionCube) {
|
||||
stream_level = KRMIN(stream_level, m_pReflectionCube->getStreamLevel(KRTexture::TEXTURE_USAGE_REFECTION_CUBE));
|
||||
}
|
||||
|
||||
return stream_level;
|
||||
}
|
||||
|
||||
void KRMaterial::getTextures()
|
||||
{
|
||||
if(!m_pAmbientMap && m_ambientMap.size()) {
|
||||
m_pAmbientMap = getContext().getTextureManager()->getTexture(m_ambientMap);
|
||||
}
|
||||
if(!m_pDiffuseMap && m_diffuseMap.size()) {
|
||||
m_pDiffuseMap = getContext().getTextureManager()->getTexture(m_diffuseMap);
|
||||
}
|
||||
if(!m_pNormalMap && m_normalMap.size()) {
|
||||
m_pNormalMap = getContext().getTextureManager()->getTexture(m_normalMap);
|
||||
}
|
||||
if(!m_pSpecularMap && m_specularMap.size()) {
|
||||
m_pSpecularMap = getContext().getTextureManager()->getTexture(m_specularMap);
|
||||
}
|
||||
if(!m_pReflectionMap && m_reflectionMap.size()) {
|
||||
m_pReflectionMap = getContext().getTextureManager()->getTexture(m_reflectionMap);
|
||||
}
|
||||
if(!m_pReflectionCube && m_reflectionCube.size()) {
|
||||
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 bLightMap = pLightMap && pCamera->settings.bEnableLightMap;
|
||||
|
||||
getTextures();
|
||||
|
||||
Vector2 default_scale = Vector2::One();
|
||||
Vector2 default_offset = Vector2::Zero();
|
||||
|
||||
bool bHasReflection = m_reflectionColor != Vector3::Zero();
|
||||
bool bDiffuseMap = m_pDiffuseMap != NULL && pCamera->settings.bEnableDiffuseMap;
|
||||
bool bNormalMap = m_pNormalMap != NULL && pCamera->settings.bEnableNormalMap;
|
||||
bool bSpecMap = m_pSpecularMap != NULL && pCamera->settings.bEnableSpecMap;
|
||||
bool bReflectionMap = m_pReflectionMap != NULL && pCamera->settings.bEnableReflectionMap && pCamera->settings.bEnableReflection && bHasReflection;
|
||||
bool bReflectionCubeMap = m_pReflectionCube != NULL && pCamera->settings.bEnableReflection && bHasReflection;
|
||||
bool bAlphaTest = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_TEST) && bDiffuseMap;
|
||||
bool bAlphaBlend = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE) || (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
|
||||
|
||||
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;
|
||||
if(!getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, matModel, point_lights, directional_lights, spot_lights, 0, renderPass, rim_color, rim_power, fade_color)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bind bones
|
||||
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
|
||||
GLfloat bone_mats[256 * 16];
|
||||
GLfloat *bone_mat_component = bone_mats;
|
||||
for(int bone_index=0; bone_index < bones.size(); bone_index++) {
|
||||
KRBone *bone = bones[bone_index];
|
||||
|
||||
// Vector3 initialRotation = bone->getInitialLocalRotation();
|
||||
// Vector3 rotation = bone->getLocalRotation();
|
||||
// Vector3 initialTranslation = bone->getInitialLocalTranslation();
|
||||
// Vector3 translation = bone->getLocalTranslation();
|
||||
// Vector3 initialScale = bone->getInitialLocalScale();
|
||||
// Vector3 scale = bone->getLocalScale();
|
||||
//
|
||||
//printf("%s - delta rotation: %.4f %.4f %.4f\n", bone->getName().c_str(), (rotation.x - initialRotation.x) * 180.0 / M_PI, (rotation.y - initialRotation.y) * 180.0 / M_PI, (rotation.z - initialRotation.z) * 180.0 / M_PI);
|
||||
//printf("%s - delta translation: %.4f %.4f %.4f\n", bone->getName().c_str(), translation.x - initialTranslation.x, translation.y - initialTranslation.y, translation.z - initialTranslation.z);
|
||||
// printf("%s - delta scale: %.4f %.4f %.4f\n", bone->getName().c_str(), scale.x - initialScale.x, scale.y - initialScale.y, scale.z - initialScale.z);
|
||||
|
||||
Matrix4 skin_bone_bind_pose = bind_poses[bone_index];
|
||||
Matrix4 active_mat = bone->getActivePoseMatrix();
|
||||
Matrix4 inv_bind_mat = bone->getInverseBindPoseMatrix();
|
||||
Matrix4 inv_bind_mat2 = Matrix4::Invert(bind_poses[bone_index]);
|
||||
Matrix4 t = (inv_bind_mat * active_mat);
|
||||
Matrix4 t2 = inv_bind_mat2 * bone->getModelMatrix();
|
||||
for(int i=0; i < 16; i++) {
|
||||
*bone_mat_component++ = t[i];
|
||||
}
|
||||
}
|
||||
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
|
||||
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);
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
|
||||
// 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));
|
||||
} else {
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, m_diffuseColor);
|
||||
}
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
|
||||
// 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));
|
||||
} else {
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SPECULAR, m_specularColor);
|
||||
}
|
||||
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SHININESS, m_ns);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_REFLECTION, m_reflectionColor);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_SCALE, m_diffuseMapScale);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_SCALE, m_specularMapScale);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_SCALE, m_reflectionMapScale);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_SCALE, m_normalMapScale);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_OFFSET, m_diffuseMapOffset);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_OFFSET, m_specularMapOffset);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_OFFSET, m_reflectionMapOffset);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_OFFSET, m_normalMapOffset);
|
||||
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_tr);
|
||||
|
||||
if(bDiffuseMap) {
|
||||
m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap, lod_coverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
|
||||
}
|
||||
|
||||
if(bSpecMap) {
|
||||
m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap, lod_coverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
|
||||
}
|
||||
|
||||
if(bNormalMap) {
|
||||
m_pContext->getTextureManager()->selectTexture(2, m_pNormalMap, lod_coverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
|
||||
}
|
||||
|
||||
if(bReflectionCubeMap && (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);
|
||||
}
|
||||
|
||||
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
|
||||
m_pContext->getTextureManager()->selectTexture(7, m_pReflectionMap, lod_coverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string &KRMaterial::getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,288 +1,288 @@
|
||||
//
|
||||
// KRMaterialManager.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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
|
||||
// provided with the distribution.
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// 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
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRMaterialManager.h"
|
||||
|
||||
|
||||
KRMaterialManager::KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRShaderManager *pShaderManager) : KRContextObject(context)
|
||||
{
|
||||
m_pTextureManager = pTextureManager;
|
||||
m_pShaderManager = pShaderManager;
|
||||
}
|
||||
|
||||
KRMaterialManager::~KRMaterialManager() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
unordered_map<std::string, KRMaterial *> &KRMaterialManager::getMaterials()
|
||||
{
|
||||
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) {
|
||||
if(blend_enable) {
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(blend_src, blend_dest));
|
||||
} else {
|
||||
GLDEBUG(glDisable(GL_BLEND));
|
||||
}
|
||||
|
||||
if(depth_test_enable) {
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(depth_func));
|
||||
} else {
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
}
|
||||
|
||||
if(depth_write_enable) {
|
||||
GLDEBUG(glDepthMask(GL_TRUE));
|
||||
} else {
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
KRMaterial *KRMaterialManager::getMaterial(const std::string &name) {
|
||||
std::string lowerName = name;
|
||||
std::transform(lowerName.begin(), lowerName.end(),
|
||||
lowerName.begin(), ::tolower);
|
||||
|
||||
|
||||
unordered_map<std::string, KRMaterial *>::iterator itr = m_materials.find(lowerName);
|
||||
if(itr == m_materials.end()) {
|
||||
KRContext::Log(KRContext::LOG_LEVEL_WARNING, "Material not found: %s", name.c_str());
|
||||
// Not found
|
||||
return NULL;
|
||||
} else {
|
||||
return (*itr).second;
|
||||
}
|
||||
}
|
||||
|
||||
void KRMaterialManager::add(KRMaterial *new_material) {
|
||||
// FINDME, TODO - Potential memory leak if multiple materials with the same name are added
|
||||
std::string lowerName = new_material->getName();
|
||||
std::transform(lowerName.begin(), lowerName.end(),
|
||||
lowerName.begin(), ::tolower);
|
||||
|
||||
m_materials[lowerName] = new_material;
|
||||
}
|
||||
|
||||
bool KRMaterialManager::load(const char *szName, KRDataBlock *data) {
|
||||
KRMaterial *pMaterial = NULL;
|
||||
char szSymbol[16][256];
|
||||
data->lock();
|
||||
|
||||
char *pScan = (char *)data->getStart();
|
||||
char *pEnd = (char *)data->getEnd();
|
||||
while(pScan < pEnd) {
|
||||
|
||||
// Scan through whitespace
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||
pScan++;
|
||||
}
|
||||
|
||||
if(*pScan == '#') {
|
||||
// Line is a comment line
|
||||
|
||||
// Scan to the end of the line
|
||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||
pScan++;
|
||||
}
|
||||
} else {
|
||||
int cSymbols = 0;
|
||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||
|
||||
char *pDest = szSymbol[cSymbols++];
|
||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||
if(*pScan >= 'A' && *pScan <= 'Z') {
|
||||
*pDest++ = *pScan++ + 'a' - 'A'; // convert to lower case for case sensitve comparison later
|
||||
} else {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// Scan through whitespace, but don't advance to next line
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
||||
pScan++;
|
||||
}
|
||||
}
|
||||
|
||||
if(cSymbols > 0) {
|
||||
|
||||
if(strcmp(szSymbol[0], "newmtl") == 0 && cSymbols >= 2) {
|
||||
|
||||
pMaterial = new KRMaterial(*m_pContext, szSymbol[1]);
|
||||
m_materials[szSymbol[1]] = pMaterial;
|
||||
}
|
||||
if(pMaterial != NULL) {
|
||||
if(strcmp(szSymbol[0], "alpha_mode") == 0) {
|
||||
if(cSymbols == 2) {
|
||||
if(strcmp(szSymbol[1], "test") == 0) {
|
||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_TEST);
|
||||
} else if(strcmp(szSymbol[1], "blendoneside") == 0) {
|
||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
|
||||
} else if(strcmp(szSymbol[1], "blendtwoside") == 0) {
|
||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
|
||||
} else {
|
||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE);
|
||||
}
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "ka") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setAmbient(Vector3::Create(r, r, r));
|
||||
} else if(cSymbols == 4) {
|
||||
pScan2 = szSymbol[2];
|
||||
float g = strtof(pScan2, &pScan2);
|
||||
pScan2 = szSymbol[3];
|
||||
float b = strtof(pScan2, &pScan2);
|
||||
pMaterial->setAmbient(Vector3::Create(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "kd") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setDiffuse(Vector3::Create(r, r, r));
|
||||
} else if(cSymbols == 4) {
|
||||
pScan2 = szSymbol[2];
|
||||
float g = strtof(pScan2, &pScan2);
|
||||
pScan2 = szSymbol[3];
|
||||
float b = strtof(pScan2, &pScan2);
|
||||
pMaterial->setDiffuse(Vector3::Create(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "ks") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setSpecular(Vector3::Create(r, r, r));
|
||||
} else if(cSymbols == 4) {
|
||||
pScan2 = szSymbol[2];
|
||||
float g = strtof(pScan2, &pScan2);
|
||||
pScan2 = szSymbol[3];
|
||||
float b = strtof(pScan2, &pScan2);
|
||||
pMaterial->setSpecular(Vector3::Create(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "kr") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setReflection(Vector3::Create(r, r, r));
|
||||
} else if(cSymbols == 4) {
|
||||
pScan2 = szSymbol[2];
|
||||
float g = strtof(pScan2, &pScan2);
|
||||
pScan2 = szSymbol[3];
|
||||
float b = strtof(pScan2, &pScan2);
|
||||
pMaterial->setReflection(Vector3::Create(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "tr") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float a = strtof(pScan2, &pScan2);
|
||||
pMaterial->setTransparency(a);
|
||||
} else if(strcmp(szSymbol[0], "ns") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float a = strtof(pScan2, &pScan2);
|
||||
pMaterial->setShininess(a);
|
||||
} else if(strncmp(szSymbol[0], "map", 3) == 0) {
|
||||
// Truncate file extension
|
||||
char *pScan2 = szSymbol[1];
|
||||
char *pLastPeriod = NULL;
|
||||
while(*pScan2 != '\0') {
|
||||
if(*pScan2 == '.') {
|
||||
pLastPeriod = pScan2;
|
||||
}
|
||||
pScan2++;
|
||||
}
|
||||
if(pLastPeriod) {
|
||||
*pLastPeriod = '\0';
|
||||
}
|
||||
|
||||
Vector2 texture_scale = Vector2::Create(1.0f, 1.0f);
|
||||
Vector2 texture_offset = Vector2::Create(0.0f, 0.0f);
|
||||
|
||||
int iScanSymbol = 2;
|
||||
int iScaleParam = -1;
|
||||
int iOffsetParam = -1;
|
||||
while(iScanSymbol < cSymbols) {
|
||||
if(strcmp(szSymbol[iScanSymbol], "-s") == 0) {
|
||||
// Scale
|
||||
iScaleParam = 0;
|
||||
iOffsetParam = -1;
|
||||
} else if(strcmp(szSymbol[iScanSymbol], "-o") == 0) {
|
||||
// Offset
|
||||
iOffsetParam = 0;
|
||||
iScaleParam = -1;
|
||||
} else {
|
||||
char *pScan3 = szSymbol[iScanSymbol];
|
||||
float v = strtof(pScan3, &pScan3);
|
||||
if(iScaleParam == 0) {
|
||||
texture_scale.x = v;
|
||||
iScaleParam++;
|
||||
} else if(iScaleParam == 1) {
|
||||
texture_scale.y = v;
|
||||
iScaleParam++;
|
||||
} else if(iOffsetParam == 0) {
|
||||
texture_offset.x = v;
|
||||
iOffsetParam++;
|
||||
} else if(iOffsetParam == 1) {
|
||||
texture_offset.y = v;
|
||||
iOffsetParam++;
|
||||
}
|
||||
}
|
||||
iScanSymbol++;
|
||||
}
|
||||
|
||||
if(strcmp(szSymbol[0], "map_ka") == 0) {
|
||||
pMaterial->setAmbientMap(szSymbol[1], texture_scale, texture_offset);
|
||||
} else if(strcmp(szSymbol[0], "map_kd") == 0) {
|
||||
pMaterial->setDiffuseMap(szSymbol[1], texture_scale, texture_offset);
|
||||
} else if(strcmp(szSymbol[0], "map_ks") == 0) {
|
||||
pMaterial->setSpecularMap(szSymbol[1], texture_scale, texture_offset);
|
||||
} else if(strcmp(szSymbol[0], "map_normal") == 0) {
|
||||
pMaterial->setNormalMap(szSymbol[1], texture_scale, texture_offset);
|
||||
} else if(strcmp(szSymbol[0], "map_reflection") == 0) {
|
||||
pMaterial->setReflectionMap(szSymbol[1], texture_scale, texture_offset);
|
||||
} else if(strcmp(szSymbol[0], "map_reflectioncube") == 0) {
|
||||
pMaterial->setReflectionCube(szSymbol[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
data->unlock();
|
||||
delete data;
|
||||
return true;
|
||||
}
|
||||
//
|
||||
// KRMaterialManager.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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
|
||||
// provided with the distribution.
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// 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
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRMaterialManager.h"
|
||||
|
||||
|
||||
KRMaterialManager::KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRShaderManager *pShaderManager) : KRContextObject(context)
|
||||
{
|
||||
m_pTextureManager = pTextureManager;
|
||||
m_pShaderManager = pShaderManager;
|
||||
}
|
||||
|
||||
KRMaterialManager::~KRMaterialManager() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
unordered_map<std::string, KRMaterial *> &KRMaterialManager::getMaterials()
|
||||
{
|
||||
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) {
|
||||
if(blend_enable) {
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(blend_src, blend_dest));
|
||||
} else {
|
||||
GLDEBUG(glDisable(GL_BLEND));
|
||||
}
|
||||
|
||||
if(depth_test_enable) {
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(depth_func));
|
||||
} else {
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
}
|
||||
|
||||
if(depth_write_enable) {
|
||||
GLDEBUG(glDepthMask(GL_TRUE));
|
||||
} else {
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
KRMaterial *KRMaterialManager::getMaterial(const std::string &name) {
|
||||
std::string lowerName = name;
|
||||
std::transform(lowerName.begin(), lowerName.end(),
|
||||
lowerName.begin(), ::tolower);
|
||||
|
||||
|
||||
unordered_map<std::string, KRMaterial *>::iterator itr = m_materials.find(lowerName);
|
||||
if(itr == m_materials.end()) {
|
||||
KRContext::Log(KRContext::LOG_LEVEL_WARNING, "Material not found: %s", name.c_str());
|
||||
// Not found
|
||||
return NULL;
|
||||
} else {
|
||||
return (*itr).second;
|
||||
}
|
||||
}
|
||||
|
||||
void KRMaterialManager::add(KRMaterial *new_material) {
|
||||
// FINDME, TODO - Potential memory leak if multiple materials with the same name are added
|
||||
std::string lowerName = new_material->getName();
|
||||
std::transform(lowerName.begin(), lowerName.end(),
|
||||
lowerName.begin(), ::tolower);
|
||||
|
||||
m_materials[lowerName] = new_material;
|
||||
}
|
||||
|
||||
bool KRMaterialManager::load(const char *szName, KRDataBlock *data) {
|
||||
KRMaterial *pMaterial = NULL;
|
||||
char szSymbol[16][256];
|
||||
data->lock();
|
||||
|
||||
char *pScan = (char *)data->getStart();
|
||||
char *pEnd = (char *)data->getEnd();
|
||||
while(pScan < pEnd) {
|
||||
|
||||
// Scan through whitespace
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||
pScan++;
|
||||
}
|
||||
|
||||
if(*pScan == '#') {
|
||||
// Line is a comment line
|
||||
|
||||
// Scan to the end of the line
|
||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||
pScan++;
|
||||
}
|
||||
} else {
|
||||
int cSymbols = 0;
|
||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||
|
||||
char *pDest = szSymbol[cSymbols++];
|
||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||
if(*pScan >= 'A' && *pScan <= 'Z') {
|
||||
*pDest++ = *pScan++ + 'a' - 'A'; // convert to lower case for case sensitve comparison later
|
||||
} else {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// Scan through whitespace, but don't advance to next line
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
||||
pScan++;
|
||||
}
|
||||
}
|
||||
|
||||
if(cSymbols > 0) {
|
||||
|
||||
if(strcmp(szSymbol[0], "newmtl") == 0 && cSymbols >= 2) {
|
||||
|
||||
pMaterial = new KRMaterial(*m_pContext, szSymbol[1]);
|
||||
m_materials[szSymbol[1]] = pMaterial;
|
||||
}
|
||||
if(pMaterial != NULL) {
|
||||
if(strcmp(szSymbol[0], "alpha_mode") == 0) {
|
||||
if(cSymbols == 2) {
|
||||
if(strcmp(szSymbol[1], "test") == 0) {
|
||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_TEST);
|
||||
} else if(strcmp(szSymbol[1], "blendoneside") == 0) {
|
||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
|
||||
} else if(strcmp(szSymbol[1], "blendtwoside") == 0) {
|
||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
|
||||
} else {
|
||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE);
|
||||
}
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "ka") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setAmbient(Vector3::Create(r, r, r));
|
||||
} else if(cSymbols == 4) {
|
||||
pScan2 = szSymbol[2];
|
||||
float g = strtof(pScan2, &pScan2);
|
||||
pScan2 = szSymbol[3];
|
||||
float b = strtof(pScan2, &pScan2);
|
||||
pMaterial->setAmbient(Vector3::Create(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "kd") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setDiffuse(Vector3::Create(r, r, r));
|
||||
} else if(cSymbols == 4) {
|
||||
pScan2 = szSymbol[2];
|
||||
float g = strtof(pScan2, &pScan2);
|
||||
pScan2 = szSymbol[3];
|
||||
float b = strtof(pScan2, &pScan2);
|
||||
pMaterial->setDiffuse(Vector3::Create(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "ks") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setSpecular(Vector3::Create(r, r, r));
|
||||
} else if(cSymbols == 4) {
|
||||
pScan2 = szSymbol[2];
|
||||
float g = strtof(pScan2, &pScan2);
|
||||
pScan2 = szSymbol[3];
|
||||
float b = strtof(pScan2, &pScan2);
|
||||
pMaterial->setSpecular(Vector3::Create(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "kr") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setReflection(Vector3::Create(r, r, r));
|
||||
} else if(cSymbols == 4) {
|
||||
pScan2 = szSymbol[2];
|
||||
float g = strtof(pScan2, &pScan2);
|
||||
pScan2 = szSymbol[3];
|
||||
float b = strtof(pScan2, &pScan2);
|
||||
pMaterial->setReflection(Vector3::Create(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "tr") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float a = strtof(pScan2, &pScan2);
|
||||
pMaterial->setTransparency(a);
|
||||
} else if(strcmp(szSymbol[0], "ns") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float a = strtof(pScan2, &pScan2);
|
||||
pMaterial->setShininess(a);
|
||||
} else if(strncmp(szSymbol[0], "map", 3) == 0) {
|
||||
// Truncate file extension
|
||||
char *pScan2 = szSymbol[1];
|
||||
char *pLastPeriod = NULL;
|
||||
while(*pScan2 != '\0') {
|
||||
if(*pScan2 == '.') {
|
||||
pLastPeriod = pScan2;
|
||||
}
|
||||
pScan2++;
|
||||
}
|
||||
if(pLastPeriod) {
|
||||
*pLastPeriod = '\0';
|
||||
}
|
||||
|
||||
Vector2 texture_scale = Vector2::Create(1.0f, 1.0f);
|
||||
Vector2 texture_offset = Vector2::Create(0.0f, 0.0f);
|
||||
|
||||
int iScanSymbol = 2;
|
||||
int iScaleParam = -1;
|
||||
int iOffsetParam = -1;
|
||||
while(iScanSymbol < cSymbols) {
|
||||
if(strcmp(szSymbol[iScanSymbol], "-s") == 0) {
|
||||
// Scale
|
||||
iScaleParam = 0;
|
||||
iOffsetParam = -1;
|
||||
} else if(strcmp(szSymbol[iScanSymbol], "-o") == 0) {
|
||||
// Offset
|
||||
iOffsetParam = 0;
|
||||
iScaleParam = -1;
|
||||
} else {
|
||||
char *pScan3 = szSymbol[iScanSymbol];
|
||||
float v = strtof(pScan3, &pScan3);
|
||||
if(iScaleParam == 0) {
|
||||
texture_scale.x = v;
|
||||
iScaleParam++;
|
||||
} else if(iScaleParam == 1) {
|
||||
texture_scale.y = v;
|
||||
iScaleParam++;
|
||||
} else if(iOffsetParam == 0) {
|
||||
texture_offset.x = v;
|
||||
iOffsetParam++;
|
||||
} else if(iOffsetParam == 1) {
|
||||
texture_offset.y = v;
|
||||
iOffsetParam++;
|
||||
}
|
||||
}
|
||||
iScanSymbol++;
|
||||
}
|
||||
|
||||
if(strcmp(szSymbol[0], "map_ka") == 0) {
|
||||
pMaterial->setAmbientMap(szSymbol[1], texture_scale, texture_offset);
|
||||
} else if(strcmp(szSymbol[0], "map_kd") == 0) {
|
||||
pMaterial->setDiffuseMap(szSymbol[1], texture_scale, texture_offset);
|
||||
} else if(strcmp(szSymbol[0], "map_ks") == 0) {
|
||||
pMaterial->setSpecularMap(szSymbol[1], texture_scale, texture_offset);
|
||||
} else if(strcmp(szSymbol[0], "map_normal") == 0) {
|
||||
pMaterial->setNormalMap(szSymbol[1], texture_scale, texture_offset);
|
||||
} else if(strcmp(szSymbol[0], "map_reflection") == 0) {
|
||||
pMaterial->setReflectionMap(szSymbol[1], texture_scale, texture_offset);
|
||||
} else if(strcmp(szSymbol[0], "map_reflectioncube") == 0) {
|
||||
pMaterial->setReflectionCube(szSymbol[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
data->unlock();
|
||||
delete data;
|
||||
return true;
|
||||
}
|
||||
|
||||
3208
kraken/KRMesh.cpp
3208
kraken/KRMesh.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,69 +1,69 @@
|
||||
//
|
||||
// KRMeshCube.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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
|
||||
// provided with the distribution.
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// 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
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#include "KRMeshCube.h"
|
||||
|
||||
|
||||
KRMeshCube::KRMeshCube(KRContext &context) : KRMesh(context, "__cube")
|
||||
{
|
||||
m_constant = true;
|
||||
|
||||
KRMesh::mesh_info mi;
|
||||
|
||||
mi.vertices.push_back(Vector3::Create(1.0, 1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0,-1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0,-1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0,-1.0,-1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0, 1.0,-1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0, 1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0, 1.0,-1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0,-1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0,-1.0,-1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0,-1.0,-1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0, 1.0,-1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0, 1.0,-1.0));
|
||||
|
||||
|
||||
mi.submesh_starts.push_back(0);
|
||||
mi.submesh_lengths.push_back(mi.vertices.size());
|
||||
mi.material_names.push_back("");
|
||||
mi.format = KRENGINE_MODEL_FORMAT_STRIP;
|
||||
|
||||
|
||||
LoadData(mi, true, true);
|
||||
}
|
||||
|
||||
KRMeshCube::~KRMeshCube()
|
||||
{
|
||||
|
||||
}
|
||||
//
|
||||
// KRMeshCube.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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
|
||||
// provided with the distribution.
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// 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
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#include "KRMeshCube.h"
|
||||
|
||||
|
||||
KRMeshCube::KRMeshCube(KRContext &context) : KRMesh(context, "__cube")
|
||||
{
|
||||
m_constant = true;
|
||||
|
||||
KRMesh::mesh_info mi;
|
||||
|
||||
mi.vertices.push_back(Vector3::Create(1.0, 1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0,-1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0,-1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0,-1.0,-1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0, 1.0,-1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0, 1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0, 1.0,-1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0,-1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0,-1.0,-1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0,-1.0,-1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0, 1.0,-1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0, 1.0,-1.0));
|
||||
|
||||
|
||||
mi.submesh_starts.push_back(0);
|
||||
mi.submesh_lengths.push_back(mi.vertices.size());
|
||||
mi.material_names.push_back("");
|
||||
mi.format = KRENGINE_MODEL_FORMAT_STRIP;
|
||||
|
||||
|
||||
LoadData(mi, true, true);
|
||||
}
|
||||
|
||||
KRMeshCube::~KRMeshCube()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -1,63 +1,63 @@
|
||||
//
|
||||
// KRMeshQuad.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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
|
||||
// provided with the distribution.
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// 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
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#include "KRMeshQuad.h"
|
||||
|
||||
|
||||
KRMeshQuad::KRMeshQuad(KRContext &context) : KRMesh(context, "__quad")
|
||||
{
|
||||
m_constant = true;
|
||||
|
||||
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.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(0.0f, 1.0f));
|
||||
mi.uva.push_back(Vector2::Create(1.0f, 1.0f));
|
||||
|
||||
|
||||
mi.submesh_starts.push_back(0);
|
||||
mi.submesh_lengths.push_back(mi.vertices.size());
|
||||
mi.material_names.push_back("");
|
||||
mi.format = KRENGINE_MODEL_FORMAT_STRIP;
|
||||
|
||||
LoadData(mi, true, true);
|
||||
}
|
||||
|
||||
KRMeshQuad::~KRMeshQuad()
|
||||
{
|
||||
|
||||
}
|
||||
//
|
||||
// KRMeshQuad.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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
|
||||
// provided with the distribution.
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// 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
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#include "KRMeshQuad.h"
|
||||
|
||||
|
||||
KRMeshQuad::KRMeshQuad(KRContext &context) : KRMesh(context, "__quad")
|
||||
{
|
||||
m_constant = true;
|
||||
|
||||
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.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(0.0f, 1.0f));
|
||||
mi.uva.push_back(Vector2::Create(1.0f, 1.0f));
|
||||
|
||||
|
||||
mi.submesh_starts.push_back(0);
|
||||
mi.submesh_lengths.push_back(mi.vertices.size());
|
||||
mi.material_names.push_back("");
|
||||
mi.format = KRENGINE_MODEL_FORMAT_STRIP;
|
||||
|
||||
LoadData(mi, true, true);
|
||||
}
|
||||
|
||||
KRMeshQuad::~KRMeshQuad()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -1,135 +1,135 @@
|
||||
//
|
||||
// KRMeshSphere.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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
|
||||
// provided with the distribution.
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// 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
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#include "KRMeshSphere.h"
|
||||
|
||||
|
||||
KRMeshSphere::KRMeshSphere(KRContext &context) : KRMesh(context, "__sphere")
|
||||
{
|
||||
m_constant = true;
|
||||
|
||||
KRMesh::mesh_info mi;
|
||||
|
||||
// Create a triangular facet approximation to a sphere
|
||||
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
|
||||
|
||||
int iterations = 3;
|
||||
int facet_count = pow(4, iterations) * 8;
|
||||
|
||||
class Facet3 {
|
||||
public:
|
||||
Facet3() {
|
||||
|
||||
}
|
||||
~Facet3() {
|
||||
|
||||
}
|
||||
Vector3 p1;
|
||||
Vector3 p2;
|
||||
Vector3 p3;
|
||||
};
|
||||
|
||||
std::vector<Facet3> f = std::vector<Facet3>(facet_count);
|
||||
|
||||
int i,it;
|
||||
float a;
|
||||
Vector3 p[6] = {
|
||||
Vector3::Create(0,0,1),
|
||||
Vector3::Create(0,0,-1),
|
||||
Vector3::Create(-1,-1,0),
|
||||
Vector3::Create(1,-1,0),
|
||||
Vector3::Create(1,1,0),
|
||||
Vector3::Create(-1,1,0)
|
||||
};
|
||||
|
||||
Vector3 pa,pb,pc;
|
||||
int nt = 0,ntold;
|
||||
|
||||
/* Create the level 0 object */
|
||||
a = 1 / sqrt(2.0);
|
||||
for (i=0;i<6;i++) {
|
||||
p[i].x *= a;
|
||||
p[i].y *= a;
|
||||
}
|
||||
f[0].p1 = p[0]; f[0].p2 = p[3]; f[0].p3 = p[4];
|
||||
f[1].p1 = p[0]; f[1].p2 = p[4]; f[1].p3 = p[5];
|
||||
f[2].p1 = p[0]; f[2].p2 = p[5]; f[2].p3 = p[2];
|
||||
f[3].p1 = p[0]; f[3].p2 = p[2]; f[3].p3 = p[3];
|
||||
f[4].p1 = p[1]; f[4].p2 = p[4]; f[4].p3 = p[3];
|
||||
f[5].p1 = p[1]; f[5].p2 = p[5]; f[5].p3 = p[4];
|
||||
f[6].p1 = p[1]; f[6].p2 = p[2]; f[6].p3 = p[5];
|
||||
f[7].p1 = p[1]; f[7].p2 = p[3]; f[7].p3 = p[2];
|
||||
nt = 8;
|
||||
|
||||
/* Bisect each edge and move to the surface of a unit sphere */
|
||||
for (it=0;it<iterations;it++) {
|
||||
ntold = nt;
|
||||
for (i=0;i<ntold;i++) {
|
||||
pa.x = (f[i].p1.x + f[i].p2.x) / 2;
|
||||
pa.y = (f[i].p1.y + f[i].p2.y) / 2;
|
||||
pa.z = (f[i].p1.z + f[i].p2.z) / 2;
|
||||
pb.x = (f[i].p2.x + f[i].p3.x) / 2;
|
||||
pb.y = (f[i].p2.y + f[i].p3.y) / 2;
|
||||
pb.z = (f[i].p2.z + f[i].p3.z) / 2;
|
||||
pc.x = (f[i].p3.x + f[i].p1.x) / 2;
|
||||
pc.y = (f[i].p3.y + f[i].p1.y) / 2;
|
||||
pc.z = (f[i].p3.z + f[i].p1.z) / 2;
|
||||
pa.normalize();
|
||||
pb.normalize();
|
||||
pc.normalize();
|
||||
f[nt].p1 = f[i].p1; f[nt].p2 = pa; f[nt].p3 = pc; nt++;
|
||||
f[nt].p1 = pa; f[nt].p2 = f[i].p2; f[nt].p3 = pb; nt++;
|
||||
f[nt].p1 = pb; f[nt].p2 = f[i].p3; f[nt].p3 = pc; nt++;
|
||||
f[i].p1 = pa;
|
||||
f[i].p2 = pb;
|
||||
f[i].p3 = pc;
|
||||
}
|
||||
}
|
||||
|
||||
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].p2);
|
||||
mi.vertices.push_back(f[facet_index].p3);
|
||||
}
|
||||
|
||||
mi.submesh_starts.push_back(0);
|
||||
mi.submesh_lengths.push_back(mi.vertices.size());
|
||||
mi.material_names.push_back("");
|
||||
|
||||
|
||||
mi.format = KRENGINE_MODEL_FORMAT_TRIANGLES;
|
||||
LoadData(mi, true, true);
|
||||
}
|
||||
|
||||
KRMeshSphere::~KRMeshSphere()
|
||||
{
|
||||
|
||||
}
|
||||
//
|
||||
// KRMeshSphere.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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
|
||||
// provided with the distribution.
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// 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
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#include "KRMeshSphere.h"
|
||||
|
||||
|
||||
KRMeshSphere::KRMeshSphere(KRContext &context) : KRMesh(context, "__sphere")
|
||||
{
|
||||
m_constant = true;
|
||||
|
||||
KRMesh::mesh_info mi;
|
||||
|
||||
// Create a triangular facet approximation to a sphere
|
||||
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
|
||||
|
||||
int iterations = 3;
|
||||
int facet_count = pow(4, iterations) * 8;
|
||||
|
||||
class Facet3 {
|
||||
public:
|
||||
Facet3() {
|
||||
|
||||
}
|
||||
~Facet3() {
|
||||
|
||||
}
|
||||
Vector3 p1;
|
||||
Vector3 p2;
|
||||
Vector3 p3;
|
||||
};
|
||||
|
||||
std::vector<Facet3> f = std::vector<Facet3>(facet_count);
|
||||
|
||||
int i,it;
|
||||
float a;
|
||||
Vector3 p[6] = {
|
||||
Vector3::Create(0,0,1),
|
||||
Vector3::Create(0,0,-1),
|
||||
Vector3::Create(-1,-1,0),
|
||||
Vector3::Create(1,-1,0),
|
||||
Vector3::Create(1,1,0),
|
||||
Vector3::Create(-1,1,0)
|
||||
};
|
||||
|
||||
Vector3 pa,pb,pc;
|
||||
int nt = 0,ntold;
|
||||
|
||||
/* Create the level 0 object */
|
||||
a = 1 / sqrt(2.0);
|
||||
for (i=0;i<6;i++) {
|
||||
p[i].x *= a;
|
||||
p[i].y *= a;
|
||||
}
|
||||
f[0].p1 = p[0]; f[0].p2 = p[3]; f[0].p3 = p[4];
|
||||
f[1].p1 = p[0]; f[1].p2 = p[4]; f[1].p3 = p[5];
|
||||
f[2].p1 = p[0]; f[2].p2 = p[5]; f[2].p3 = p[2];
|
||||
f[3].p1 = p[0]; f[3].p2 = p[2]; f[3].p3 = p[3];
|
||||
f[4].p1 = p[1]; f[4].p2 = p[4]; f[4].p3 = p[3];
|
||||
f[5].p1 = p[1]; f[5].p2 = p[5]; f[5].p3 = p[4];
|
||||
f[6].p1 = p[1]; f[6].p2 = p[2]; f[6].p3 = p[5];
|
||||
f[7].p1 = p[1]; f[7].p2 = p[3]; f[7].p3 = p[2];
|
||||
nt = 8;
|
||||
|
||||
/* Bisect each edge and move to the surface of a unit sphere */
|
||||
for (it=0;it<iterations;it++) {
|
||||
ntold = nt;
|
||||
for (i=0;i<ntold;i++) {
|
||||
pa.x = (f[i].p1.x + f[i].p2.x) / 2;
|
||||
pa.y = (f[i].p1.y + f[i].p2.y) / 2;
|
||||
pa.z = (f[i].p1.z + f[i].p2.z) / 2;
|
||||
pb.x = (f[i].p2.x + f[i].p3.x) / 2;
|
||||
pb.y = (f[i].p2.y + f[i].p3.y) / 2;
|
||||
pb.z = (f[i].p2.z + f[i].p3.z) / 2;
|
||||
pc.x = (f[i].p3.x + f[i].p1.x) / 2;
|
||||
pc.y = (f[i].p3.y + f[i].p1.y) / 2;
|
||||
pc.z = (f[i].p3.z + f[i].p1.z) / 2;
|
||||
pa.normalize();
|
||||
pb.normalize();
|
||||
pc.normalize();
|
||||
f[nt].p1 = f[i].p1; f[nt].p2 = pa; f[nt].p3 = pc; nt++;
|
||||
f[nt].p1 = pa; f[nt].p2 = f[i].p2; f[nt].p3 = pb; nt++;
|
||||
f[nt].p1 = pb; f[nt].p2 = f[i].p3; f[nt].p3 = pc; nt++;
|
||||
f[i].p1 = pa;
|
||||
f[i].p2 = pb;
|
||||
f[i].p3 = pc;
|
||||
}
|
||||
}
|
||||
|
||||
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].p2);
|
||||
mi.vertices.push_back(f[facet_index].p3);
|
||||
}
|
||||
|
||||
mi.submesh_starts.push_back(0);
|
||||
mi.submesh_lengths.push_back(mi.vertices.size());
|
||||
mi.material_names.push_back("");
|
||||
|
||||
|
||||
mi.format = KRENGINE_MODEL_FORMAT_TRIANGLES;
|
||||
LoadData(mi, true, true);
|
||||
}
|
||||
|
||||
KRMeshSphere::~KRMeshSphere()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -1,263 +1,263 @@
|
||||
//
|
||||
// KRModel.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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
|
||||
// provided with the distribution.
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// 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
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRModel.h"
|
||||
#include "KRContext.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) {
|
||||
m_lightMap = light_map;
|
||||
m_pLightMap = NULL;
|
||||
m_model_name = model_name;
|
||||
m_min_lod_coverage = lod_min_coverage;
|
||||
m_receivesShadow = receives_shadow;
|
||||
m_faces_camera = faces_camera;
|
||||
m_rim_color = rim_color;
|
||||
m_rim_power = rim_power;
|
||||
|
||||
m_boundsCachedMat.c[0] = -1.0f;
|
||||
m_boundsCachedMat.c[1] = -1.0f;
|
||||
m_boundsCachedMat.c[2] = -1.0f;
|
||||
m_boundsCachedMat.c[3] = -1.0f;
|
||||
m_boundsCachedMat.c[4] = -1.0f;
|
||||
m_boundsCachedMat.c[5] = -1.0f;
|
||||
m_boundsCachedMat.c[6] = -1.0f;
|
||||
m_boundsCachedMat.c[7] = -1.0f;
|
||||
m_boundsCachedMat.c[8] = -1.0f;
|
||||
m_boundsCachedMat.c[9] = -1.0f;
|
||||
m_boundsCachedMat.c[10] = -1.0f;
|
||||
m_boundsCachedMat.c[11] = -1.0f;
|
||||
m_boundsCachedMat.c[12] = -1.0f;
|
||||
m_boundsCachedMat.c[13] = -1.0f;
|
||||
m_boundsCachedMat.c[14] = -1.0f;
|
||||
m_boundsCachedMat.c[15] = -1.0f;
|
||||
}
|
||||
|
||||
KRModel::~KRModel() {
|
||||
|
||||
}
|
||||
|
||||
std::string KRModel::getElementName() {
|
||||
return "model";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRModel::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("mesh", m_model_name.c_str());
|
||||
e->SetAttribute("light_map", m_lightMap.c_str());
|
||||
e->SetAttribute("lod_min_coverage", m_min_lod_coverage);
|
||||
e->SetAttribute("receives_shadow", m_receivesShadow ? "true" : "false");
|
||||
e->SetAttribute("faces_camera", m_faces_camera ? "true" : "false");
|
||||
kraken::setXMLAttribute("rim_color", e, m_rim_color, Vector3::Zero());
|
||||
e->SetAttribute("rim_power", m_rim_power);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRModel::setRimColor(const Vector3 &rim_color)
|
||||
{
|
||||
m_rim_color = rim_color;
|
||||
}
|
||||
|
||||
void KRModel::setRimPower(float rim_power)
|
||||
{
|
||||
m_rim_power = rim_power;
|
||||
}
|
||||
|
||||
Vector3 KRModel::getRimColor()
|
||||
{
|
||||
return m_rim_color;
|
||||
}
|
||||
|
||||
float KRModel::getRimPower()
|
||||
{
|
||||
return m_rim_power;
|
||||
}
|
||||
|
||||
void KRModel::setLightMap(const std::string &name)
|
||||
{
|
||||
m_lightMap = name;
|
||||
m_pLightMap = NULL;
|
||||
}
|
||||
|
||||
std::string KRModel::getLightMap()
|
||||
{
|
||||
return m_lightMap;
|
||||
}
|
||||
|
||||
void KRModel::loadModel() {
|
||||
if(m_models.size() == 0) {
|
||||
std::vector<KRMesh *> models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first
|
||||
unordered_map<KRMesh *, std::vector<KRBone *> > bones;
|
||||
if(models.size() > 0) {
|
||||
bool all_bones_found = true;
|
||||
for(std::vector<KRMesh *>::iterator model_itr = models.begin(); model_itr != models.end(); model_itr++) {
|
||||
KRMesh *model = *model_itr;
|
||||
std::vector<KRBone *> model_bones;
|
||||
int bone_count = model->getBoneCount();
|
||||
for(int bone_index=0; bone_index < bone_count; bone_index++) {
|
||||
KRBone *matching_bone = dynamic_cast<KRBone *>(getScene().getRootNode()->find<KRNode>(model->getBoneName(bone_index)));
|
||||
if(matching_bone) {
|
||||
model_bones.push_back(matching_bone);
|
||||
} else {
|
||||
all_bones_found = false; // Reject when there are any missing bones or multiple matches
|
||||
}
|
||||
}
|
||||
bones[model] = model_bones;
|
||||
}
|
||||
if(all_bones_found) {
|
||||
m_models = models;
|
||||
m_bones = bones;
|
||||
getScene().notify_sceneGraphModify(this);
|
||||
}
|
||||
|
||||
invalidateBounds();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KRModel::render(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) {
|
||||
preStream(viewport);
|
||||
}
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
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) {
|
||||
loadModel();
|
||||
|
||||
if(m_models.size() > 0) {
|
||||
// Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied
|
||||
|
||||
/*
|
||||
float lod_coverage = 0.0f;
|
||||
if(m_models.size() > 1) {
|
||||
lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
|
||||
} else if(viewport.visible(getBounds())) {
|
||||
lod_coverage = 1.0f;
|
||||
}
|
||||
*/
|
||||
|
||||
float lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
|
||||
|
||||
if(lod_coverage > m_min_lod_coverage) {
|
||||
|
||||
// ---===--- Select the best LOD model based on screen coverage ---===---
|
||||
std::vector<KRMesh *>::iterator itr=m_models.begin();
|
||||
KRMesh *pModel = *itr++;
|
||||
|
||||
while(itr != m_models.end()) {
|
||||
KRMesh *pLODModel = *itr++;
|
||||
if((float)pLODModel->getLODCoverage() / 100.0f > lod_coverage && pLODModel->getLODCoverage() < pModel->getLODCoverage()) {
|
||||
pModel = pLODModel;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_pLightMap == NULL && m_lightMap.size()) {
|
||||
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
|
||||
}
|
||||
|
||||
if(m_pLightMap && 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);
|
||||
}
|
||||
|
||||
Matrix4 matModel = getModelMatrix();
|
||||
if(m_faces_camera) {
|
||||
Vector3 model_center = Matrix4::Dot(matModel, Vector3::Zero());
|
||||
Vector3 camera_pos = viewport.getCameraPosition();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KRModel::preStream(const KRViewport &viewport)
|
||||
{
|
||||
loadModel();
|
||||
float lod_coverage = viewport.coverage(getBounds());
|
||||
|
||||
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
|
||||
(*itr)->preStream(lod_coverage);
|
||||
}
|
||||
|
||||
if(m_pLightMap == NULL && m_lightMap.size()) {
|
||||
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
|
||||
}
|
||||
|
||||
if(m_pLightMap) {
|
||||
m_pLightMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
kraken_stream_level KRModel::getStreamLevel(const KRViewport &viewport)
|
||||
{
|
||||
kraken_stream_level stream_level = KRNode::getStreamLevel(viewport);
|
||||
|
||||
loadModel();
|
||||
|
||||
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
|
||||
stream_level = KRMIN(stream_level, (*itr)->getStreamLevel());
|
||||
}
|
||||
|
||||
return stream_level;
|
||||
}
|
||||
|
||||
AABB KRModel::getBounds() {
|
||||
loadModel();
|
||||
if(m_models.size() > 0) {
|
||||
if(m_faces_camera) {
|
||||
AABB normal_bounds = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||
float max_dimension = normal_bounds.longest_radius();
|
||||
return AABB::Create(normal_bounds.center()-Vector3::Create(max_dimension), normal_bounds.center() + Vector3::Create(max_dimension));
|
||||
} else {
|
||||
|
||||
if(!(m_boundsCachedMat == getModelMatrix())) {
|
||||
m_boundsCachedMat = getModelMatrix();
|
||||
m_boundsCached = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||
}
|
||||
return m_boundsCached;
|
||||
}
|
||||
} else {
|
||||
return AABB::Infinite();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// KRModel.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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
|
||||
// provided with the distribution.
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// 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
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRModel.h"
|
||||
#include "KRContext.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) {
|
||||
m_lightMap = light_map;
|
||||
m_pLightMap = NULL;
|
||||
m_model_name = model_name;
|
||||
m_min_lod_coverage = lod_min_coverage;
|
||||
m_receivesShadow = receives_shadow;
|
||||
m_faces_camera = faces_camera;
|
||||
m_rim_color = rim_color;
|
||||
m_rim_power = rim_power;
|
||||
|
||||
m_boundsCachedMat.c[0] = -1.0f;
|
||||
m_boundsCachedMat.c[1] = -1.0f;
|
||||
m_boundsCachedMat.c[2] = -1.0f;
|
||||
m_boundsCachedMat.c[3] = -1.0f;
|
||||
m_boundsCachedMat.c[4] = -1.0f;
|
||||
m_boundsCachedMat.c[5] = -1.0f;
|
||||
m_boundsCachedMat.c[6] = -1.0f;
|
||||
m_boundsCachedMat.c[7] = -1.0f;
|
||||
m_boundsCachedMat.c[8] = -1.0f;
|
||||
m_boundsCachedMat.c[9] = -1.0f;
|
||||
m_boundsCachedMat.c[10] = -1.0f;
|
||||
m_boundsCachedMat.c[11] = -1.0f;
|
||||
m_boundsCachedMat.c[12] = -1.0f;
|
||||
m_boundsCachedMat.c[13] = -1.0f;
|
||||
m_boundsCachedMat.c[14] = -1.0f;
|
||||
m_boundsCachedMat.c[15] = -1.0f;
|
||||
}
|
||||
|
||||
KRModel::~KRModel() {
|
||||
|
||||
}
|
||||
|
||||
std::string KRModel::getElementName() {
|
||||
return "model";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRModel::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("mesh", m_model_name.c_str());
|
||||
e->SetAttribute("light_map", m_lightMap.c_str());
|
||||
e->SetAttribute("lod_min_coverage", m_min_lod_coverage);
|
||||
e->SetAttribute("receives_shadow", m_receivesShadow ? "true" : "false");
|
||||
e->SetAttribute("faces_camera", m_faces_camera ? "true" : "false");
|
||||
kraken::setXMLAttribute("rim_color", e, m_rim_color, Vector3::Zero());
|
||||
e->SetAttribute("rim_power", m_rim_power);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRModel::setRimColor(const Vector3 &rim_color)
|
||||
{
|
||||
m_rim_color = rim_color;
|
||||
}
|
||||
|
||||
void KRModel::setRimPower(float rim_power)
|
||||
{
|
||||
m_rim_power = rim_power;
|
||||
}
|
||||
|
||||
Vector3 KRModel::getRimColor()
|
||||
{
|
||||
return m_rim_color;
|
||||
}
|
||||
|
||||
float KRModel::getRimPower()
|
||||
{
|
||||
return m_rim_power;
|
||||
}
|
||||
|
||||
void KRModel::setLightMap(const std::string &name)
|
||||
{
|
||||
m_lightMap = name;
|
||||
m_pLightMap = NULL;
|
||||
}
|
||||
|
||||
std::string KRModel::getLightMap()
|
||||
{
|
||||
return m_lightMap;
|
||||
}
|
||||
|
||||
void KRModel::loadModel() {
|
||||
if(m_models.size() == 0) {
|
||||
std::vector<KRMesh *> models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first
|
||||
unordered_map<KRMesh *, std::vector<KRBone *> > bones;
|
||||
if(models.size() > 0) {
|
||||
bool all_bones_found = true;
|
||||
for(std::vector<KRMesh *>::iterator model_itr = models.begin(); model_itr != models.end(); model_itr++) {
|
||||
KRMesh *model = *model_itr;
|
||||
std::vector<KRBone *> model_bones;
|
||||
int bone_count = model->getBoneCount();
|
||||
for(int bone_index=0; bone_index < bone_count; bone_index++) {
|
||||
KRBone *matching_bone = dynamic_cast<KRBone *>(getScene().getRootNode()->find<KRNode>(model->getBoneName(bone_index)));
|
||||
if(matching_bone) {
|
||||
model_bones.push_back(matching_bone);
|
||||
} else {
|
||||
all_bones_found = false; // Reject when there are any missing bones or multiple matches
|
||||
}
|
||||
}
|
||||
bones[model] = model_bones;
|
||||
}
|
||||
if(all_bones_found) {
|
||||
m_models = models;
|
||||
m_bones = bones;
|
||||
getScene().notify_sceneGraphModify(this);
|
||||
}
|
||||
|
||||
invalidateBounds();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KRModel::render(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) {
|
||||
preStream(viewport);
|
||||
}
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
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) {
|
||||
loadModel();
|
||||
|
||||
if(m_models.size() > 0) {
|
||||
// Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied
|
||||
|
||||
/*
|
||||
float lod_coverage = 0.0f;
|
||||
if(m_models.size() > 1) {
|
||||
lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
|
||||
} else if(viewport.visible(getBounds())) {
|
||||
lod_coverage = 1.0f;
|
||||
}
|
||||
*/
|
||||
|
||||
float lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
|
||||
|
||||
if(lod_coverage > m_min_lod_coverage) {
|
||||
|
||||
// ---===--- Select the best LOD model based on screen coverage ---===---
|
||||
std::vector<KRMesh *>::iterator itr=m_models.begin();
|
||||
KRMesh *pModel = *itr++;
|
||||
|
||||
while(itr != m_models.end()) {
|
||||
KRMesh *pLODModel = *itr++;
|
||||
if((float)pLODModel->getLODCoverage() / 100.0f > lod_coverage && pLODModel->getLODCoverage() < pModel->getLODCoverage()) {
|
||||
pModel = pLODModel;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_pLightMap == NULL && m_lightMap.size()) {
|
||||
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
|
||||
}
|
||||
|
||||
if(m_pLightMap && 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);
|
||||
}
|
||||
|
||||
Matrix4 matModel = getModelMatrix();
|
||||
if(m_faces_camera) {
|
||||
Vector3 model_center = Matrix4::Dot(matModel, Vector3::Zero());
|
||||
Vector3 camera_pos = viewport.getCameraPosition();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KRModel::preStream(const KRViewport &viewport)
|
||||
{
|
||||
loadModel();
|
||||
float lod_coverage = viewport.coverage(getBounds());
|
||||
|
||||
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
|
||||
(*itr)->preStream(lod_coverage);
|
||||
}
|
||||
|
||||
if(m_pLightMap == NULL && m_lightMap.size()) {
|
||||
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
|
||||
}
|
||||
|
||||
if(m_pLightMap) {
|
||||
m_pLightMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
kraken_stream_level KRModel::getStreamLevel(const KRViewport &viewport)
|
||||
{
|
||||
kraken_stream_level stream_level = KRNode::getStreamLevel(viewport);
|
||||
|
||||
loadModel();
|
||||
|
||||
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
|
||||
stream_level = KRMIN(stream_level, (*itr)->getStreamLevel());
|
||||
}
|
||||
|
||||
return stream_level;
|
||||
}
|
||||
|
||||
AABB KRModel::getBounds() {
|
||||
loadModel();
|
||||
if(m_models.size() > 0) {
|
||||
if(m_faces_camera) {
|
||||
AABB normal_bounds = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||
float max_dimension = normal_bounds.longest_radius();
|
||||
return AABB::Create(normal_bounds.center()-Vector3::Create(max_dimension), normal_bounds.center() + Vector3::Create(max_dimension));
|
||||
} else {
|
||||
|
||||
if(!(m_boundsCachedMat == getModelMatrix())) {
|
||||
m_boundsCachedMat = getModelMatrix();
|
||||
m_boundsCached = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||
}
|
||||
return m_boundsCached;
|
||||
}
|
||||
} else {
|
||||
return AABB::Infinite();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1926
kraken/KRNode.cpp
1926
kraken/KRNode.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,156 +1,156 @@
|
||||
//
|
||||
// KROctree.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-08-29.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "public/kraken.h"
|
||||
#include "KROctree.h"
|
||||
#include "KRNode.h"
|
||||
#include "KRCollider.h"
|
||||
|
||||
KROctree::KROctree()
|
||||
{
|
||||
m_pRootNode = NULL;
|
||||
}
|
||||
|
||||
KROctree::~KROctree()
|
||||
{
|
||||
if(m_pRootNode) {
|
||||
delete m_pRootNode;
|
||||
}
|
||||
}
|
||||
|
||||
void KROctree::add(KRNode *pNode)
|
||||
{
|
||||
AABB nodeBounds = pNode->getBounds();
|
||||
if(nodeBounds == AABB::Zero()) {
|
||||
// This item is not visible, don't add it to the octree or outer scene nodes
|
||||
} else if(nodeBounds == AABB::Infinite()) {
|
||||
// This item is infinitely large; we track it separately
|
||||
m_outerSceneNodes.insert(pNode);
|
||||
} else {
|
||||
if(m_pRootNode == NULL) {
|
||||
// First item inserted, create a node large enough to fit it
|
||||
m_pRootNode = new KROctreeNode(NULL, nodeBounds);
|
||||
m_pRootNode->add(pNode);
|
||||
} else {
|
||||
// Keep encapsulating the root node until the new root contains the inserted node
|
||||
bool bInsideRoot = false;
|
||||
while(!bInsideRoot) {
|
||||
AABB rootBounds = m_pRootNode->getBounds();
|
||||
Vector3 rootSize = rootBounds.size();
|
||||
if(nodeBounds.min.x < rootBounds.min.x || nodeBounds.min.y < rootBounds.min.y || nodeBounds.min.z < rootBounds.min.z) {
|
||||
m_pRootNode = new KROctreeNode(NULL, AABB::Create(rootBounds.min - rootSize, rootBounds.max), 7, m_pRootNode);
|
||||
} else if(nodeBounds.max.x > rootBounds.max.x || nodeBounds.max.y > rootBounds.max.y || nodeBounds.max.z > rootBounds.max.z) {
|
||||
m_pRootNode = new KROctreeNode(NULL, AABB::Create(rootBounds.min, rootBounds.max + rootSize), 0, m_pRootNode);
|
||||
} else {
|
||||
bInsideRoot = true;
|
||||
}
|
||||
}
|
||||
m_pRootNode->add(pNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KROctree::remove(KRNode *pNode)
|
||||
{
|
||||
if(!m_outerSceneNodes.erase(pNode)) {
|
||||
if(m_pRootNode) {
|
||||
pNode->removeFromOctreeNodes();
|
||||
}
|
||||
}
|
||||
|
||||
shrink();
|
||||
}
|
||||
|
||||
void KROctree::update(KRNode *pNode)
|
||||
{
|
||||
// TODO: This may be more efficient as an incremental operation rather than removing and re-adding the node
|
||||
remove(pNode);
|
||||
add(pNode);
|
||||
shrink();
|
||||
}
|
||||
|
||||
void KROctree::shrink()
|
||||
{
|
||||
if(m_pRootNode) {
|
||||
while(m_pRootNode->canShrinkRoot()) {
|
||||
KROctreeNode *newRoot = m_pRootNode->stripChild();
|
||||
delete m_pRootNode;
|
||||
m_pRootNode = newRoot;
|
||||
if(m_pRootNode == NULL) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KROctreeNode *KROctree::getRootNode()
|
||||
{
|
||||
return m_pRootNode;
|
||||
}
|
||||
|
||||
std::set<KRNode *> &KROctree::getOuterSceneNodes()
|
||||
{
|
||||
return m_outerSceneNodes;
|
||||
}
|
||||
|
||||
|
||||
bool KROctree::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
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++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
|
||||
if(collider) {
|
||||
outer_colliders.push_back(collider);
|
||||
}
|
||||
}
|
||||
for(std::vector<KRCollider *>::iterator itr=outer_colliders.begin(); itr != outer_colliders.end(); itr++) {
|
||||
if((*itr)->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
|
||||
if(m_pRootNode) {
|
||||
if(m_pRootNode->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctree::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
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);
|
||||
if(collider) {
|
||||
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
if(m_pRootNode) {
|
||||
if(m_pRootNode->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctree::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
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++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
|
||||
if(collider) {
|
||||
outer_colliders.push_back(collider);
|
||||
}
|
||||
}
|
||||
for(std::vector<KRCollider *>::iterator itr=outer_colliders.begin(); itr != outer_colliders.end(); itr++) {
|
||||
if((*itr)->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
|
||||
if(m_pRootNode) {
|
||||
if(m_pRootNode->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
//
|
||||
// KROctree.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-08-29.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "public/kraken.h"
|
||||
#include "KROctree.h"
|
||||
#include "KRNode.h"
|
||||
#include "KRCollider.h"
|
||||
|
||||
KROctree::KROctree()
|
||||
{
|
||||
m_pRootNode = NULL;
|
||||
}
|
||||
|
||||
KROctree::~KROctree()
|
||||
{
|
||||
if(m_pRootNode) {
|
||||
delete m_pRootNode;
|
||||
}
|
||||
}
|
||||
|
||||
void KROctree::add(KRNode *pNode)
|
||||
{
|
||||
AABB nodeBounds = pNode->getBounds();
|
||||
if(nodeBounds == AABB::Zero()) {
|
||||
// This item is not visible, don't add it to the octree or outer scene nodes
|
||||
} else if(nodeBounds == AABB::Infinite()) {
|
||||
// This item is infinitely large; we track it separately
|
||||
m_outerSceneNodes.insert(pNode);
|
||||
} else {
|
||||
if(m_pRootNode == NULL) {
|
||||
// First item inserted, create a node large enough to fit it
|
||||
m_pRootNode = new KROctreeNode(NULL, nodeBounds);
|
||||
m_pRootNode->add(pNode);
|
||||
} else {
|
||||
// Keep encapsulating the root node until the new root contains the inserted node
|
||||
bool bInsideRoot = false;
|
||||
while(!bInsideRoot) {
|
||||
AABB rootBounds = m_pRootNode->getBounds();
|
||||
Vector3 rootSize = rootBounds.size();
|
||||
if(nodeBounds.min.x < rootBounds.min.x || nodeBounds.min.y < rootBounds.min.y || nodeBounds.min.z < rootBounds.min.z) {
|
||||
m_pRootNode = new KROctreeNode(NULL, AABB::Create(rootBounds.min - rootSize, rootBounds.max), 7, m_pRootNode);
|
||||
} else if(nodeBounds.max.x > rootBounds.max.x || nodeBounds.max.y > rootBounds.max.y || nodeBounds.max.z > rootBounds.max.z) {
|
||||
m_pRootNode = new KROctreeNode(NULL, AABB::Create(rootBounds.min, rootBounds.max + rootSize), 0, m_pRootNode);
|
||||
} else {
|
||||
bInsideRoot = true;
|
||||
}
|
||||
}
|
||||
m_pRootNode->add(pNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KROctree::remove(KRNode *pNode)
|
||||
{
|
||||
if(!m_outerSceneNodes.erase(pNode)) {
|
||||
if(m_pRootNode) {
|
||||
pNode->removeFromOctreeNodes();
|
||||
}
|
||||
}
|
||||
|
||||
shrink();
|
||||
}
|
||||
|
||||
void KROctree::update(KRNode *pNode)
|
||||
{
|
||||
// TODO: This may be more efficient as an incremental operation rather than removing and re-adding the node
|
||||
remove(pNode);
|
||||
add(pNode);
|
||||
shrink();
|
||||
}
|
||||
|
||||
void KROctree::shrink()
|
||||
{
|
||||
if(m_pRootNode) {
|
||||
while(m_pRootNode->canShrinkRoot()) {
|
||||
KROctreeNode *newRoot = m_pRootNode->stripChild();
|
||||
delete m_pRootNode;
|
||||
m_pRootNode = newRoot;
|
||||
if(m_pRootNode == NULL) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KROctreeNode *KROctree::getRootNode()
|
||||
{
|
||||
return m_pRootNode;
|
||||
}
|
||||
|
||||
std::set<KRNode *> &KROctree::getOuterSceneNodes()
|
||||
{
|
||||
return m_outerSceneNodes;
|
||||
}
|
||||
|
||||
|
||||
bool KROctree::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
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++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
|
||||
if(collider) {
|
||||
outer_colliders.push_back(collider);
|
||||
}
|
||||
}
|
||||
for(std::vector<KRCollider *>::iterator itr=outer_colliders.begin(); itr != outer_colliders.end(); itr++) {
|
||||
if((*itr)->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
|
||||
if(m_pRootNode) {
|
||||
if(m_pRootNode->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctree::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
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);
|
||||
if(collider) {
|
||||
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
if(m_pRootNode) {
|
||||
if(m_pRootNode->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctree::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
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++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
|
||||
if(collider) {
|
||||
outer_colliders.push_back(collider);
|
||||
}
|
||||
}
|
||||
for(std::vector<KRCollider *>::iterator itr=outer_colliders.begin(); itr != outer_colliders.end(); itr++) {
|
||||
if((*itr)->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
|
||||
if(m_pRootNode) {
|
||||
if(m_pRootNode->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,290 +1,290 @@
|
||||
//
|
||||
// KROctreeNode.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-08-29.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KROctreeNode.h"
|
||||
#include "KRNode.h"
|
||||
#include "KRCollider.h"
|
||||
|
||||
KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds) : m_bounds(bounds)
|
||||
{
|
||||
m_parent = parent;
|
||||
|
||||
for(int i=0; i<8; i++) m_children[i] = NULL;
|
||||
|
||||
m_occlusionQuery = 0;
|
||||
m_occlusionTested = false;
|
||||
m_activeQuery = false;
|
||||
}
|
||||
|
||||
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
|
||||
m_parent = parent;
|
||||
|
||||
for(int i=0; i<8; i++) m_children[i] = NULL;
|
||||
m_children[iChild] = pChild;
|
||||
pChild->m_parent = this;
|
||||
|
||||
m_occlusionQuery = 0;
|
||||
m_occlusionTested = false;
|
||||
m_activeQuery = false;
|
||||
}
|
||||
|
||||
KROctreeNode::~KROctreeNode()
|
||||
{
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i] != NULL) {
|
||||
delete m_children[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(m_occlusionTested) {
|
||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KROctreeNode::beginOcclusionQuery()
|
||||
{
|
||||
if(!m_occlusionTested){
|
||||
GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery));
|
||||
#if TARGET_OS_IPHONE || defined(ANDROID)
|
||||
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
|
||||
#else
|
||||
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
|
||||
#endif
|
||||
m_occlusionTested = true;
|
||||
m_activeQuery = true;
|
||||
}
|
||||
}
|
||||
|
||||
void KROctreeNode::endOcclusionQuery()
|
||||
{
|
||||
if(m_activeQuery) {
|
||||
// Only end a query if we started one
|
||||
#if TARGET_OS_IPHONE || defined(ANDROID)
|
||||
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
|
||||
#else
|
||||
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AABB KROctreeNode::getBounds()
|
||||
{
|
||||
return m_bounds;
|
||||
}
|
||||
|
||||
void KROctreeNode::add(KRNode *pNode)
|
||||
{
|
||||
int iChild = getChildIndex(pNode);
|
||||
if(iChild == -1) {
|
||||
m_sceneNodes.insert(pNode);
|
||||
pNode->addToOctreeNode(this);
|
||||
} else {
|
||||
if(m_children[iChild] == NULL) {
|
||||
m_children[iChild] = new KROctreeNode(this, getChildBounds(iChild));
|
||||
}
|
||||
m_children[iChild]->add(pNode);
|
||||
}
|
||||
}
|
||||
|
||||
AABB KROctreeNode::getChildBounds(int iChild)
|
||||
{
|
||||
Vector3 center = m_bounds.center();
|
||||
|
||||
return AABB::Create(
|
||||
Vector3::Create(
|
||||
(iChild & 1) == 0 ? m_bounds.min.x : center.x,
|
||||
(iChild & 2) == 0 ? m_bounds.min.y : center.y,
|
||||
(iChild & 4) == 0 ? m_bounds.min.z : center.z),
|
||||
Vector3::Create(
|
||||
(iChild & 1) == 0 ? center.x : m_bounds.max.x,
|
||||
(iChild & 2) == 0 ? center.y : m_bounds.max.y,
|
||||
(iChild & 4) == 0 ? center.z : m_bounds.max.z)
|
||||
);
|
||||
}
|
||||
|
||||
int KROctreeNode::getChildIndex(KRNode *pNode)
|
||||
{
|
||||
for(int iChild=0; iChild < 8; iChild++) {
|
||||
if(getChildBounds(iChild).contains(pNode->getBounds())) {
|
||||
return iChild;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void KROctreeNode::trim()
|
||||
{
|
||||
for(int iChild = 0; iChild < 8; iChild++) {
|
||||
if(m_children[iChild]) {
|
||||
if(m_children[iChild]->isEmpty()) {
|
||||
delete m_children[iChild];
|
||||
m_children[iChild] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KROctreeNode::remove(KRNode *pNode)
|
||||
{
|
||||
m_sceneNodes.erase(pNode);
|
||||
}
|
||||
|
||||
void KROctreeNode::update(KRNode *pNode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool KROctreeNode::isEmpty() const
|
||||
{
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return m_sceneNodes.empty();
|
||||
}
|
||||
|
||||
bool KROctreeNode::canShrinkRoot() const
|
||||
{
|
||||
int cChildren = 0;
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
cChildren++;
|
||||
}
|
||||
}
|
||||
return cChildren <= 1 && m_sceneNodes.empty();
|
||||
}
|
||||
|
||||
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
|
||||
// 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++) {
|
||||
if(m_children[i]) {
|
||||
KROctreeNode *child = m_children[i];
|
||||
child->m_parent = NULL;
|
||||
m_children[i] = NULL;
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
KROctreeNode *KROctreeNode::getParent()
|
||||
{
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
KROctreeNode **KROctreeNode::getChildren()
|
||||
{
|
||||
return m_children;
|
||||
}
|
||||
|
||||
std::set<KRNode *> &KROctreeNode::getSceneNodes()
|
||||
{
|
||||
return m_sceneNodes;
|
||||
}
|
||||
|
||||
|
||||
bool KROctreeNode::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
|
||||
// Optimization: If we already have a hit, only search for hits that are closer
|
||||
hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask);
|
||||
} else {
|
||||
if(getBounds().intersectsLine(v0, v1)) {
|
||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||
if(collider) {
|
||||
if(collider->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
if(m_children[i]->lineCast(v0, v1, hitinfo, layer_mask)) {
|
||||
hit_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctreeNode::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
if(hitinfo.didHit()) {
|
||||
// Optimization: If we already have a hit, only search for hits that are closer
|
||||
hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask); // Note: This is purposefully lineCast as opposed to RayCast
|
||||
} else {
|
||||
if(getBounds().intersectsRay(v0, dir)) {
|
||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||
if(collider) {
|
||||
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
if(m_children[i]->rayCast(v0, dir, hitinfo, layer_mask)) {
|
||||
hit_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctreeNode::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
/*
|
||||
// FINDME, TODO - Adapt this optimization to work with sphereCasts
|
||||
|
||||
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
|
||||
// Optimization: If we already have a hit, only search for hits that are closer
|
||||
hit_found = sphereCast(v0, hitinfo.getPosition(), radius, hitinfo, layer_mask);
|
||||
} else {
|
||||
*/
|
||||
|
||||
AABB swept_bounds = AABB::Create(Vector3::Create(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius), Vector3::Create(KRMAX(v0.x, v1.x) + radius, KRMAX(v0.y, v1.y) + radius, KRMAX(v0.z, v1.z) + radius));
|
||||
// FINDME, TODO - Investigate AABB - swept sphere intersections or OBB - AABB intersections: "if(getBounds().intersectsSweptSphere(v0, v1, radius)) {"
|
||||
if(getBounds().intersects(swept_bounds)) {
|
||||
|
||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||
if(collider) {
|
||||
if(collider->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
if(m_children[i]->sphereCast(v0, v1, radius, hitinfo, layer_mask)) {
|
||||
hit_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
//
|
||||
// KROctreeNode.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-08-29.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KROctreeNode.h"
|
||||
#include "KRNode.h"
|
||||
#include "KRCollider.h"
|
||||
|
||||
KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds) : m_bounds(bounds)
|
||||
{
|
||||
m_parent = parent;
|
||||
|
||||
for(int i=0; i<8; i++) m_children[i] = NULL;
|
||||
|
||||
m_occlusionQuery = 0;
|
||||
m_occlusionTested = false;
|
||||
m_activeQuery = false;
|
||||
}
|
||||
|
||||
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
|
||||
m_parent = parent;
|
||||
|
||||
for(int i=0; i<8; i++) m_children[i] = NULL;
|
||||
m_children[iChild] = pChild;
|
||||
pChild->m_parent = this;
|
||||
|
||||
m_occlusionQuery = 0;
|
||||
m_occlusionTested = false;
|
||||
m_activeQuery = false;
|
||||
}
|
||||
|
||||
KROctreeNode::~KROctreeNode()
|
||||
{
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i] != NULL) {
|
||||
delete m_children[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(m_occlusionTested) {
|
||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KROctreeNode::beginOcclusionQuery()
|
||||
{
|
||||
if(!m_occlusionTested){
|
||||
GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery));
|
||||
#if TARGET_OS_IPHONE || defined(ANDROID)
|
||||
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
|
||||
#else
|
||||
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
|
||||
#endif
|
||||
m_occlusionTested = true;
|
||||
m_activeQuery = true;
|
||||
}
|
||||
}
|
||||
|
||||
void KROctreeNode::endOcclusionQuery()
|
||||
{
|
||||
if(m_activeQuery) {
|
||||
// Only end a query if we started one
|
||||
#if TARGET_OS_IPHONE || defined(ANDROID)
|
||||
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
|
||||
#else
|
||||
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AABB KROctreeNode::getBounds()
|
||||
{
|
||||
return m_bounds;
|
||||
}
|
||||
|
||||
void KROctreeNode::add(KRNode *pNode)
|
||||
{
|
||||
int iChild = getChildIndex(pNode);
|
||||
if(iChild == -1) {
|
||||
m_sceneNodes.insert(pNode);
|
||||
pNode->addToOctreeNode(this);
|
||||
} else {
|
||||
if(m_children[iChild] == NULL) {
|
||||
m_children[iChild] = new KROctreeNode(this, getChildBounds(iChild));
|
||||
}
|
||||
m_children[iChild]->add(pNode);
|
||||
}
|
||||
}
|
||||
|
||||
AABB KROctreeNode::getChildBounds(int iChild)
|
||||
{
|
||||
Vector3 center = m_bounds.center();
|
||||
|
||||
return AABB::Create(
|
||||
Vector3::Create(
|
||||
(iChild & 1) == 0 ? m_bounds.min.x : center.x,
|
||||
(iChild & 2) == 0 ? m_bounds.min.y : center.y,
|
||||
(iChild & 4) == 0 ? m_bounds.min.z : center.z),
|
||||
Vector3::Create(
|
||||
(iChild & 1) == 0 ? center.x : m_bounds.max.x,
|
||||
(iChild & 2) == 0 ? center.y : m_bounds.max.y,
|
||||
(iChild & 4) == 0 ? center.z : m_bounds.max.z)
|
||||
);
|
||||
}
|
||||
|
||||
int KROctreeNode::getChildIndex(KRNode *pNode)
|
||||
{
|
||||
for(int iChild=0; iChild < 8; iChild++) {
|
||||
if(getChildBounds(iChild).contains(pNode->getBounds())) {
|
||||
return iChild;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void KROctreeNode::trim()
|
||||
{
|
||||
for(int iChild = 0; iChild < 8; iChild++) {
|
||||
if(m_children[iChild]) {
|
||||
if(m_children[iChild]->isEmpty()) {
|
||||
delete m_children[iChild];
|
||||
m_children[iChild] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KROctreeNode::remove(KRNode *pNode)
|
||||
{
|
||||
m_sceneNodes.erase(pNode);
|
||||
}
|
||||
|
||||
void KROctreeNode::update(KRNode *pNode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool KROctreeNode::isEmpty() const
|
||||
{
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return m_sceneNodes.empty();
|
||||
}
|
||||
|
||||
bool KROctreeNode::canShrinkRoot() const
|
||||
{
|
||||
int cChildren = 0;
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
cChildren++;
|
||||
}
|
||||
}
|
||||
return cChildren <= 1 && m_sceneNodes.empty();
|
||||
}
|
||||
|
||||
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
|
||||
// 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++) {
|
||||
if(m_children[i]) {
|
||||
KROctreeNode *child = m_children[i];
|
||||
child->m_parent = NULL;
|
||||
m_children[i] = NULL;
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
KROctreeNode *KROctreeNode::getParent()
|
||||
{
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
KROctreeNode **KROctreeNode::getChildren()
|
||||
{
|
||||
return m_children;
|
||||
}
|
||||
|
||||
std::set<KRNode *> &KROctreeNode::getSceneNodes()
|
||||
{
|
||||
return m_sceneNodes;
|
||||
}
|
||||
|
||||
|
||||
bool KROctreeNode::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
|
||||
// Optimization: If we already have a hit, only search for hits that are closer
|
||||
hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask);
|
||||
} else {
|
||||
if(getBounds().intersectsLine(v0, v1)) {
|
||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||
if(collider) {
|
||||
if(collider->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
if(m_children[i]->lineCast(v0, v1, hitinfo, layer_mask)) {
|
||||
hit_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctreeNode::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
if(hitinfo.didHit()) {
|
||||
// Optimization: If we already have a hit, only search for hits that are closer
|
||||
hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask); // Note: This is purposefully lineCast as opposed to RayCast
|
||||
} else {
|
||||
if(getBounds().intersectsRay(v0, dir)) {
|
||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||
if(collider) {
|
||||
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
if(m_children[i]->rayCast(v0, dir, hitinfo, layer_mask)) {
|
||||
hit_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctreeNode::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
/*
|
||||
// FINDME, TODO - Adapt this optimization to work with sphereCasts
|
||||
|
||||
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
|
||||
// Optimization: If we already have a hit, only search for hits that are closer
|
||||
hit_found = sphereCast(v0, hitinfo.getPosition(), radius, hitinfo, layer_mask);
|
||||
} else {
|
||||
*/
|
||||
|
||||
AABB swept_bounds = AABB::Create(Vector3::Create(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius), Vector3::Create(KRMAX(v0.x, v1.x) + radius, KRMAX(v0.y, v1.y) + radius, KRMAX(v0.z, v1.z) + radius));
|
||||
// FINDME, TODO - Investigate AABB - swept sphere intersections or OBB - AABB intersections: "if(getBounds().intersectsSweptSphere(v0, v1, radius)) {"
|
||||
if(getBounds().intersects(swept_bounds)) {
|
||||
|
||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||
if(collider) {
|
||||
if(collider->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
if(m_children[i]->sphereCast(v0, v1, radius, hitinfo, layer_mask)) {
|
||||
hit_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,89 +1,89 @@
|
||||
//
|
||||
// KRParticleSystemNewtonian.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-11-02.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRParticleSystemNewtonian.h"
|
||||
#include "KRTexture.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRParticleSystemNewtonian::KRParticleSystemNewtonian(KRScene &scene, std::string name) : KRParticleSystem(scene, name)
|
||||
{
|
||||
m_particlesAbsoluteTime = 0.0f;
|
||||
}
|
||||
|
||||
KRParticleSystemNewtonian::~KRParticleSystemNewtonian()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string KRParticleSystemNewtonian::getElementName()
|
||||
{
|
||||
return "newtonian_particles";
|
||||
}
|
||||
|
||||
void KRParticleSystemNewtonian::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRParticleSystem::loadXML(e);
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRParticleSystemNewtonian::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRParticleSystem::saveXML(parent);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
AABB KRParticleSystemNewtonian::getBounds()
|
||||
{
|
||||
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
|
||||
}
|
||||
|
||||
void KRParticleSystemNewtonian::physicsUpdate(float deltaTime)
|
||||
{
|
||||
KRParticleSystem::physicsUpdate(deltaTime);
|
||||
m_particlesAbsoluteTime += deltaTime;
|
||||
}
|
||||
|
||||
bool KRParticleSystemNewtonian::hasPhysics()
|
||||
{
|
||||
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) {
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
|
||||
if(viewport.visible(getBounds())) {
|
||||
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
KRTexture *pParticleTexture = m_pContext->getTextureManager()->getTexture("flare");
|
||||
m_pContext->getTextureManager()->selectTexture(0, pParticleTexture, 0.0f, KRTexture::TEXTURE_USAGE_PARTICLE);
|
||||
|
||||
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);
|
||||
|
||||
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())) {
|
||||
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, 1.0f);
|
||||
|
||||
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);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// KRParticleSystemNewtonian.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-11-02.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRParticleSystemNewtonian.h"
|
||||
#include "KRTexture.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRParticleSystemNewtonian::KRParticleSystemNewtonian(KRScene &scene, std::string name) : KRParticleSystem(scene, name)
|
||||
{
|
||||
m_particlesAbsoluteTime = 0.0f;
|
||||
}
|
||||
|
||||
KRParticleSystemNewtonian::~KRParticleSystemNewtonian()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string KRParticleSystemNewtonian::getElementName()
|
||||
{
|
||||
return "newtonian_particles";
|
||||
}
|
||||
|
||||
void KRParticleSystemNewtonian::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRParticleSystem::loadXML(e);
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRParticleSystemNewtonian::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRParticleSystem::saveXML(parent);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
AABB KRParticleSystemNewtonian::getBounds()
|
||||
{
|
||||
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
|
||||
}
|
||||
|
||||
void KRParticleSystemNewtonian::physicsUpdate(float deltaTime)
|
||||
{
|
||||
KRParticleSystem::physicsUpdate(deltaTime);
|
||||
m_particlesAbsoluteTime += deltaTime;
|
||||
}
|
||||
|
||||
bool KRParticleSystemNewtonian::hasPhysics()
|
||||
{
|
||||
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) {
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
|
||||
if(viewport.visible(getBounds())) {
|
||||
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
KRTexture *pParticleTexture = m_pContext->getTextureManager()->getTexture("flare");
|
||||
m_pContext->getTextureManager()->selectTexture(0, pParticleTexture, 0.0f, KRTexture::TEXTURE_USAGE_PARTICLE);
|
||||
|
||||
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);
|
||||
|
||||
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())) {
|
||||
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, 1.0f);
|
||||
|
||||
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);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,226 +1,226 @@
|
||||
//
|
||||
// KRPointLight.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRPointLight.h"
|
||||
#include "KRCamera.h"
|
||||
#include "KRContext.h"
|
||||
#include "KRStockGeometry.h"
|
||||
|
||||
KRPointLight::KRPointLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
||||
{
|
||||
m_sphereVertices = NULL;
|
||||
m_cVertices = 0;
|
||||
}
|
||||
|
||||
KRPointLight::~KRPointLight()
|
||||
{
|
||||
if(m_sphereVertices) {
|
||||
delete m_sphereVertices;
|
||||
m_cVertices = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string KRPointLight::getElementName() {
|
||||
return "point_light";
|
||||
}
|
||||
|
||||
AABB KRPointLight::getBounds() {
|
||||
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
||||
if(influence_radius < m_flareOcclusionSize) {
|
||||
influence_radius = m_flareOcclusionSize;
|
||||
}
|
||||
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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
bool bVisualize = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.bShowDeferred;
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS || bVisualize) {
|
||||
// Lights are rendered on the second pass of the deferred renderer
|
||||
|
||||
std::vector<KRPointLight *> this_light;
|
||||
this_light.push_back(this);
|
||||
|
||||
Vector3 light_position = getLocalTranslation();
|
||||
|
||||
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
||||
|
||||
Matrix4 sphereModelMatrix = Matrix4();
|
||||
sphereModelMatrix.scale(influence_radius);
|
||||
sphereModelMatrix.translate(light_position.x, light_position.y, light_position.z);
|
||||
|
||||
if(viewport.visible(getBounds())) { // Cull out any lights not within the view frustrum
|
||||
|
||||
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());
|
||||
|
||||
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())) {
|
||||
|
||||
|
||||
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_DECAY_START, getDecayStart());
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_CUTOFF, KRLIGHT_MIN_INFLUENCE);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_POSITION, light_position);
|
||||
|
||||
|
||||
if(bVisualize) {
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
}
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
|
||||
if(bInsideLight) {
|
||||
|
||||
// Disable z-buffer test
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
|
||||
// Render a full screen quad
|
||||
m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
} else {
|
||||
#if GL_OES_vertex_array_object
|
||||
GLDEBUG(glBindVertexArrayOES(0));
|
||||
#endif
|
||||
m_pContext->getMeshManager()->configureAttribs(1 << KRMesh::KRENGINE_ATTRIB_VERTEX);
|
||||
// Render sphere of light's influence
|
||||
generateMesh();
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_VERTEX, 3, GL_FLOAT, 0, 0, m_sphereVertices));
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, m_cVertices));
|
||||
}
|
||||
}
|
||||
if(bVisualize) {
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KRPointLight::generateMesh() {
|
||||
// Create a triangular facet approximation to a sphere
|
||||
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
|
||||
|
||||
int iterations = 3;
|
||||
int facet_count = pow(4, iterations) * 8;
|
||||
|
||||
if(m_cVertices != facet_count * 3) {
|
||||
if(m_sphereVertices) {
|
||||
free(m_sphereVertices);
|
||||
m_sphereVertices = NULL;
|
||||
}
|
||||
|
||||
m_cVertices = facet_count * 3;
|
||||
|
||||
|
||||
class Facet3 {
|
||||
public:
|
||||
Facet3() {
|
||||
|
||||
}
|
||||
~Facet3() {
|
||||
|
||||
}
|
||||
Vector3 p1;
|
||||
Vector3 p2;
|
||||
Vector3 p3;
|
||||
};
|
||||
|
||||
std::vector<Facet3> f = std::vector<Facet3>(facet_count);
|
||||
|
||||
int i,it;
|
||||
float a;
|
||||
Vector3 p[6] = {
|
||||
Vector3::Create(0,0,1),
|
||||
Vector3::Create(0,0,-1),
|
||||
Vector3::Create(-1,-1,0),
|
||||
Vector3::Create(1,-1,0),
|
||||
Vector3::Create(1,1,0),
|
||||
Vector3::Create(-1,1,0)
|
||||
};
|
||||
|
||||
Vector3 pa,pb,pc;
|
||||
int nt = 0,ntold;
|
||||
|
||||
/* Create the level 0 object */
|
||||
a = 1.0f / sqrtf(2.0f);
|
||||
for (i=0;i<6;i++) {
|
||||
p[i].x *= a;
|
||||
p[i].y *= a;
|
||||
}
|
||||
f[0].p1 = p[0]; f[0].p2 = p[3]; f[0].p3 = p[4];
|
||||
f[1].p1 = p[0]; f[1].p2 = p[4]; f[1].p3 = p[5];
|
||||
f[2].p1 = p[0]; f[2].p2 = p[5]; f[2].p3 = p[2];
|
||||
f[3].p1 = p[0]; f[3].p2 = p[2]; f[3].p3 = p[3];
|
||||
f[4].p1 = p[1]; f[4].p2 = p[4]; f[4].p3 = p[3];
|
||||
f[5].p1 = p[1]; f[5].p2 = p[5]; f[5].p3 = p[4];
|
||||
f[6].p1 = p[1]; f[6].p2 = p[2]; f[6].p3 = p[5];
|
||||
f[7].p1 = p[1]; f[7].p2 = p[3]; f[7].p3 = p[2];
|
||||
nt = 8;
|
||||
|
||||
/* Bisect each edge and move to the surface of a unit sphere */
|
||||
for (it=0;it<iterations;it++) {
|
||||
ntold = nt;
|
||||
for (i=0;i<ntold;i++) {
|
||||
pa.x = (f[i].p1.x + f[i].p2.x) / 2;
|
||||
pa.y = (f[i].p1.y + f[i].p2.y) / 2;
|
||||
pa.z = (f[i].p1.z + f[i].p2.z) / 2;
|
||||
pb.x = (f[i].p2.x + f[i].p3.x) / 2;
|
||||
pb.y = (f[i].p2.y + f[i].p3.y) / 2;
|
||||
pb.z = (f[i].p2.z + f[i].p3.z) / 2;
|
||||
pc.x = (f[i].p3.x + f[i].p1.x) / 2;
|
||||
pc.y = (f[i].p3.y + f[i].p1.y) / 2;
|
||||
pc.z = (f[i].p3.z + f[i].p1.z) / 2;
|
||||
pa.normalize();
|
||||
pb.normalize();
|
||||
pc.normalize();
|
||||
f[nt].p1 = f[i].p1; f[nt].p2 = pa; f[nt].p3 = pc; nt++;
|
||||
f[nt].p1 = pa; f[nt].p2 = f[i].p2; f[nt].p3 = pb; nt++;
|
||||
f[nt].p1 = pb; f[nt].p2 = f[i].p3; f[nt].p3 = pc; nt++;
|
||||
f[i].p1 = pa;
|
||||
f[i].p2 = pb;
|
||||
f[i].p3 = pc;
|
||||
}
|
||||
}
|
||||
|
||||
m_sphereVertices = (GLfloat *)malloc(sizeof(GLfloat) * m_cVertices * 3);
|
||||
assert(m_sphereVertices != NULL);
|
||||
GLfloat *pDest = m_sphereVertices;
|
||||
for(int facet_index=0; facet_index < facet_count; facet_index++) {
|
||||
*pDest++ = f[facet_index].p1.x;
|
||||
*pDest++ = f[facet_index].p1.y;
|
||||
*pDest++ = f[facet_index].p1.z;
|
||||
*pDest++ = f[facet_index].p2.x;
|
||||
*pDest++ = f[facet_index].p2.y;
|
||||
*pDest++ = f[facet_index].p2.z;
|
||||
*pDest++ = f[facet_index].p3.x;
|
||||
*pDest++ = f[facet_index].p3.y;
|
||||
*pDest++ = f[facet_index].p3.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// KRPointLight.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRPointLight.h"
|
||||
#include "KRCamera.h"
|
||||
#include "KRContext.h"
|
||||
#include "KRStockGeometry.h"
|
||||
|
||||
KRPointLight::KRPointLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
||||
{
|
||||
m_sphereVertices = NULL;
|
||||
m_cVertices = 0;
|
||||
}
|
||||
|
||||
KRPointLight::~KRPointLight()
|
||||
{
|
||||
if(m_sphereVertices) {
|
||||
delete m_sphereVertices;
|
||||
m_cVertices = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string KRPointLight::getElementName() {
|
||||
return "point_light";
|
||||
}
|
||||
|
||||
AABB KRPointLight::getBounds() {
|
||||
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
||||
if(influence_radius < m_flareOcclusionSize) {
|
||||
influence_radius = m_flareOcclusionSize;
|
||||
}
|
||||
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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
bool bVisualize = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.bShowDeferred;
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS || bVisualize) {
|
||||
// Lights are rendered on the second pass of the deferred renderer
|
||||
|
||||
std::vector<KRPointLight *> this_light;
|
||||
this_light.push_back(this);
|
||||
|
||||
Vector3 light_position = getLocalTranslation();
|
||||
|
||||
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
||||
|
||||
Matrix4 sphereModelMatrix = Matrix4();
|
||||
sphereModelMatrix.scale(influence_radius);
|
||||
sphereModelMatrix.translate(light_position.x, light_position.y, light_position.z);
|
||||
|
||||
if(viewport.visible(getBounds())) { // Cull out any lights not within the view frustrum
|
||||
|
||||
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());
|
||||
|
||||
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())) {
|
||||
|
||||
|
||||
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_DECAY_START, getDecayStart());
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_CUTOFF, KRLIGHT_MIN_INFLUENCE);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_POSITION, light_position);
|
||||
|
||||
|
||||
if(bVisualize) {
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
}
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
|
||||
if(bInsideLight) {
|
||||
|
||||
// Disable z-buffer test
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
|
||||
// Render a full screen quad
|
||||
m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
} else {
|
||||
#if GL_OES_vertex_array_object
|
||||
GLDEBUG(glBindVertexArrayOES(0));
|
||||
#endif
|
||||
m_pContext->getMeshManager()->configureAttribs(1 << KRMesh::KRENGINE_ATTRIB_VERTEX);
|
||||
// Render sphere of light's influence
|
||||
generateMesh();
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_VERTEX, 3, GL_FLOAT, 0, 0, m_sphereVertices));
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, m_cVertices));
|
||||
}
|
||||
}
|
||||
if(bVisualize) {
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KRPointLight::generateMesh() {
|
||||
// Create a triangular facet approximation to a sphere
|
||||
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
|
||||
|
||||
int iterations = 3;
|
||||
int facet_count = pow(4, iterations) * 8;
|
||||
|
||||
if(m_cVertices != facet_count * 3) {
|
||||
if(m_sphereVertices) {
|
||||
free(m_sphereVertices);
|
||||
m_sphereVertices = NULL;
|
||||
}
|
||||
|
||||
m_cVertices = facet_count * 3;
|
||||
|
||||
|
||||
class Facet3 {
|
||||
public:
|
||||
Facet3() {
|
||||
|
||||
}
|
||||
~Facet3() {
|
||||
|
||||
}
|
||||
Vector3 p1;
|
||||
Vector3 p2;
|
||||
Vector3 p3;
|
||||
};
|
||||
|
||||
std::vector<Facet3> f = std::vector<Facet3>(facet_count);
|
||||
|
||||
int i,it;
|
||||
float a;
|
||||
Vector3 p[6] = {
|
||||
Vector3::Create(0,0,1),
|
||||
Vector3::Create(0,0,-1),
|
||||
Vector3::Create(-1,-1,0),
|
||||
Vector3::Create(1,-1,0),
|
||||
Vector3::Create(1,1,0),
|
||||
Vector3::Create(-1,1,0)
|
||||
};
|
||||
|
||||
Vector3 pa,pb,pc;
|
||||
int nt = 0,ntold;
|
||||
|
||||
/* Create the level 0 object */
|
||||
a = 1.0f / sqrtf(2.0f);
|
||||
for (i=0;i<6;i++) {
|
||||
p[i].x *= a;
|
||||
p[i].y *= a;
|
||||
}
|
||||
f[0].p1 = p[0]; f[0].p2 = p[3]; f[0].p3 = p[4];
|
||||
f[1].p1 = p[0]; f[1].p2 = p[4]; f[1].p3 = p[5];
|
||||
f[2].p1 = p[0]; f[2].p2 = p[5]; f[2].p3 = p[2];
|
||||
f[3].p1 = p[0]; f[3].p2 = p[2]; f[3].p3 = p[3];
|
||||
f[4].p1 = p[1]; f[4].p2 = p[4]; f[4].p3 = p[3];
|
||||
f[5].p1 = p[1]; f[5].p2 = p[5]; f[5].p3 = p[4];
|
||||
f[6].p1 = p[1]; f[6].p2 = p[2]; f[6].p3 = p[5];
|
||||
f[7].p1 = p[1]; f[7].p2 = p[3]; f[7].p3 = p[2];
|
||||
nt = 8;
|
||||
|
||||
/* Bisect each edge and move to the surface of a unit sphere */
|
||||
for (it=0;it<iterations;it++) {
|
||||
ntold = nt;
|
||||
for (i=0;i<ntold;i++) {
|
||||
pa.x = (f[i].p1.x + f[i].p2.x) / 2;
|
||||
pa.y = (f[i].p1.y + f[i].p2.y) / 2;
|
||||
pa.z = (f[i].p1.z + f[i].p2.z) / 2;
|
||||
pb.x = (f[i].p2.x + f[i].p3.x) / 2;
|
||||
pb.y = (f[i].p2.y + f[i].p3.y) / 2;
|
||||
pb.z = (f[i].p2.z + f[i].p3.z) / 2;
|
||||
pc.x = (f[i].p3.x + f[i].p1.x) / 2;
|
||||
pc.y = (f[i].p3.y + f[i].p1.y) / 2;
|
||||
pc.z = (f[i].p3.z + f[i].p1.z) / 2;
|
||||
pa.normalize();
|
||||
pb.normalize();
|
||||
pc.normalize();
|
||||
f[nt].p1 = f[i].p1; f[nt].p2 = pa; f[nt].p3 = pc; nt++;
|
||||
f[nt].p1 = pa; f[nt].p2 = f[i].p2; f[nt].p3 = pb; nt++;
|
||||
f[nt].p1 = pb; f[nt].p2 = f[i].p3; f[nt].p3 = pc; nt++;
|
||||
f[i].p1 = pa;
|
||||
f[i].p2 = pb;
|
||||
f[i].p3 = pc;
|
||||
}
|
||||
}
|
||||
|
||||
m_sphereVertices = (GLfloat *)malloc(sizeof(GLfloat) * m_cVertices * 3);
|
||||
assert(m_sphereVertices != NULL);
|
||||
GLfloat *pDest = m_sphereVertices;
|
||||
for(int facet_index=0; facet_index < facet_count; facet_index++) {
|
||||
*pDest++ = f[facet_index].p1.x;
|
||||
*pDest++ = f[facet_index].p1.y;
|
||||
*pDest++ = f[facet_index].p1.z;
|
||||
*pDest++ = f[facet_index].p2.x;
|
||||
*pDest++ = f[facet_index].p2.y;
|
||||
*pDest++ = f[facet_index].p2.z;
|
||||
*pDest++ = f[facet_index].p3.x;
|
||||
*pDest++ = f[facet_index].p3.y;
|
||||
*pDest++ = f[facet_index].p3.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,204 +1,204 @@
|
||||
//
|
||||
// KRRenderSettings.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-20.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRRenderSettings.h"
|
||||
|
||||
KRRenderSettings::KRRenderSettings()
|
||||
{
|
||||
siren_enable = true;
|
||||
siren_enable_reverb = true;
|
||||
siren_enable_hrtf = true;
|
||||
siren_reverb_max_length = 2.0f;
|
||||
|
||||
m_enable_realtime_occlusion = false;
|
||||
bShowShadowBuffer = false;
|
||||
bShowOctree = false;
|
||||
bShowDeferred = false;
|
||||
bEnablePerPixel = true;
|
||||
bEnableDiffuseMap = true;
|
||||
bEnableNormalMap = true;
|
||||
bEnableSpecMap = true;
|
||||
bEnableReflectionMap = true;
|
||||
bEnableReflection = true;
|
||||
bDebugPSSM = false;
|
||||
bEnableAmbient = true;
|
||||
bEnableDiffuse = true;
|
||||
bEnableSpecular = true;
|
||||
bEnableLightMap = true;
|
||||
bEnableDeferredLighting = false;
|
||||
max_anisotropy = 4.0f;
|
||||
|
||||
ambient_intensity = Vector3::Zero();
|
||||
light_intensity = Vector3::One();
|
||||
|
||||
perspective_fov = 45.0f * D2R;
|
||||
perspective_nearz = 0.3f; // was 0.05f
|
||||
perspective_farz = 1000.0f;
|
||||
|
||||
dof_quality = 0;
|
||||
dof_depth = 0.05f;
|
||||
dof_falloff = 0.05f;
|
||||
|
||||
bEnableFlash = false;
|
||||
flash_intensity = 1.0f;
|
||||
flash_depth = 0.7f;
|
||||
flash_falloff = 0.5f;
|
||||
|
||||
|
||||
bEnableVignette = false;
|
||||
vignette_radius = 0.4f;
|
||||
vignette_falloff = 1.0f;
|
||||
|
||||
|
||||
m_cShadowBuffers = 0;
|
||||
|
||||
volumetric_environment_enable = false;
|
||||
volumetric_environment_downsample = 2;
|
||||
volumetric_environment_max_distance = 100.0f;
|
||||
volumetric_environment_quality = (50.0f - 5.0f) / 495.0f;
|
||||
volumetric_environment_intensity = 0.9f;
|
||||
|
||||
|
||||
fog_near = 50.0f;
|
||||
fog_far = 500.0f;
|
||||
fog_density = 0.0005f;
|
||||
fog_color = Vector3::Create(0.45f, 0.45f, 0.5f);
|
||||
fog_type = 0;
|
||||
|
||||
dust_particle_intensity = 0.25f;
|
||||
dust_particle_enable = false;
|
||||
|
||||
m_lodBias = 0.0f;
|
||||
|
||||
debug_display = KRENGINE_DEBUG_DISPLAY_NONE;
|
||||
}
|
||||
|
||||
KRRenderSettings::~KRRenderSettings()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KRRenderSettings& KRRenderSettings::operator=(const KRRenderSettings &s)
|
||||
{
|
||||
siren_enable = s.siren_enable;
|
||||
siren_enable_reverb = s.siren_enable_reverb;
|
||||
siren_enable_hrtf = s.siren_enable_hrtf;
|
||||
siren_reverb_max_length = s.siren_reverb_max_length;
|
||||
|
||||
bEnablePerPixel = s.bEnablePerPixel;
|
||||
bEnableDiffuseMap = s.bEnableDiffuseMap;
|
||||
bEnableNormalMap = s.bEnableNormalMap;
|
||||
bEnableSpecMap = s.bEnableSpecMap;
|
||||
bEnableReflectionMap = s.bEnableReflectionMap;
|
||||
bEnableReflection=s.bEnableReflection;
|
||||
bEnableLightMap=s.bEnableLightMap;
|
||||
bDebugPSSM=s.bDebugPSSM;
|
||||
bShowShadowBuffer=s.bShowShadowBuffer;
|
||||
bShowOctree=s.bShowOctree;
|
||||
bShowDeferred=s.bShowDeferred;
|
||||
bEnableAmbient=s.bEnableAmbient;
|
||||
bEnableDiffuse=s.bEnableDiffuse;
|
||||
bEnableSpecular=s.bEnableSpecular;
|
||||
bEnableDeferredLighting=s.bEnableDeferredLighting;
|
||||
light_intensity=s.light_intensity;
|
||||
ambient_intensity=s.ambient_intensity;
|
||||
perspective_fov=s.perspective_fov;
|
||||
|
||||
dof_quality=s.dof_quality;
|
||||
dof_depth=s.dof_depth;
|
||||
dof_falloff=s.dof_falloff;
|
||||
bEnableFlash=s.bEnableFlash;
|
||||
flash_intensity=s.flash_intensity;
|
||||
flash_depth=s.flash_depth;
|
||||
flash_falloff=s.flash_falloff;
|
||||
|
||||
bEnableVignette=s.bEnableVignette;
|
||||
vignette_radius=s.vignette_radius;
|
||||
vignette_falloff=s.vignette_falloff;
|
||||
|
||||
m_viewportSize=s.m_viewportSize;
|
||||
|
||||
m_cShadowBuffers=s.m_cShadowBuffers;
|
||||
|
||||
m_debug_text=s.m_debug_text;
|
||||
|
||||
volumetric_environment_enable=s.volumetric_environment_enable;
|
||||
volumetric_environment_downsample=s.volumetric_environment_downsample;
|
||||
volumetric_environment_max_distance=s.volumetric_environment_max_distance;
|
||||
volumetric_environment_quality=s.volumetric_environment_quality;
|
||||
volumetric_environment_intensity=s.volumetric_environment_intensity;
|
||||
|
||||
fog_near=s.fog_near;
|
||||
fog_far=s.fog_far;
|
||||
fog_density=s.fog_density;
|
||||
fog_color=s.fog_color;
|
||||
fog_type=s.fog_type;
|
||||
|
||||
dust_particle_intensity=s.dust_particle_intensity;
|
||||
dust_particle_enable=s.dust_particle_enable;
|
||||
perspective_nearz=s.perspective_nearz;
|
||||
perspective_farz=s.perspective_farz;
|
||||
debug_display = s.debug_display;
|
||||
|
||||
m_lodBias = s.m_lodBias;
|
||||
m_enable_realtime_occlusion = s.m_enable_realtime_occlusion;
|
||||
|
||||
max_anisotropy = s.max_anisotropy;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Vector2 &KRRenderSettings::getViewportSize() {
|
||||
return m_viewportSize;
|
||||
}
|
||||
|
||||
void KRRenderSettings::setViewportSize(const Vector2 &size) {
|
||||
m_viewportSize = size;
|
||||
}
|
||||
|
||||
float KRRenderSettings::getPerspectiveNearZ()
|
||||
{
|
||||
return perspective_nearz;
|
||||
}
|
||||
float KRRenderSettings::getPerspectiveFarZ()
|
||||
{
|
||||
return perspective_farz;
|
||||
}
|
||||
|
||||
void KRRenderSettings::setPerspectiveNear(float v)
|
||||
{
|
||||
if(perspective_nearz != v) {
|
||||
perspective_nearz = v;
|
||||
}
|
||||
}
|
||||
void KRRenderSettings::setPerpsectiveFarZ(float v)
|
||||
{
|
||||
if(perspective_farz != v) {
|
||||
perspective_farz = v;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float KRRenderSettings::getLODBias()
|
||||
{
|
||||
return m_lodBias;
|
||||
}
|
||||
|
||||
void KRRenderSettings::setLODBias(float v)
|
||||
{
|
||||
m_lodBias = v;
|
||||
}
|
||||
|
||||
bool KRRenderSettings::getEnableRealtimeOcclusion()
|
||||
{
|
||||
return m_enable_realtime_occlusion;
|
||||
}
|
||||
void KRRenderSettings::setEnableRealtimeOcclusion(bool enable)
|
||||
{
|
||||
m_enable_realtime_occlusion = enable;
|
||||
//
|
||||
// KRRenderSettings.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-20.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRRenderSettings.h"
|
||||
|
||||
KRRenderSettings::KRRenderSettings()
|
||||
{
|
||||
siren_enable = true;
|
||||
siren_enable_reverb = true;
|
||||
siren_enable_hrtf = true;
|
||||
siren_reverb_max_length = 2.0f;
|
||||
|
||||
m_enable_realtime_occlusion = false;
|
||||
bShowShadowBuffer = false;
|
||||
bShowOctree = false;
|
||||
bShowDeferred = false;
|
||||
bEnablePerPixel = true;
|
||||
bEnableDiffuseMap = true;
|
||||
bEnableNormalMap = true;
|
||||
bEnableSpecMap = true;
|
||||
bEnableReflectionMap = true;
|
||||
bEnableReflection = true;
|
||||
bDebugPSSM = false;
|
||||
bEnableAmbient = true;
|
||||
bEnableDiffuse = true;
|
||||
bEnableSpecular = true;
|
||||
bEnableLightMap = true;
|
||||
bEnableDeferredLighting = false;
|
||||
max_anisotropy = 4.0f;
|
||||
|
||||
ambient_intensity = Vector3::Zero();
|
||||
light_intensity = Vector3::One();
|
||||
|
||||
perspective_fov = 45.0f * D2R;
|
||||
perspective_nearz = 0.3f; // was 0.05f
|
||||
perspective_farz = 1000.0f;
|
||||
|
||||
dof_quality = 0;
|
||||
dof_depth = 0.05f;
|
||||
dof_falloff = 0.05f;
|
||||
|
||||
bEnableFlash = false;
|
||||
flash_intensity = 1.0f;
|
||||
flash_depth = 0.7f;
|
||||
flash_falloff = 0.5f;
|
||||
|
||||
|
||||
bEnableVignette = false;
|
||||
vignette_radius = 0.4f;
|
||||
vignette_falloff = 1.0f;
|
||||
|
||||
|
||||
m_cShadowBuffers = 0;
|
||||
|
||||
volumetric_environment_enable = false;
|
||||
volumetric_environment_downsample = 2;
|
||||
volumetric_environment_max_distance = 100.0f;
|
||||
volumetric_environment_quality = (50.0f - 5.0f) / 495.0f;
|
||||
volumetric_environment_intensity = 0.9f;
|
||||
|
||||
|
||||
fog_near = 50.0f;
|
||||
fog_far = 500.0f;
|
||||
fog_density = 0.0005f;
|
||||
fog_color = Vector3::Create(0.45f, 0.45f, 0.5f);
|
||||
fog_type = 0;
|
||||
|
||||
dust_particle_intensity = 0.25f;
|
||||
dust_particle_enable = false;
|
||||
|
||||
m_lodBias = 0.0f;
|
||||
|
||||
debug_display = KRENGINE_DEBUG_DISPLAY_NONE;
|
||||
}
|
||||
|
||||
KRRenderSettings::~KRRenderSettings()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KRRenderSettings& KRRenderSettings::operator=(const KRRenderSettings &s)
|
||||
{
|
||||
siren_enable = s.siren_enable;
|
||||
siren_enable_reverb = s.siren_enable_reverb;
|
||||
siren_enable_hrtf = s.siren_enable_hrtf;
|
||||
siren_reverb_max_length = s.siren_reverb_max_length;
|
||||
|
||||
bEnablePerPixel = s.bEnablePerPixel;
|
||||
bEnableDiffuseMap = s.bEnableDiffuseMap;
|
||||
bEnableNormalMap = s.bEnableNormalMap;
|
||||
bEnableSpecMap = s.bEnableSpecMap;
|
||||
bEnableReflectionMap = s.bEnableReflectionMap;
|
||||
bEnableReflection=s.bEnableReflection;
|
||||
bEnableLightMap=s.bEnableLightMap;
|
||||
bDebugPSSM=s.bDebugPSSM;
|
||||
bShowShadowBuffer=s.bShowShadowBuffer;
|
||||
bShowOctree=s.bShowOctree;
|
||||
bShowDeferred=s.bShowDeferred;
|
||||
bEnableAmbient=s.bEnableAmbient;
|
||||
bEnableDiffuse=s.bEnableDiffuse;
|
||||
bEnableSpecular=s.bEnableSpecular;
|
||||
bEnableDeferredLighting=s.bEnableDeferredLighting;
|
||||
light_intensity=s.light_intensity;
|
||||
ambient_intensity=s.ambient_intensity;
|
||||
perspective_fov=s.perspective_fov;
|
||||
|
||||
dof_quality=s.dof_quality;
|
||||
dof_depth=s.dof_depth;
|
||||
dof_falloff=s.dof_falloff;
|
||||
bEnableFlash=s.bEnableFlash;
|
||||
flash_intensity=s.flash_intensity;
|
||||
flash_depth=s.flash_depth;
|
||||
flash_falloff=s.flash_falloff;
|
||||
|
||||
bEnableVignette=s.bEnableVignette;
|
||||
vignette_radius=s.vignette_radius;
|
||||
vignette_falloff=s.vignette_falloff;
|
||||
|
||||
m_viewportSize=s.m_viewportSize;
|
||||
|
||||
m_cShadowBuffers=s.m_cShadowBuffers;
|
||||
|
||||
m_debug_text=s.m_debug_text;
|
||||
|
||||
volumetric_environment_enable=s.volumetric_environment_enable;
|
||||
volumetric_environment_downsample=s.volumetric_environment_downsample;
|
||||
volumetric_environment_max_distance=s.volumetric_environment_max_distance;
|
||||
volumetric_environment_quality=s.volumetric_environment_quality;
|
||||
volumetric_environment_intensity=s.volumetric_environment_intensity;
|
||||
|
||||
fog_near=s.fog_near;
|
||||
fog_far=s.fog_far;
|
||||
fog_density=s.fog_density;
|
||||
fog_color=s.fog_color;
|
||||
fog_type=s.fog_type;
|
||||
|
||||
dust_particle_intensity=s.dust_particle_intensity;
|
||||
dust_particle_enable=s.dust_particle_enable;
|
||||
perspective_nearz=s.perspective_nearz;
|
||||
perspective_farz=s.perspective_farz;
|
||||
debug_display = s.debug_display;
|
||||
|
||||
m_lodBias = s.m_lodBias;
|
||||
m_enable_realtime_occlusion = s.m_enable_realtime_occlusion;
|
||||
|
||||
max_anisotropy = s.max_anisotropy;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Vector2 &KRRenderSettings::getViewportSize() {
|
||||
return m_viewportSize;
|
||||
}
|
||||
|
||||
void KRRenderSettings::setViewportSize(const Vector2 &size) {
|
||||
m_viewportSize = size;
|
||||
}
|
||||
|
||||
float KRRenderSettings::getPerspectiveNearZ()
|
||||
{
|
||||
return perspective_nearz;
|
||||
}
|
||||
float KRRenderSettings::getPerspectiveFarZ()
|
||||
{
|
||||
return perspective_farz;
|
||||
}
|
||||
|
||||
void KRRenderSettings::setPerspectiveNear(float v)
|
||||
{
|
||||
if(perspective_nearz != v) {
|
||||
perspective_nearz = v;
|
||||
}
|
||||
}
|
||||
void KRRenderSettings::setPerpsectiveFarZ(float v)
|
||||
{
|
||||
if(perspective_farz != v) {
|
||||
perspective_farz = v;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float KRRenderSettings::getLODBias()
|
||||
{
|
||||
return m_lodBias;
|
||||
}
|
||||
|
||||
void KRRenderSettings::setLODBias(float v)
|
||||
{
|
||||
m_lodBias = v;
|
||||
}
|
||||
|
||||
bool KRRenderSettings::getEnableRealtimeOcclusion()
|
||||
{
|
||||
return m_enable_realtime_occlusion;
|
||||
}
|
||||
void KRRenderSettings::setEnableRealtimeOcclusion(bool enable)
|
||||
{
|
||||
m_enable_realtime_occlusion = enable;
|
||||
}
|
||||
@@ -1,341 +1,341 @@
|
||||
//
|
||||
// KRResource_obj.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-03-22.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRResource.h"
|
||||
#include "KRMesh.h"
|
||||
|
||||
std::vector<KRResource *> KRResource::LoadObj(KRContext &context, const std::string& path)
|
||||
{
|
||||
std::vector<KRResource *> resources;
|
||||
|
||||
KRMesh *new_mesh = new KRMesh(context, KRResource::GetFileBase(path));
|
||||
resources.push_back(new_mesh);
|
||||
|
||||
KRMesh::mesh_info mi;
|
||||
|
||||
std::vector<std::string> material_names_t;
|
||||
|
||||
KRDataBlock data;
|
||||
|
||||
char szSymbol[500][256];
|
||||
|
||||
int *pFaces = NULL;
|
||||
|
||||
vector<KRMesh::pack_material *> m_materials;
|
||||
|
||||
if(data.load(path)) {
|
||||
// -----=====----- Get counts -----=====-----
|
||||
|
||||
int cVertexData = 0;
|
||||
|
||||
|
||||
int cFaces = 1;
|
||||
int cMaterialFaceStart = 1;
|
||||
|
||||
char *pScan = (char *)data.getStart();
|
||||
char *pEnd = (char *)data.getEnd();
|
||||
while(pScan < pEnd) {
|
||||
|
||||
// Scan through whitespace
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||
pScan++;
|
||||
}
|
||||
|
||||
if(*pScan == '#') {
|
||||
// Line is a comment line
|
||||
|
||||
// Scan to the end of the line
|
||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||
pScan++;
|
||||
}
|
||||
} else {
|
||||
int cSymbols = 0;
|
||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||
|
||||
char *pDest = szSymbol[cSymbols++];
|
||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// Scan through whitespace, but don't advance to next line
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
||||
pScan++;
|
||||
}
|
||||
}
|
||||
|
||||
if(strcmp(szSymbol[0], "v") == 0) {
|
||||
// Vertex (v)
|
||||
} else if(strcmp(szSymbol[0], "vt") == 0) {
|
||||
// Vertex Texture UV Coordinate (vt)
|
||||
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
||||
// Vertex Normal (vn)
|
||||
} else if(strcmp(szSymbol[0], "f") == 0) {
|
||||
// Face (f)
|
||||
int cFaceVertexes = (cSymbols - 3) * 3; // 3 vertexes per triangle. Triangles have 4 symbols. Quads have 5 symbols and generate two triangles.
|
||||
cVertexData += cFaceVertexes;
|
||||
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) {
|
||||
// Use Material (usemtl)
|
||||
if(cMaterialFaceStart - cFaces > 0) {
|
||||
cFaces++;
|
||||
|
||||
}
|
||||
material_names_t.push_back(std::string(szSymbol[1]));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----=====----- Populate vertexes and faces -----=====-----
|
||||
|
||||
int *pFaces = (int *)malloc(sizeof(int) * (cFaces + 1));
|
||||
assert(pFaces != NULL);
|
||||
|
||||
std::vector<Vector3> indexed_vertices;
|
||||
std::vector<Vector2> indexed_uva;
|
||||
std::vector<Vector3> indexed_normals;
|
||||
|
||||
int *pFace = pFaces;
|
||||
int *pMaterialFaces = pFace++;
|
||||
*pMaterialFaces = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
// --------
|
||||
|
||||
pScan = (char *)data.getStart();
|
||||
while(pScan < pEnd) {
|
||||
|
||||
// Scan through whitespace
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||
pScan++;
|
||||
}
|
||||
|
||||
if(*pScan == '#') {
|
||||
// Line is a comment line
|
||||
|
||||
// Scan to the end of the line
|
||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||
pScan++;
|
||||
}
|
||||
} else {
|
||||
int cSymbols = 0;
|
||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||
|
||||
char *pDest = szSymbol[cSymbols++];
|
||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// Scan through whitespace, but don't advance to next line
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
||||
pScan++;
|
||||
}
|
||||
}
|
||||
|
||||
if(strcmp(szSymbol[0], "v") == 0) {
|
||||
// Vertex (v)
|
||||
float x, y, z;
|
||||
char *pChar = szSymbol[1];
|
||||
x = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
y = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[3];
|
||||
z = strtof(pChar, &pChar);
|
||||
indexed_vertices.push_back(Vector3::Create(x,y,z));
|
||||
} else if(strcmp(szSymbol[0], "vt") == 0) {
|
||||
// Vertex Texture UV Coordinate (vt)
|
||||
char *pChar = szSymbol[1];
|
||||
float u,v;
|
||||
|
||||
u = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
v = strtof(pChar, &pChar);
|
||||
indexed_uva.push_back(Vector2::Create(u,v));
|
||||
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
||||
// Vertex Normal (vn)
|
||||
float x,y,z;
|
||||
char *pChar = szSymbol[1];
|
||||
x = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
y = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[3];
|
||||
z = strtof(pChar, &pChar);
|
||||
indexed_normals.push_back(Vector3::Create(x,y,z));
|
||||
} else if(strcmp(szSymbol[0], "f") == 0) {
|
||||
// Face (f)
|
||||
int cFaceVertices = cSymbols - 1;
|
||||
|
||||
*pFace++ = cFaceVertices;
|
||||
for(int iSymbol=1; iSymbol < cSymbols; iSymbol++) {
|
||||
char *pChar = szSymbol[iSymbol];
|
||||
if(*pChar == '.' || (*pChar >= '0' && *pChar <= '9')) {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Vertex Index
|
||||
|
||||
if(*pChar == '/') {
|
||||
pChar++;
|
||||
if(*pChar == '/') {
|
||||
*pFace++ = -1;
|
||||
} else {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Texture Coordinate Index
|
||||
}
|
||||
} else {
|
||||
*pFace++ = -1;
|
||||
}
|
||||
|
||||
if(*pChar == '/') {
|
||||
pChar++;
|
||||
if(*pChar == '/') {
|
||||
*pFace++ = -1;
|
||||
} else {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Normal Index
|
||||
}
|
||||
} else {
|
||||
*pFace++ = -1;
|
||||
}
|
||||
while(*pChar == '/') {
|
||||
pChar++;
|
||||
strtol(pChar, &pChar, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else if(strcmp(szSymbol[0], "usemtl") == 0) {
|
||||
// Use Material (usemtl)
|
||||
if(pFace - pMaterialFaces > 1) {
|
||||
*pMaterialFaces = pFace - pMaterialFaces - 1;
|
||||
pMaterialFaces = pFace++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*pMaterialFaces = pFace - pMaterialFaces - 1;
|
||||
*pFace++ = 0;
|
||||
|
||||
|
||||
int iVertex = 0;
|
||||
|
||||
|
||||
std::vector<std::string>::iterator material_itr = material_names_t.begin();
|
||||
KRMesh::pack_material *pMaterial = new KRMesh::pack_material();
|
||||
pMaterial->start_vertex = iVertex;
|
||||
pMaterial->vertex_count = 0;
|
||||
memset(pMaterial->szName, 256, 0);
|
||||
if(material_itr < material_names_t.end()) {
|
||||
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
|
||||
}
|
||||
m_materials.push_back(pMaterial);
|
||||
|
||||
|
||||
pFace = pFaces;
|
||||
while(*pFace != 0 && iVertex < cVertexData) {
|
||||
pMaterial->start_vertex = iVertex;
|
||||
|
||||
int *pMaterialEndFace = pFace + *pFace;
|
||||
++pFace;
|
||||
while(pFace < pMaterialEndFace && iVertex < cVertexData) {
|
||||
int cFaceVertexes = *pFace;
|
||||
Vector3 firstFaceVertex;
|
||||
Vector3 prevFaceVertex;
|
||||
Vector3 firstFaceNormal;
|
||||
Vector3 prevFaceNormal;
|
||||
Vector2 firstFaceUva;
|
||||
Vector2 prevFaceUva;
|
||||
for(int iFaceVertex=0; iFaceVertex < cFaceVertexes; iFaceVertex++) {
|
||||
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
|
||||
iVertex+=2;
|
||||
|
||||
mi.vertices.push_back(firstFaceVertex);
|
||||
mi.uva.push_back(firstFaceUva);
|
||||
mi.normals.push_back(firstFaceNormal);
|
||||
|
||||
mi.vertices.push_back(prevFaceVertex);
|
||||
mi.uva.push_back(prevFaceUva);
|
||||
mi.normals.push_back(prevFaceNormal);
|
||||
}
|
||||
Vector3 vertex = indexed_vertices[pFace[iFaceVertex*3+1]];
|
||||
Vector2 new_uva;
|
||||
if(pFace[iFaceVertex*3+2] >= 0) {
|
||||
new_uva = indexed_uva[pFace[iFaceVertex*3+2]];
|
||||
}
|
||||
Vector3 normal;
|
||||
if(pFace[iFaceVertex*3+3] >= 0){
|
||||
Vector3 normal = indexed_normals[pFace[iFaceVertex*3+3]];
|
||||
}
|
||||
|
||||
mi.vertices.push_back(vertex);
|
||||
mi.uva.push_back(new_uva);
|
||||
mi.normals.push_back(normal);
|
||||
|
||||
if(iFaceVertex==0) {
|
||||
firstFaceVertex = vertex;
|
||||
firstFaceUva = new_uva;
|
||||
firstFaceNormal = normal;
|
||||
}
|
||||
prevFaceVertex = vertex;
|
||||
prevFaceUva = new_uva;
|
||||
prevFaceNormal = normal;
|
||||
|
||||
iVertex++;
|
||||
}
|
||||
pFace += cFaceVertexes * 3 + 1;
|
||||
}
|
||||
pMaterial->vertex_count = iVertex - pMaterial->start_vertex;
|
||||
if(*pFace != 0) {
|
||||
pMaterial = new KRMesh::pack_material();
|
||||
pMaterial->start_vertex = iVertex;
|
||||
pMaterial->vertex_count = 0;
|
||||
memset(pMaterial->szName, 256, 0);
|
||||
|
||||
if(material_itr < material_names_t.end()) {
|
||||
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
|
||||
}
|
||||
m_materials.push_back(pMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
for(int iMaterial=0; iMaterial < m_materials.size(); iMaterial++) {
|
||||
KRMesh::pack_material *pNewMaterial = m_materials[iMaterial];
|
||||
if(pNewMaterial->vertex_count > 0) {
|
||||
mi.material_names.push_back(std::string(pNewMaterial->szName));
|
||||
mi.submesh_starts.push_back(pNewMaterial->start_vertex);
|
||||
mi.submesh_lengths.push_back(pNewMaterial->vertex_count);
|
||||
}
|
||||
delete pNewMaterial;
|
||||
}
|
||||
|
||||
// TODO: Bones not yet supported for OBJ
|
||||
// std::vector<std::string> bone_names;
|
||||
// std::vector<Matrix4> bone_bind_poses;
|
||||
// std::vector<std::vector<int> > bone_indexes;
|
||||
// std::vector<std::vector<float> > bone_weights;
|
||||
//
|
||||
// std::vector<__uint16_t> vertex_indexes;
|
||||
// std::vector<std::pair<int, int> > vertex_index_bases;
|
||||
|
||||
mi.format = KRMesh::KRENGINE_MODEL_FORMAT_TRIANGLES;
|
||||
new_mesh->LoadData(mi, true, false);
|
||||
}
|
||||
|
||||
if(pFaces) {
|
||||
free(pFaces);
|
||||
}
|
||||
|
||||
return resources;
|
||||
}
|
||||
//
|
||||
// KRResource_obj.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-03-22.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRResource.h"
|
||||
#include "KRMesh.h"
|
||||
|
||||
std::vector<KRResource *> KRResource::LoadObj(KRContext &context, const std::string& path)
|
||||
{
|
||||
std::vector<KRResource *> resources;
|
||||
|
||||
KRMesh *new_mesh = new KRMesh(context, KRResource::GetFileBase(path));
|
||||
resources.push_back(new_mesh);
|
||||
|
||||
KRMesh::mesh_info mi;
|
||||
|
||||
std::vector<std::string> material_names_t;
|
||||
|
||||
KRDataBlock data;
|
||||
|
||||
char szSymbol[500][256];
|
||||
|
||||
int *pFaces = NULL;
|
||||
|
||||
vector<KRMesh::pack_material *> m_materials;
|
||||
|
||||
if(data.load(path)) {
|
||||
// -----=====----- Get counts -----=====-----
|
||||
|
||||
int cVertexData = 0;
|
||||
|
||||
|
||||
int cFaces = 1;
|
||||
int cMaterialFaceStart = 1;
|
||||
|
||||
char *pScan = (char *)data.getStart();
|
||||
char *pEnd = (char *)data.getEnd();
|
||||
while(pScan < pEnd) {
|
||||
|
||||
// Scan through whitespace
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||
pScan++;
|
||||
}
|
||||
|
||||
if(*pScan == '#') {
|
||||
// Line is a comment line
|
||||
|
||||
// Scan to the end of the line
|
||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||
pScan++;
|
||||
}
|
||||
} else {
|
||||
int cSymbols = 0;
|
||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||
|
||||
char *pDest = szSymbol[cSymbols++];
|
||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// Scan through whitespace, but don't advance to next line
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
||||
pScan++;
|
||||
}
|
||||
}
|
||||
|
||||
if(strcmp(szSymbol[0], "v") == 0) {
|
||||
// Vertex (v)
|
||||
} else if(strcmp(szSymbol[0], "vt") == 0) {
|
||||
// Vertex Texture UV Coordinate (vt)
|
||||
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
||||
// Vertex Normal (vn)
|
||||
} else if(strcmp(szSymbol[0], "f") == 0) {
|
||||
// Face (f)
|
||||
int cFaceVertexes = (cSymbols - 3) * 3; // 3 vertexes per triangle. Triangles have 4 symbols. Quads have 5 symbols and generate two triangles.
|
||||
cVertexData += cFaceVertexes;
|
||||
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) {
|
||||
// Use Material (usemtl)
|
||||
if(cMaterialFaceStart - cFaces > 0) {
|
||||
cFaces++;
|
||||
|
||||
}
|
||||
material_names_t.push_back(std::string(szSymbol[1]));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----=====----- Populate vertexes and faces -----=====-----
|
||||
|
||||
int *pFaces = (int *)malloc(sizeof(int) * (cFaces + 1));
|
||||
assert(pFaces != NULL);
|
||||
|
||||
std::vector<Vector3> indexed_vertices;
|
||||
std::vector<Vector2> indexed_uva;
|
||||
std::vector<Vector3> indexed_normals;
|
||||
|
||||
int *pFace = pFaces;
|
||||
int *pMaterialFaces = pFace++;
|
||||
*pMaterialFaces = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
// --------
|
||||
|
||||
pScan = (char *)data.getStart();
|
||||
while(pScan < pEnd) {
|
||||
|
||||
// Scan through whitespace
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||
pScan++;
|
||||
}
|
||||
|
||||
if(*pScan == '#') {
|
||||
// Line is a comment line
|
||||
|
||||
// Scan to the end of the line
|
||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||
pScan++;
|
||||
}
|
||||
} else {
|
||||
int cSymbols = 0;
|
||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||
|
||||
char *pDest = szSymbol[cSymbols++];
|
||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// Scan through whitespace, but don't advance to next line
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
||||
pScan++;
|
||||
}
|
||||
}
|
||||
|
||||
if(strcmp(szSymbol[0], "v") == 0) {
|
||||
// Vertex (v)
|
||||
float x, y, z;
|
||||
char *pChar = szSymbol[1];
|
||||
x = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
y = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[3];
|
||||
z = strtof(pChar, &pChar);
|
||||
indexed_vertices.push_back(Vector3::Create(x,y,z));
|
||||
} else if(strcmp(szSymbol[0], "vt") == 0) {
|
||||
// Vertex Texture UV Coordinate (vt)
|
||||
char *pChar = szSymbol[1];
|
||||
float u,v;
|
||||
|
||||
u = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
v = strtof(pChar, &pChar);
|
||||
indexed_uva.push_back(Vector2::Create(u,v));
|
||||
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
||||
// Vertex Normal (vn)
|
||||
float x,y,z;
|
||||
char *pChar = szSymbol[1];
|
||||
x = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
y = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[3];
|
||||
z = strtof(pChar, &pChar);
|
||||
indexed_normals.push_back(Vector3::Create(x,y,z));
|
||||
} else if(strcmp(szSymbol[0], "f") == 0) {
|
||||
// Face (f)
|
||||
int cFaceVertices = cSymbols - 1;
|
||||
|
||||
*pFace++ = cFaceVertices;
|
||||
for(int iSymbol=1; iSymbol < cSymbols; iSymbol++) {
|
||||
char *pChar = szSymbol[iSymbol];
|
||||
if(*pChar == '.' || (*pChar >= '0' && *pChar <= '9')) {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Vertex Index
|
||||
|
||||
if(*pChar == '/') {
|
||||
pChar++;
|
||||
if(*pChar == '/') {
|
||||
*pFace++ = -1;
|
||||
} else {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Texture Coordinate Index
|
||||
}
|
||||
} else {
|
||||
*pFace++ = -1;
|
||||
}
|
||||
|
||||
if(*pChar == '/') {
|
||||
pChar++;
|
||||
if(*pChar == '/') {
|
||||
*pFace++ = -1;
|
||||
} else {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Normal Index
|
||||
}
|
||||
} else {
|
||||
*pFace++ = -1;
|
||||
}
|
||||
while(*pChar == '/') {
|
||||
pChar++;
|
||||
strtol(pChar, &pChar, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else if(strcmp(szSymbol[0], "usemtl") == 0) {
|
||||
// Use Material (usemtl)
|
||||
if(pFace - pMaterialFaces > 1) {
|
||||
*pMaterialFaces = pFace - pMaterialFaces - 1;
|
||||
pMaterialFaces = pFace++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*pMaterialFaces = pFace - pMaterialFaces - 1;
|
||||
*pFace++ = 0;
|
||||
|
||||
|
||||
int iVertex = 0;
|
||||
|
||||
|
||||
std::vector<std::string>::iterator material_itr = material_names_t.begin();
|
||||
KRMesh::pack_material *pMaterial = new KRMesh::pack_material();
|
||||
pMaterial->start_vertex = iVertex;
|
||||
pMaterial->vertex_count = 0;
|
||||
memset(pMaterial->szName, 256, 0);
|
||||
if(material_itr < material_names_t.end()) {
|
||||
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
|
||||
}
|
||||
m_materials.push_back(pMaterial);
|
||||
|
||||
|
||||
pFace = pFaces;
|
||||
while(*pFace != 0 && iVertex < cVertexData) {
|
||||
pMaterial->start_vertex = iVertex;
|
||||
|
||||
int *pMaterialEndFace = pFace + *pFace;
|
||||
++pFace;
|
||||
while(pFace < pMaterialEndFace && iVertex < cVertexData) {
|
||||
int cFaceVertexes = *pFace;
|
||||
Vector3 firstFaceVertex;
|
||||
Vector3 prevFaceVertex;
|
||||
Vector3 firstFaceNormal;
|
||||
Vector3 prevFaceNormal;
|
||||
Vector2 firstFaceUva;
|
||||
Vector2 prevFaceUva;
|
||||
for(int iFaceVertex=0; iFaceVertex < cFaceVertexes; iFaceVertex++) {
|
||||
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
|
||||
iVertex+=2;
|
||||
|
||||
mi.vertices.push_back(firstFaceVertex);
|
||||
mi.uva.push_back(firstFaceUva);
|
||||
mi.normals.push_back(firstFaceNormal);
|
||||
|
||||
mi.vertices.push_back(prevFaceVertex);
|
||||
mi.uva.push_back(prevFaceUva);
|
||||
mi.normals.push_back(prevFaceNormal);
|
||||
}
|
||||
Vector3 vertex = indexed_vertices[pFace[iFaceVertex*3+1]];
|
||||
Vector2 new_uva;
|
||||
if(pFace[iFaceVertex*3+2] >= 0) {
|
||||
new_uva = indexed_uva[pFace[iFaceVertex*3+2]];
|
||||
}
|
||||
Vector3 normal;
|
||||
if(pFace[iFaceVertex*3+3] >= 0){
|
||||
Vector3 normal = indexed_normals[pFace[iFaceVertex*3+3]];
|
||||
}
|
||||
|
||||
mi.vertices.push_back(vertex);
|
||||
mi.uva.push_back(new_uva);
|
||||
mi.normals.push_back(normal);
|
||||
|
||||
if(iFaceVertex==0) {
|
||||
firstFaceVertex = vertex;
|
||||
firstFaceUva = new_uva;
|
||||
firstFaceNormal = normal;
|
||||
}
|
||||
prevFaceVertex = vertex;
|
||||
prevFaceUva = new_uva;
|
||||
prevFaceNormal = normal;
|
||||
|
||||
iVertex++;
|
||||
}
|
||||
pFace += cFaceVertexes * 3 + 1;
|
||||
}
|
||||
pMaterial->vertex_count = iVertex - pMaterial->start_vertex;
|
||||
if(*pFace != 0) {
|
||||
pMaterial = new KRMesh::pack_material();
|
||||
pMaterial->start_vertex = iVertex;
|
||||
pMaterial->vertex_count = 0;
|
||||
memset(pMaterial->szName, 256, 0);
|
||||
|
||||
if(material_itr < material_names_t.end()) {
|
||||
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
|
||||
}
|
||||
m_materials.push_back(pMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
for(int iMaterial=0; iMaterial < m_materials.size(); iMaterial++) {
|
||||
KRMesh::pack_material *pNewMaterial = m_materials[iMaterial];
|
||||
if(pNewMaterial->vertex_count > 0) {
|
||||
mi.material_names.push_back(std::string(pNewMaterial->szName));
|
||||
mi.submesh_starts.push_back(pNewMaterial->start_vertex);
|
||||
mi.submesh_lengths.push_back(pNewMaterial->vertex_count);
|
||||
}
|
||||
delete pNewMaterial;
|
||||
}
|
||||
|
||||
// TODO: Bones not yet supported for OBJ
|
||||
// std::vector<std::string> bone_names;
|
||||
// std::vector<Matrix4> bone_bind_poses;
|
||||
// std::vector<std::vector<int> > bone_indexes;
|
||||
// std::vector<std::vector<float> > bone_weights;
|
||||
//
|
||||
// std::vector<__uint16_t> vertex_indexes;
|
||||
// std::vector<std::pair<int, int> > vertex_index_bases;
|
||||
|
||||
mi.format = KRMesh::KRENGINE_MODEL_FORMAT_TRIANGLES;
|
||||
new_mesh->LoadData(mi, true, false);
|
||||
}
|
||||
|
||||
if(pFaces) {
|
||||
free(pFaces);
|
||||
}
|
||||
|
||||
return resources;
|
||||
}
|
||||
|
||||
@@ -1,166 +1,166 @@
|
||||
//
|
||||
// KRReverbZone.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-06.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRReverbZone.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRReverbZone::KRReverbZone(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_reverb = "";
|
||||
m_reverb_gain = 1.0f;
|
||||
m_gradient_distance = 0.25f;
|
||||
|
||||
}
|
||||
|
||||
KRReverbZone::~KRReverbZone()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRReverbZone::getElementName() {
|
||||
return "reverb_zone";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRReverbZone::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("zone", m_zone.c_str());
|
||||
e->SetAttribute("sample", m_reverb.c_str());
|
||||
e->SetAttribute("gain", m_reverb_gain);
|
||||
e->SetAttribute("gradient", m_gradient_distance);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRReverbZone::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRNode::loadXML(e);
|
||||
|
||||
m_zone = e->Attribute("zone");
|
||||
|
||||
m_gradient_distance = 0.25f;
|
||||
if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
|
||||
m_gradient_distance = 0.25f;
|
||||
}
|
||||
|
||||
m_reverb = e->Attribute("sample");
|
||||
|
||||
m_reverb_gain = 1.0f;
|
||||
if(e->QueryFloatAttribute("gain", &m_reverb_gain) != tinyxml2::XML_SUCCESS) {
|
||||
m_reverb_gain = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
std::string KRReverbZone::getReverb()
|
||||
{
|
||||
return m_reverb;
|
||||
}
|
||||
|
||||
void KRReverbZone::setReverb(const std::string &reverb)
|
||||
{
|
||||
m_reverb = reverb;
|
||||
}
|
||||
|
||||
float KRReverbZone::getReverbGain()
|
||||
{
|
||||
return m_reverb_gain;
|
||||
}
|
||||
|
||||
void KRReverbZone::setReverbGain(float reverb_gain)
|
||||
{
|
||||
m_reverb_gain = reverb_gain;
|
||||
}
|
||||
|
||||
std::string KRReverbZone::getZone()
|
||||
{
|
||||
return m_zone;
|
||||
}
|
||||
|
||||
void KRReverbZone::setZone(const std::string &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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_REVERB_ZONES;
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
||||
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);
|
||||
|
||||
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
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
||||
if(sphereModels.size()) {
|
||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float KRReverbZone::getGradientDistance()
|
||||
{
|
||||
return m_gradient_distance;
|
||||
}
|
||||
|
||||
void KRReverbZone::setGradientDistance(float gradient_distance)
|
||||
{
|
||||
m_gradient_distance = gradient_distance;
|
||||
}
|
||||
|
||||
AABB KRReverbZone::getBounds() {
|
||||
// Reverb zones always have a -1, -1, -1 to 1, 1, 1 bounding box
|
||||
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
|
||||
}
|
||||
|
||||
float KRReverbZone::getContainment(const Vector3 &pos)
|
||||
{
|
||||
AABB bounds = getBounds();
|
||||
if(bounds.contains(pos)) {
|
||||
Vector3 size = bounds.size();
|
||||
Vector3 diff = pos - bounds.center();
|
||||
diff = diff * 2.0f;
|
||||
diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z);
|
||||
float d = diff.magnitude();
|
||||
|
||||
if(m_gradient_distance <= 0.0f) {
|
||||
// Avoid division by zero
|
||||
d = d > 1.0f ? 0.0f : 1.0f;
|
||||
} else {
|
||||
d = (1.0f - d) / m_gradient_distance;
|
||||
d = KRCLAMP(d, 0.0f, 1.0f);
|
||||
}
|
||||
return d;
|
||||
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
//
|
||||
// KRReverbZone.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-06.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRReverbZone.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRReverbZone::KRReverbZone(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_reverb = "";
|
||||
m_reverb_gain = 1.0f;
|
||||
m_gradient_distance = 0.25f;
|
||||
|
||||
}
|
||||
|
||||
KRReverbZone::~KRReverbZone()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRReverbZone::getElementName() {
|
||||
return "reverb_zone";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRReverbZone::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("zone", m_zone.c_str());
|
||||
e->SetAttribute("sample", m_reverb.c_str());
|
||||
e->SetAttribute("gain", m_reverb_gain);
|
||||
e->SetAttribute("gradient", m_gradient_distance);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRReverbZone::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRNode::loadXML(e);
|
||||
|
||||
m_zone = e->Attribute("zone");
|
||||
|
||||
m_gradient_distance = 0.25f;
|
||||
if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
|
||||
m_gradient_distance = 0.25f;
|
||||
}
|
||||
|
||||
m_reverb = e->Attribute("sample");
|
||||
|
||||
m_reverb_gain = 1.0f;
|
||||
if(e->QueryFloatAttribute("gain", &m_reverb_gain) != tinyxml2::XML_SUCCESS) {
|
||||
m_reverb_gain = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
std::string KRReverbZone::getReverb()
|
||||
{
|
||||
return m_reverb;
|
||||
}
|
||||
|
||||
void KRReverbZone::setReverb(const std::string &reverb)
|
||||
{
|
||||
m_reverb = reverb;
|
||||
}
|
||||
|
||||
float KRReverbZone::getReverbGain()
|
||||
{
|
||||
return m_reverb_gain;
|
||||
}
|
||||
|
||||
void KRReverbZone::setReverbGain(float reverb_gain)
|
||||
{
|
||||
m_reverb_gain = reverb_gain;
|
||||
}
|
||||
|
||||
std::string KRReverbZone::getZone()
|
||||
{
|
||||
return m_zone;
|
||||
}
|
||||
|
||||
void KRReverbZone::setZone(const std::string &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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_REVERB_ZONES;
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
||||
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);
|
||||
|
||||
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
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
||||
if(sphereModels.size()) {
|
||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float KRReverbZone::getGradientDistance()
|
||||
{
|
||||
return m_gradient_distance;
|
||||
}
|
||||
|
||||
void KRReverbZone::setGradientDistance(float gradient_distance)
|
||||
{
|
||||
m_gradient_distance = gradient_distance;
|
||||
}
|
||||
|
||||
AABB KRReverbZone::getBounds() {
|
||||
// Reverb zones always have a -1, -1, -1 to 1, 1, 1 bounding box
|
||||
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
|
||||
}
|
||||
|
||||
float KRReverbZone::getContainment(const Vector3 &pos)
|
||||
{
|
||||
AABB bounds = getBounds();
|
||||
if(bounds.contains(pos)) {
|
||||
Vector3 size = bounds.size();
|
||||
Vector3 diff = pos - bounds.center();
|
||||
diff = diff * 2.0f;
|
||||
diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z);
|
||||
float d = diff.magnitude();
|
||||
|
||||
if(m_gradient_distance <= 0.0f) {
|
||||
// Avoid division by zero
|
||||
d = d > 1.0f ? 0.0f : 1.0f;
|
||||
} else {
|
||||
d = (1.0f - d) / m_gradient_distance;
|
||||
d = KRCLAMP(d, 0.0f, 1.0f);
|
||||
}
|
||||
return d;
|
||||
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
1216
kraken/KRScene.cpp
1216
kraken/KRScene.cpp
File diff suppressed because it is too large
Load Diff
1192
kraken/KRShader.cpp
1192
kraken/KRShader.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,61 +1,61 @@
|
||||
//
|
||||
// KRSpotLight.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRSpotLight.h"
|
||||
|
||||
KRSpotLight::KRSpotLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
||||
{
|
||||
}
|
||||
|
||||
KRSpotLight::~KRSpotLight()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string KRSpotLight::getElementName() {
|
||||
return "spot_light";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRSpotLight::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRLight::saveXML(parent);
|
||||
e->SetAttribute("inner_angle", m_innerAngle);
|
||||
e->SetAttribute("outer_angle", m_outerAngle);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRSpotLight::loadXML(tinyxml2::XMLElement *e) {
|
||||
KRLight::loadXML(e);
|
||||
|
||||
e->QueryFloatAttribute("inner_angle", &m_innerAngle);
|
||||
e->QueryFloatAttribute("outer_angle", &m_outerAngle);
|
||||
}
|
||||
|
||||
float KRSpotLight::getInnerAngle() {
|
||||
return m_innerAngle;
|
||||
}
|
||||
float KRSpotLight::getOuterAngle() {
|
||||
return m_outerAngle;
|
||||
}
|
||||
void KRSpotLight::setInnerAngle(float innerAngle) {
|
||||
m_innerAngle = innerAngle;
|
||||
}
|
||||
void KRSpotLight::setOuterAngle(float outerAngle) {
|
||||
m_outerAngle = outerAngle;
|
||||
}
|
||||
|
||||
AABB KRSpotLight::getBounds() {
|
||||
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
||||
if(influence_radius < m_flareOcclusionSize) {
|
||||
influence_radius = m_flareOcclusionSize;
|
||||
}
|
||||
return AABB::Create(Vector3::Create(-influence_radius), Vector3::Create(influence_radius), getModelMatrix());
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// KRSpotLight.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRSpotLight.h"
|
||||
|
||||
KRSpotLight::KRSpotLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
||||
{
|
||||
}
|
||||
|
||||
KRSpotLight::~KRSpotLight()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string KRSpotLight::getElementName() {
|
||||
return "spot_light";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRSpotLight::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRLight::saveXML(parent);
|
||||
e->SetAttribute("inner_angle", m_innerAngle);
|
||||
e->SetAttribute("outer_angle", m_outerAngle);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRSpotLight::loadXML(tinyxml2::XMLElement *e) {
|
||||
KRLight::loadXML(e);
|
||||
|
||||
e->QueryFloatAttribute("inner_angle", &m_innerAngle);
|
||||
e->QueryFloatAttribute("outer_angle", &m_outerAngle);
|
||||
}
|
||||
|
||||
float KRSpotLight::getInnerAngle() {
|
||||
return m_innerAngle;
|
||||
}
|
||||
float KRSpotLight::getOuterAngle() {
|
||||
return m_outerAngle;
|
||||
}
|
||||
void KRSpotLight::setInnerAngle(float innerAngle) {
|
||||
m_innerAngle = innerAngle;
|
||||
}
|
||||
void KRSpotLight::setOuterAngle(float outerAngle) {
|
||||
m_outerAngle = outerAngle;
|
||||
}
|
||||
|
||||
AABB KRSpotLight::getBounds() {
|
||||
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
||||
if(influence_radius < m_flareOcclusionSize) {
|
||||
influence_radius = m_flareOcclusionSize;
|
||||
}
|
||||
return AABB::Create(Vector3::Create(-influence_radius), Vector3::Create(influence_radius), getModelMatrix());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,141 +1,141 @@
|
||||
//
|
||||
// KRSprite.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRSprite.h"
|
||||
|
||||
#include "KRNode.h"
|
||||
#include "KRCamera.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
#include "KRShaderManager.h"
|
||||
#include "KRShader.h"
|
||||
#include "KRStockGeometry.h"
|
||||
#include "KRDirectionalLight.h"
|
||||
#include "KRSpotLight.h"
|
||||
#include "KRPointLight.h"
|
||||
|
||||
|
||||
KRSprite::KRSprite(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_spriteTexture = "";
|
||||
m_pSpriteTexture = NULL;
|
||||
m_spriteAlpha = 1.0f;
|
||||
}
|
||||
|
||||
KRSprite::~KRSprite()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRSprite::getElementName() {
|
||||
return "sprite";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRSprite::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("sprite_texture", m_spriteTexture.c_str());
|
||||
e->SetAttribute("sprite_alpha", m_spriteAlpha);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRSprite::loadXML(tinyxml2::XMLElement *e) {
|
||||
KRNode::loadXML(e);
|
||||
|
||||
if(e->QueryFloatAttribute("sprite_alpha", &m_spriteAlpha) != tinyxml2::XML_SUCCESS) {
|
||||
m_spriteAlpha = 1.0f;
|
||||
}
|
||||
|
||||
const char *szSpriteTexture = e->Attribute("sprite_texture");
|
||||
if(szSpriteTexture) {
|
||||
m_spriteTexture = szSpriteTexture;
|
||||
} else {
|
||||
m_spriteTexture = "";
|
||||
}
|
||||
m_pSpriteTexture = NULL;
|
||||
}
|
||||
|
||||
void KRSprite::setSpriteTexture(std::string sprite_texture) {
|
||||
m_spriteTexture = sprite_texture;
|
||||
m_pSpriteTexture = NULL;
|
||||
}
|
||||
|
||||
void KRSprite::setSpriteAlpha(float alpha)
|
||||
{
|
||||
m_spriteAlpha = alpha;
|
||||
}
|
||||
|
||||
float KRSprite::getSpriteAlpha() const
|
||||
{
|
||||
return m_spriteAlpha;
|
||||
}
|
||||
|
||||
AABB KRSprite::getBounds() {
|
||||
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) {
|
||||
|
||||
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) {
|
||||
// Pre-stream sprites, even if the alpha is zero
|
||||
if(m_spriteTexture.size() && m_pSpriteTexture == NULL) {
|
||||
if(!m_pSpriteTexture && m_spriteTexture.size()) {
|
||||
m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture);
|
||||
}
|
||||
}
|
||||
|
||||
if(m_pSpriteTexture) {
|
||||
m_pSpriteTexture->resetPoolExpiry(0.0f, KRTexture::TEXTURE_USAGE_SPRITE);
|
||||
}
|
||||
}
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
|
||||
if(m_spriteTexture.size() && m_spriteAlpha > 0.0f) {
|
||||
|
||||
|
||||
if(!m_pSpriteTexture && m_spriteTexture.size()) {
|
||||
m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture);
|
||||
}
|
||||
|
||||
if(m_pSpriteTexture) {
|
||||
/*
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
*/
|
||||
|
||||
// TODO - Sprites are currently additive only. Need to expose this and allow for multiple blending modes
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
// 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);
|
||||
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);
|
||||
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);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
//
|
||||
// KRSprite.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRSprite.h"
|
||||
|
||||
#include "KRNode.h"
|
||||
#include "KRCamera.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
#include "KRShaderManager.h"
|
||||
#include "KRShader.h"
|
||||
#include "KRStockGeometry.h"
|
||||
#include "KRDirectionalLight.h"
|
||||
#include "KRSpotLight.h"
|
||||
#include "KRPointLight.h"
|
||||
|
||||
|
||||
KRSprite::KRSprite(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_spriteTexture = "";
|
||||
m_pSpriteTexture = NULL;
|
||||
m_spriteAlpha = 1.0f;
|
||||
}
|
||||
|
||||
KRSprite::~KRSprite()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRSprite::getElementName() {
|
||||
return "sprite";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRSprite::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("sprite_texture", m_spriteTexture.c_str());
|
||||
e->SetAttribute("sprite_alpha", m_spriteAlpha);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRSprite::loadXML(tinyxml2::XMLElement *e) {
|
||||
KRNode::loadXML(e);
|
||||
|
||||
if(e->QueryFloatAttribute("sprite_alpha", &m_spriteAlpha) != tinyxml2::XML_SUCCESS) {
|
||||
m_spriteAlpha = 1.0f;
|
||||
}
|
||||
|
||||
const char *szSpriteTexture = e->Attribute("sprite_texture");
|
||||
if(szSpriteTexture) {
|
||||
m_spriteTexture = szSpriteTexture;
|
||||
} else {
|
||||
m_spriteTexture = "";
|
||||
}
|
||||
m_pSpriteTexture = NULL;
|
||||
}
|
||||
|
||||
void KRSprite::setSpriteTexture(std::string sprite_texture) {
|
||||
m_spriteTexture = sprite_texture;
|
||||
m_pSpriteTexture = NULL;
|
||||
}
|
||||
|
||||
void KRSprite::setSpriteAlpha(float alpha)
|
||||
{
|
||||
m_spriteAlpha = alpha;
|
||||
}
|
||||
|
||||
float KRSprite::getSpriteAlpha() const
|
||||
{
|
||||
return m_spriteAlpha;
|
||||
}
|
||||
|
||||
AABB KRSprite::getBounds() {
|
||||
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) {
|
||||
|
||||
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) {
|
||||
// Pre-stream sprites, even if the alpha is zero
|
||||
if(m_spriteTexture.size() && m_pSpriteTexture == NULL) {
|
||||
if(!m_pSpriteTexture && m_spriteTexture.size()) {
|
||||
m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture);
|
||||
}
|
||||
}
|
||||
|
||||
if(m_pSpriteTexture) {
|
||||
m_pSpriteTexture->resetPoolExpiry(0.0f, KRTexture::TEXTURE_USAGE_SPRITE);
|
||||
}
|
||||
}
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
|
||||
if(m_spriteTexture.size() && m_spriteAlpha > 0.0f) {
|
||||
|
||||
|
||||
if(!m_pSpriteTexture && m_spriteTexture.size()) {
|
||||
m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture);
|
||||
}
|
||||
|
||||
if(m_pSpriteTexture) {
|
||||
/*
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
*/
|
||||
|
||||
// TODO - Sprites are currently additive only. Need to expose this and allow for multiple blending modes
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
// 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);
|
||||
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);
|
||||
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);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,62 +1,62 @@
|
||||
//
|
||||
// KRStreamer.cpp
|
||||
// Kraken
|
||||
//
|
||||
// Created by Kearwood Gilbert on 11/1/2013.
|
||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRStreamer.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
|
||||
KRStreamer::KRStreamer(KRContext &context) : m_context(context)
|
||||
{
|
||||
m_running = false;
|
||||
m_stop = false;
|
||||
}
|
||||
|
||||
void KRStreamer::startStreamer()
|
||||
{
|
||||
if(!m_running) {
|
||||
m_running = true;
|
||||
KRContext::activateStreamerContext();
|
||||
|
||||
m_thread = std::thread(&KRStreamer::run, this);
|
||||
}
|
||||
}
|
||||
|
||||
KRStreamer::~KRStreamer()
|
||||
{
|
||||
if(m_running) {
|
||||
m_stop = true;
|
||||
m_thread.join();
|
||||
m_running = false;
|
||||
}
|
||||
}
|
||||
|
||||
void KRStreamer::run()
|
||||
{
|
||||
|
||||
#if defined(ANDROID)
|
||||
// TODO - Set thread names on Android
|
||||
#elif defined(_WIN32) || defined(_WIN64)
|
||||
// TODO - Set thread names on windows
|
||||
#else
|
||||
pthread_setname_np("Kraken - Streamer");
|
||||
#endif
|
||||
|
||||
std::chrono::microseconds sleep_duration( 15000 );
|
||||
|
||||
KRContext::activateStreamerContext();
|
||||
|
||||
while(!m_stop)
|
||||
{
|
||||
m_context.doStreaming();
|
||||
std::this_thread::sleep_for( sleep_duration );
|
||||
}
|
||||
}
|
||||
//
|
||||
// KRStreamer.cpp
|
||||
// Kraken
|
||||
//
|
||||
// Created by Kearwood Gilbert on 11/1/2013.
|
||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRStreamer.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
|
||||
KRStreamer::KRStreamer(KRContext &context) : m_context(context)
|
||||
{
|
||||
m_running = false;
|
||||
m_stop = false;
|
||||
}
|
||||
|
||||
void KRStreamer::startStreamer()
|
||||
{
|
||||
if(!m_running) {
|
||||
m_running = true;
|
||||
KRContext::activateStreamerContext();
|
||||
|
||||
m_thread = std::thread(&KRStreamer::run, this);
|
||||
}
|
||||
}
|
||||
|
||||
KRStreamer::~KRStreamer()
|
||||
{
|
||||
if(m_running) {
|
||||
m_stop = true;
|
||||
m_thread.join();
|
||||
m_running = false;
|
||||
}
|
||||
}
|
||||
|
||||
void KRStreamer::run()
|
||||
{
|
||||
|
||||
#if defined(ANDROID)
|
||||
// TODO - Set thread names on Android
|
||||
#elif defined(_WIN32) || defined(_WIN64)
|
||||
// TODO - Set thread names on windows
|
||||
#else
|
||||
pthread_setname_np("Kraken - Streamer");
|
||||
#endif
|
||||
|
||||
std::chrono::microseconds sleep_duration( 15000 );
|
||||
|
||||
KRContext::activateStreamerContext();
|
||||
|
||||
while(!m_stop)
|
||||
{
|
||||
m_context.doStreaming();
|
||||
std::this_thread::sleep_for( sleep_duration );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,399 +1,399 @@
|
||||
//
|
||||
// KRTextureTGA.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-10-23.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRTextureTGA.h"
|
||||
#include "KREngine-common.h"
|
||||
#include "KRContext.h"
|
||||
#include "KRTextureKTX.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
char idlength;
|
||||
char colourmaptype;
|
||||
char imagetype;
|
||||
short int colourmaporigin;
|
||||
short int colourmaplength;
|
||||
char colourmapdepth;
|
||||
short int x_origin;
|
||||
short int y_origin;
|
||||
short width;
|
||||
short height;
|
||||
char bitsperpixel;
|
||||
char imagedescriptor;
|
||||
} TGA_HEADER;
|
||||
#pragma pack()
|
||||
#else
|
||||
typedef struct {
|
||||
char idlength;
|
||||
char colourmaptype;
|
||||
char imagetype;
|
||||
short int colourmaporigin;
|
||||
short int colourmaplength;
|
||||
char colourmapdepth;
|
||||
short int x_origin;
|
||||
short int y_origin;
|
||||
short width;
|
||||
short height;
|
||||
char bitsperpixel;
|
||||
char imagedescriptor;
|
||||
} __attribute__((packed)) TGA_HEADER;
|
||||
#endif
|
||||
|
||||
|
||||
KRTextureTGA::KRTextureTGA(KRContext &context, KRDataBlock *data, std::string name) : KRTexture2D(context, data, name)
|
||||
{
|
||||
data->lock();
|
||||
TGA_HEADER *pHeader = (TGA_HEADER *)data->getStart();
|
||||
|
||||
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
|
||||
switch(pHeader->imagetype) {
|
||||
case 2: // rgb
|
||||
case 10: // rgb + rle
|
||||
switch(pHeader->bitsperpixel) {
|
||||
case 24:
|
||||
{
|
||||
m_imageSize = pHeader->width * pHeader->height * 4;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
{
|
||||
m_imageSize = pHeader->width * pHeader->height * 4;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data->unlock();
|
||||
}
|
||||
|
||||
KRTextureTGA::~KRTextureTGA()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, bool compress, bool premultiply_alpha)
|
||||
{
|
||||
m_pData->lock();
|
||||
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);
|
||||
|
||||
GLenum internal_format = GL_RGBA;
|
||||
|
||||
#if !TARGET_OS_IPHONE && !defined(ANDROID)
|
||||
if(compress) {
|
||||
internal_format = pHeader->bitsperpixel == 24 ? GL_COMPRESSED_RGB_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(pHeader->colourmaptype != 0) {
|
||||
m_pData->unlock();
|
||||
return false; // Mapped colors not supported
|
||||
}
|
||||
|
||||
switch(pHeader->imagetype) {
|
||||
case 2: // rgb
|
||||
switch(pHeader->bitsperpixel) {
|
||||
case 24:
|
||||
{
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
//#ifdef __APPLE__
|
||||
// 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 };
|
||||
// vImageConvert_RGB888toRGBA8888(&source_image, NULL, 0xff, &dest_image, false, kvImageDoNotTile);
|
||||
//#else
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
|
||||
while(pSource < pEnd) {
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = 0xff;
|
||||
pSource += 3;
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
//#endif
|
||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
||||
GLDEBUG(glFinish());
|
||||
free(converted_image);
|
||||
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
{
|
||||
if(premultiply_alpha) {
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
|
||||
while(pSource < pEnd) {
|
||||
*pDest++ = (__uint32_t)pSource[2] * (__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++ = pSource[3];
|
||||
pSource += 4;
|
||||
}
|
||||
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(glFinish());
|
||||
free(converted_image);
|
||||
} else {
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
|
||||
while(pSource < pEnd) {
|
||||
*pDest++ = (__uint32_t)pSource[2];
|
||||
*pDest++ = (__uint32_t)pSource[1];
|
||||
*pDest++ = (__uint32_t)pSource[0];
|
||||
*pDest++ = pSource[3];
|
||||
pSource += 4;
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)pData));
|
||||
GLDEBUG(glFinish());
|
||||
free(converted_image);
|
||||
}
|
||||
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_pData->unlock();
|
||||
return false; // 16-bit images not yet supported
|
||||
}
|
||||
break;
|
||||
case 10: // rgb + rle
|
||||
switch(pHeader->bitsperpixel) {
|
||||
case 32:
|
||||
{
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4;
|
||||
if(premultiply_alpha) {
|
||||
while(pDest < pEnd) {
|
||||
int count = (*pSource & 0x7f) + 1;
|
||||
if(*pSource & 0x80) {
|
||||
// RLE Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = (__uint32_t)pSource[2] * (__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++ = pSource[3];
|
||||
}
|
||||
pSource += 4;
|
||||
} else {
|
||||
// RAW Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = (__uint32_t)pSource[2] * (__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++ = pSource[3];
|
||||
pSource += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
assert(pDest == pEnd);
|
||||
} else {
|
||||
while(pDest < pEnd) {
|
||||
int count = (*pSource & 0x7f) + 1;
|
||||
if(*pSource & 0x80) {
|
||||
// RLE Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = pSource[3];
|
||||
}
|
||||
pSource += 4;
|
||||
} else {
|
||||
// RAW Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = pSource[3];
|
||||
pSource += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
assert(pDest == pEnd);
|
||||
}
|
||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
||||
GLDEBUG(glFinish());
|
||||
free(converted_image);
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
{
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4;
|
||||
while(pDest < pEnd) {
|
||||
int count = (*pSource & 0x7f) + 1;
|
||||
if(*pSource & 0x80) {
|
||||
// RLE Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = 0xff;
|
||||
}
|
||||
pSource += 3;
|
||||
} else {
|
||||
// RAW Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = 0xff;
|
||||
pSource += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
assert(pDest == pEnd);
|
||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
||||
GLDEBUG(glFinish());
|
||||
free(converted_image);
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_pData->unlock();
|
||||
return false; // 16-bit images not yet supported
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_pData->unlock();
|
||||
return false; // Image type not yet supported
|
||||
}
|
||||
|
||||
m_pData->unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !TARGET_OS_IPHONE && !defined(ANDROID)
|
||||
|
||||
KRTexture *KRTextureTGA::compress(bool premultiply_alpha)
|
||||
{
|
||||
m_pData->lock();
|
||||
|
||||
std::list<KRDataBlock *> blocks;
|
||||
|
||||
getContext().getTextureManager()->_setActiveTexture(0);
|
||||
|
||||
GLuint compressed_handle = 0;
|
||||
GLDEBUG(glGenTextures(1, &compressed_handle));
|
||||
|
||||
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compressed_handle));
|
||||
|
||||
int current_max_dim = 0;
|
||||
if(!uploadTexture(GL_TEXTURE_2D, m_max_lod_max_dim, current_max_dim, true, premultiply_alpha)) {
|
||||
assert(false); // Failed to upload the texture
|
||||
}
|
||||
GLDEBUG(glGenerateMipmap(GL_TEXTURE_2D));
|
||||
|
||||
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_HEIGHT, &height));
|
||||
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format));
|
||||
|
||||
/*
|
||||
int texture_base_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_MAX_LOD, &texture_max_level));
|
||||
*/
|
||||
switch(internal_format)
|
||||
{
|
||||
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
base_internal_format = GL_BGRA;
|
||||
break;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
base_internal_format = GL_BGRA;
|
||||
break;
|
||||
default:
|
||||
assert(false); // Not yet supported
|
||||
break;
|
||||
}
|
||||
|
||||
GLuint lod_level = 0;
|
||||
GLint compressed_size = 0;
|
||||
int lod_width = width;
|
||||
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_COMPRESSED_IMAGE_SIZE, &compressed_size));
|
||||
KRDataBlock *new_block = new KRDataBlock();
|
||||
new_block->expand(compressed_size);
|
||||
new_block->lock();
|
||||
GLDEBUG(glGetCompressedTexImage(GL_TEXTURE_2D, lod_level, new_block->getStart()));
|
||||
new_block->unlock();
|
||||
blocks.push_back(new_block);
|
||||
|
||||
lod_level++;
|
||||
}
|
||||
assert(lod_width == 1);
|
||||
|
||||
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
|
||||
getContext().getTextureManager()->selectTexture(0, NULL, 0.0f, KRTexture::TEXTURE_USAGE_NONE);
|
||||
GLDEBUG(glDeleteTextures(1, &compressed_handle));
|
||||
|
||||
KRTextureKTX *new_texture = new KRTextureKTX(getContext(), getName(), internal_format, base_internal_format, width, height, blocks);
|
||||
|
||||
m_pData->unlock();
|
||||
|
||||
for(auto block_itr = blocks.begin(); block_itr != blocks.end(); block_itr++) {
|
||||
KRDataBlock *block = *block_itr;
|
||||
delete block;
|
||||
}
|
||||
|
||||
return new_texture;
|
||||
}
|
||||
#endif
|
||||
|
||||
long KRTextureTGA::getMemRequiredForSize(int max_dim)
|
||||
{
|
||||
return m_imageSize;
|
||||
}
|
||||
|
||||
std::string KRTextureTGA::getExtension()
|
||||
{
|
||||
return "tga";
|
||||
}
|
||||
//
|
||||
// KRTextureTGA.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-10-23.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRTextureTGA.h"
|
||||
#include "KREngine-common.h"
|
||||
#include "KRContext.h"
|
||||
#include "KRTextureKTX.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
char idlength;
|
||||
char colourmaptype;
|
||||
char imagetype;
|
||||
short int colourmaporigin;
|
||||
short int colourmaplength;
|
||||
char colourmapdepth;
|
||||
short int x_origin;
|
||||
short int y_origin;
|
||||
short width;
|
||||
short height;
|
||||
char bitsperpixel;
|
||||
char imagedescriptor;
|
||||
} TGA_HEADER;
|
||||
#pragma pack()
|
||||
#else
|
||||
typedef struct {
|
||||
char idlength;
|
||||
char colourmaptype;
|
||||
char imagetype;
|
||||
short int colourmaporigin;
|
||||
short int colourmaplength;
|
||||
char colourmapdepth;
|
||||
short int x_origin;
|
||||
short int y_origin;
|
||||
short width;
|
||||
short height;
|
||||
char bitsperpixel;
|
||||
char imagedescriptor;
|
||||
} __attribute__((packed)) TGA_HEADER;
|
||||
#endif
|
||||
|
||||
|
||||
KRTextureTGA::KRTextureTGA(KRContext &context, KRDataBlock *data, std::string name) : KRTexture2D(context, data, name)
|
||||
{
|
||||
data->lock();
|
||||
TGA_HEADER *pHeader = (TGA_HEADER *)data->getStart();
|
||||
|
||||
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
|
||||
switch(pHeader->imagetype) {
|
||||
case 2: // rgb
|
||||
case 10: // rgb + rle
|
||||
switch(pHeader->bitsperpixel) {
|
||||
case 24:
|
||||
{
|
||||
m_imageSize = pHeader->width * pHeader->height * 4;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
{
|
||||
m_imageSize = pHeader->width * pHeader->height * 4;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data->unlock();
|
||||
}
|
||||
|
||||
KRTextureTGA::~KRTextureTGA()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, bool compress, bool premultiply_alpha)
|
||||
{
|
||||
m_pData->lock();
|
||||
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);
|
||||
|
||||
GLenum internal_format = GL_RGBA;
|
||||
|
||||
#if !TARGET_OS_IPHONE && !defined(ANDROID)
|
||||
if(compress) {
|
||||
internal_format = pHeader->bitsperpixel == 24 ? GL_COMPRESSED_RGB_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(pHeader->colourmaptype != 0) {
|
||||
m_pData->unlock();
|
||||
return false; // Mapped colors not supported
|
||||
}
|
||||
|
||||
switch(pHeader->imagetype) {
|
||||
case 2: // rgb
|
||||
switch(pHeader->bitsperpixel) {
|
||||
case 24:
|
||||
{
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
//#ifdef __APPLE__
|
||||
// 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 };
|
||||
// vImageConvert_RGB888toRGBA8888(&source_image, NULL, 0xff, &dest_image, false, kvImageDoNotTile);
|
||||
//#else
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
|
||||
while(pSource < pEnd) {
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = 0xff;
|
||||
pSource += 3;
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
//#endif
|
||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
||||
GLDEBUG(glFinish());
|
||||
free(converted_image);
|
||||
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
{
|
||||
if(premultiply_alpha) {
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
|
||||
while(pSource < pEnd) {
|
||||
*pDest++ = (__uint32_t)pSource[2] * (__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++ = pSource[3];
|
||||
pSource += 4;
|
||||
}
|
||||
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(glFinish());
|
||||
free(converted_image);
|
||||
} else {
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
|
||||
while(pSource < pEnd) {
|
||||
*pDest++ = (__uint32_t)pSource[2];
|
||||
*pDest++ = (__uint32_t)pSource[1];
|
||||
*pDest++ = (__uint32_t)pSource[0];
|
||||
*pDest++ = pSource[3];
|
||||
pSource += 4;
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)pData));
|
||||
GLDEBUG(glFinish());
|
||||
free(converted_image);
|
||||
}
|
||||
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_pData->unlock();
|
||||
return false; // 16-bit images not yet supported
|
||||
}
|
||||
break;
|
||||
case 10: // rgb + rle
|
||||
switch(pHeader->bitsperpixel) {
|
||||
case 32:
|
||||
{
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4;
|
||||
if(premultiply_alpha) {
|
||||
while(pDest < pEnd) {
|
||||
int count = (*pSource & 0x7f) + 1;
|
||||
if(*pSource & 0x80) {
|
||||
// RLE Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = (__uint32_t)pSource[2] * (__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++ = pSource[3];
|
||||
}
|
||||
pSource += 4;
|
||||
} else {
|
||||
// RAW Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = (__uint32_t)pSource[2] * (__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++ = pSource[3];
|
||||
pSource += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
assert(pDest == pEnd);
|
||||
} else {
|
||||
while(pDest < pEnd) {
|
||||
int count = (*pSource & 0x7f) + 1;
|
||||
if(*pSource & 0x80) {
|
||||
// RLE Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = pSource[3];
|
||||
}
|
||||
pSource += 4;
|
||||
} else {
|
||||
// RAW Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = pSource[3];
|
||||
pSource += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
assert(pDest == pEnd);
|
||||
}
|
||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
||||
GLDEBUG(glFinish());
|
||||
free(converted_image);
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
{
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4;
|
||||
while(pDest < pEnd) {
|
||||
int count = (*pSource & 0x7f) + 1;
|
||||
if(*pSource & 0x80) {
|
||||
// RLE Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = 0xff;
|
||||
}
|
||||
pSource += 3;
|
||||
} else {
|
||||
// RAW Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = 0xff;
|
||||
pSource += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
assert(pDest == pEnd);
|
||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
||||
GLDEBUG(glFinish());
|
||||
free(converted_image);
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_pData->unlock();
|
||||
return false; // 16-bit images not yet supported
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_pData->unlock();
|
||||
return false; // Image type not yet supported
|
||||
}
|
||||
|
||||
m_pData->unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !TARGET_OS_IPHONE && !defined(ANDROID)
|
||||
|
||||
KRTexture *KRTextureTGA::compress(bool premultiply_alpha)
|
||||
{
|
||||
m_pData->lock();
|
||||
|
||||
std::list<KRDataBlock *> blocks;
|
||||
|
||||
getContext().getTextureManager()->_setActiveTexture(0);
|
||||
|
||||
GLuint compressed_handle = 0;
|
||||
GLDEBUG(glGenTextures(1, &compressed_handle));
|
||||
|
||||
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compressed_handle));
|
||||
|
||||
int current_max_dim = 0;
|
||||
if(!uploadTexture(GL_TEXTURE_2D, m_max_lod_max_dim, current_max_dim, true, premultiply_alpha)) {
|
||||
assert(false); // Failed to upload the texture
|
||||
}
|
||||
GLDEBUG(glGenerateMipmap(GL_TEXTURE_2D));
|
||||
|
||||
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_HEIGHT, &height));
|
||||
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format));
|
||||
|
||||
/*
|
||||
int texture_base_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_MAX_LOD, &texture_max_level));
|
||||
*/
|
||||
switch(internal_format)
|
||||
{
|
||||
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
base_internal_format = GL_BGRA;
|
||||
break;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
base_internal_format = GL_BGRA;
|
||||
break;
|
||||
default:
|
||||
assert(false); // Not yet supported
|
||||
break;
|
||||
}
|
||||
|
||||
GLuint lod_level = 0;
|
||||
GLint compressed_size = 0;
|
||||
int lod_width = width;
|
||||
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_COMPRESSED_IMAGE_SIZE, &compressed_size));
|
||||
KRDataBlock *new_block = new KRDataBlock();
|
||||
new_block->expand(compressed_size);
|
||||
new_block->lock();
|
||||
GLDEBUG(glGetCompressedTexImage(GL_TEXTURE_2D, lod_level, new_block->getStart()));
|
||||
new_block->unlock();
|
||||
blocks.push_back(new_block);
|
||||
|
||||
lod_level++;
|
||||
}
|
||||
assert(lod_width == 1);
|
||||
|
||||
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
|
||||
getContext().getTextureManager()->selectTexture(0, NULL, 0.0f, KRTexture::TEXTURE_USAGE_NONE);
|
||||
GLDEBUG(glDeleteTextures(1, &compressed_handle));
|
||||
|
||||
KRTextureKTX *new_texture = new KRTextureKTX(getContext(), getName(), internal_format, base_internal_format, width, height, blocks);
|
||||
|
||||
m_pData->unlock();
|
||||
|
||||
for(auto block_itr = blocks.begin(); block_itr != blocks.end(); block_itr++) {
|
||||
KRDataBlock *block = *block_itr;
|
||||
delete block;
|
||||
}
|
||||
|
||||
return new_texture;
|
||||
}
|
||||
#endif
|
||||
|
||||
long KRTextureTGA::getMemRequiredForSize(int max_dim)
|
||||
{
|
||||
return m_imageSize;
|
||||
}
|
||||
|
||||
std::string KRTextureTGA::getExtension()
|
||||
{
|
||||
return "tga";
|
||||
}
|
||||
|
||||
@@ -1,264 +1,264 @@
|
||||
//
|
||||
// KRViewport.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-10-25.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#define KRENGINE_SWAP_INT(x,y) {int t;t=x;x=y;y=t;}
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRViewport.h"
|
||||
|
||||
KRViewport::KRViewport()
|
||||
{
|
||||
m_size = Vector2::One();
|
||||
m_matProjection = Matrix4();
|
||||
m_matView = Matrix4();
|
||||
m_lodBias = 0.0f;
|
||||
calculateDerivedValues();
|
||||
}
|
||||
|
||||
KRViewport::KRViewport(const Vector2 &size, const Matrix4 &matView, const Matrix4 &matProjection)
|
||||
{
|
||||
m_size = size;
|
||||
m_matView = matView;
|
||||
m_matProjection = matProjection;
|
||||
calculateDerivedValues();
|
||||
}
|
||||
|
||||
|
||||
KRViewport& KRViewport::operator=(const KRViewport &v) {
|
||||
if(this != &v) { // Prevent self-assignment.
|
||||
m_size = v.m_size;
|
||||
m_matProjection = v.m_matProjection;
|
||||
m_matView = v.m_matView;
|
||||
m_lodBias = v.m_lodBias;
|
||||
|
||||
calculateDerivedValues();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
KRViewport::~KRViewport()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const Vector2 &KRViewport::getSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
const Matrix4 &KRViewport::getViewMatrix() const
|
||||
{
|
||||
return m_matView;
|
||||
}
|
||||
|
||||
const Matrix4 &KRViewport::getProjectionMatrix() const
|
||||
{
|
||||
return m_matProjection;
|
||||
}
|
||||
|
||||
void KRViewport::setSize(const Vector2 &size)
|
||||
{
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
void KRViewport::setViewMatrix(const Matrix4 &matView)
|
||||
{
|
||||
m_matView = matView;
|
||||
calculateDerivedValues();
|
||||
}
|
||||
|
||||
void KRViewport::setProjectionMatrix(const Matrix4 &matProjection)
|
||||
{
|
||||
m_matProjection = matProjection;
|
||||
calculateDerivedValues();
|
||||
}
|
||||
|
||||
const Matrix4 &KRViewport::KRViewport::getViewProjectionMatrix() const
|
||||
{
|
||||
return m_matViewProjection;
|
||||
}
|
||||
|
||||
const Matrix4 &KRViewport::getInverseViewMatrix() const
|
||||
{
|
||||
return m_matInverseView;
|
||||
}
|
||||
|
||||
const Matrix4 &KRViewport::getInverseProjectionMatrix() const
|
||||
{
|
||||
return m_matInverseProjection;
|
||||
}
|
||||
|
||||
const Vector3 &KRViewport::getCameraDirection() const
|
||||
{
|
||||
return m_cameraDirection;
|
||||
}
|
||||
|
||||
const Vector3 &KRViewport::getCameraPosition() const
|
||||
{
|
||||
return m_cameraPosition;
|
||||
}
|
||||
|
||||
const int *KRViewport::getFrontToBackOrder() const
|
||||
{
|
||||
return &m_frontToBackOrder[0];
|
||||
}
|
||||
|
||||
const int *KRViewport::getBackToFrontOrder() const
|
||||
{
|
||||
return &m_backToFrontOrder[0];
|
||||
}
|
||||
|
||||
void KRViewport::calculateDerivedValues()
|
||||
{
|
||||
m_matViewProjection = m_matView * m_matProjection;
|
||||
m_matInverseView = Matrix4::Invert(m_matView);
|
||||
m_matInverseProjection = Matrix4::Invert(m_matProjection);
|
||||
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));
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
m_frontToBackOrder[i] = i;
|
||||
}
|
||||
|
||||
if(m_cameraDirection.x > 0.0) {
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[1]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[2], m_frontToBackOrder[3]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[4], m_frontToBackOrder[5]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[6], m_frontToBackOrder[7]);
|
||||
}
|
||||
|
||||
if(m_cameraDirection.y > 0.0) {
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[2]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[1], m_frontToBackOrder[3]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[4], m_frontToBackOrder[6]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[5], m_frontToBackOrder[7]);
|
||||
}
|
||||
|
||||
if(m_cameraDirection.z > 0.0) {
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[4]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[1], m_frontToBackOrder[5]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[2], m_frontToBackOrder[6]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[3], m_frontToBackOrder[7]);
|
||||
}
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
m_backToFrontOrder[i] = m_frontToBackOrder[7-i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unordered_map<AABB, int> &KRViewport::getVisibleBounds()
|
||||
{
|
||||
return m_visibleBounds;
|
||||
}
|
||||
|
||||
float KRViewport::getLODBias() const
|
||||
{
|
||||
return m_lodBias;
|
||||
}
|
||||
|
||||
void KRViewport::setLODBias(float lod_bias)
|
||||
{
|
||||
m_lodBias = lod_bias;
|
||||
}
|
||||
|
||||
float KRViewport::coverage(const AABB &b) const
|
||||
{
|
||||
if(!visible(b)) {
|
||||
return 0.0f; // Culled out by view frustrum
|
||||
} else {
|
||||
Vector3 nearest_point = b.nearestPoint(getCameraPosition());
|
||||
float distance = (nearest_point - getCameraPosition()).magnitude();
|
||||
|
||||
Vector3 v = Matrix4::DotWDiv(m_matProjection, getCameraPosition() + getCameraDirection() * distance);
|
||||
|
||||
float screen_depth = distance / 1000.0f;
|
||||
|
||||
return KRCLAMP(1.0f - screen_depth, 0.01f, 1.0f);
|
||||
|
||||
/*
|
||||
|
||||
Vector2 screen_min;
|
||||
Vector2 screen_max;
|
||||
// Loop through all corners and transform them to screen space
|
||||
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));
|
||||
if(i==0) {
|
||||
screen_min = screen_pos.xy();
|
||||
screen_max = screen_pos.xy();
|
||||
} else {
|
||||
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.x > screen_max.x) screen_max.x = screen_pos.x;
|
||||
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.y = KRCLAMP(screen_min.y, 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);
|
||||
|
||||
float c = (screen_max.x - screen_min.x) * (screen_max.y - screen_min.y);
|
||||
return KRCLAMP(c, 0.01f, 1.0f);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool KRViewport::visible(const AABB &b) const
|
||||
{
|
||||
// test if bounding box would be within the visible range of the clip space transformed by matViewProjection
|
||||
// This is used for view frustrum culling
|
||||
|
||||
int outside_count[6] = {0, 0, 0, 0, 0, 0};
|
||||
|
||||
for(int iCorner=0; iCorner<8; iCorner++) {
|
||||
Vector4 sourceCornerVertex = Vector4::Create(
|
||||
(iCorner & 1) == 0 ? b.min.x : b.max.x,
|
||||
(iCorner & 2) == 0 ? b.min.y : b.max.y,
|
||||
(iCorner & 4) == 0 ? b.min.z : b.max.z, 1.0f);
|
||||
|
||||
Vector4 cornerVertex = Matrix4::Dot4(m_matViewProjection, sourceCornerVertex);
|
||||
|
||||
if(cornerVertex.x < -cornerVertex.w) {
|
||||
outside_count[0]++;
|
||||
}
|
||||
if(cornerVertex.y < -cornerVertex.w) {
|
||||
outside_count[1]++;
|
||||
}
|
||||
if(cornerVertex.z < -cornerVertex.w) {
|
||||
outside_count[2]++;
|
||||
}
|
||||
if(cornerVertex.x > cornerVertex.w) {
|
||||
outside_count[3]++;
|
||||
}
|
||||
if(cornerVertex.y > cornerVertex.w) {
|
||||
outside_count[4]++;
|
||||
}
|
||||
if(cornerVertex.z > cornerVertex.w) {
|
||||
outside_count[5]++;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_visible = true;
|
||||
for(int iFace=0; iFace < 6; iFace++) {
|
||||
if(outside_count[iFace] == 8) {
|
||||
is_visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
return is_visible;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// KRViewport.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-10-25.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#define KRENGINE_SWAP_INT(x,y) {int t;t=x;x=y;y=t;}
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRViewport.h"
|
||||
|
||||
KRViewport::KRViewport()
|
||||
{
|
||||
m_size = Vector2::One();
|
||||
m_matProjection = Matrix4();
|
||||
m_matView = Matrix4();
|
||||
m_lodBias = 0.0f;
|
||||
calculateDerivedValues();
|
||||
}
|
||||
|
||||
KRViewport::KRViewport(const Vector2 &size, const Matrix4 &matView, const Matrix4 &matProjection)
|
||||
{
|
||||
m_size = size;
|
||||
m_matView = matView;
|
||||
m_matProjection = matProjection;
|
||||
calculateDerivedValues();
|
||||
}
|
||||
|
||||
|
||||
KRViewport& KRViewport::operator=(const KRViewport &v) {
|
||||
if(this != &v) { // Prevent self-assignment.
|
||||
m_size = v.m_size;
|
||||
m_matProjection = v.m_matProjection;
|
||||
m_matView = v.m_matView;
|
||||
m_lodBias = v.m_lodBias;
|
||||
|
||||
calculateDerivedValues();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
KRViewport::~KRViewport()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const Vector2 &KRViewport::getSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
const Matrix4 &KRViewport::getViewMatrix() const
|
||||
{
|
||||
return m_matView;
|
||||
}
|
||||
|
||||
const Matrix4 &KRViewport::getProjectionMatrix() const
|
||||
{
|
||||
return m_matProjection;
|
||||
}
|
||||
|
||||
void KRViewport::setSize(const Vector2 &size)
|
||||
{
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
void KRViewport::setViewMatrix(const Matrix4 &matView)
|
||||
{
|
||||
m_matView = matView;
|
||||
calculateDerivedValues();
|
||||
}
|
||||
|
||||
void KRViewport::setProjectionMatrix(const Matrix4 &matProjection)
|
||||
{
|
||||
m_matProjection = matProjection;
|
||||
calculateDerivedValues();
|
||||
}
|
||||
|
||||
const Matrix4 &KRViewport::KRViewport::getViewProjectionMatrix() const
|
||||
{
|
||||
return m_matViewProjection;
|
||||
}
|
||||
|
||||
const Matrix4 &KRViewport::getInverseViewMatrix() const
|
||||
{
|
||||
return m_matInverseView;
|
||||
}
|
||||
|
||||
const Matrix4 &KRViewport::getInverseProjectionMatrix() const
|
||||
{
|
||||
return m_matInverseProjection;
|
||||
}
|
||||
|
||||
const Vector3 &KRViewport::getCameraDirection() const
|
||||
{
|
||||
return m_cameraDirection;
|
||||
}
|
||||
|
||||
const Vector3 &KRViewport::getCameraPosition() const
|
||||
{
|
||||
return m_cameraPosition;
|
||||
}
|
||||
|
||||
const int *KRViewport::getFrontToBackOrder() const
|
||||
{
|
||||
return &m_frontToBackOrder[0];
|
||||
}
|
||||
|
||||
const int *KRViewport::getBackToFrontOrder() const
|
||||
{
|
||||
return &m_backToFrontOrder[0];
|
||||
}
|
||||
|
||||
void KRViewport::calculateDerivedValues()
|
||||
{
|
||||
m_matViewProjection = m_matView * m_matProjection;
|
||||
m_matInverseView = Matrix4::Invert(m_matView);
|
||||
m_matInverseProjection = Matrix4::Invert(m_matProjection);
|
||||
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));
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
m_frontToBackOrder[i] = i;
|
||||
}
|
||||
|
||||
if(m_cameraDirection.x > 0.0) {
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[1]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[2], m_frontToBackOrder[3]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[4], m_frontToBackOrder[5]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[6], m_frontToBackOrder[7]);
|
||||
}
|
||||
|
||||
if(m_cameraDirection.y > 0.0) {
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[2]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[1], m_frontToBackOrder[3]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[4], m_frontToBackOrder[6]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[5], m_frontToBackOrder[7]);
|
||||
}
|
||||
|
||||
if(m_cameraDirection.z > 0.0) {
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[4]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[1], m_frontToBackOrder[5]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[2], m_frontToBackOrder[6]);
|
||||
KRENGINE_SWAP_INT(m_frontToBackOrder[3], m_frontToBackOrder[7]);
|
||||
}
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
m_backToFrontOrder[i] = m_frontToBackOrder[7-i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unordered_map<AABB, int> &KRViewport::getVisibleBounds()
|
||||
{
|
||||
return m_visibleBounds;
|
||||
}
|
||||
|
||||
float KRViewport::getLODBias() const
|
||||
{
|
||||
return m_lodBias;
|
||||
}
|
||||
|
||||
void KRViewport::setLODBias(float lod_bias)
|
||||
{
|
||||
m_lodBias = lod_bias;
|
||||
}
|
||||
|
||||
float KRViewport::coverage(const AABB &b) const
|
||||
{
|
||||
if(!visible(b)) {
|
||||
return 0.0f; // Culled out by view frustrum
|
||||
} else {
|
||||
Vector3 nearest_point = b.nearestPoint(getCameraPosition());
|
||||
float distance = (nearest_point - getCameraPosition()).magnitude();
|
||||
|
||||
Vector3 v = Matrix4::DotWDiv(m_matProjection, getCameraPosition() + getCameraDirection() * distance);
|
||||
|
||||
float screen_depth = distance / 1000.0f;
|
||||
|
||||
return KRCLAMP(1.0f - screen_depth, 0.01f, 1.0f);
|
||||
|
||||
/*
|
||||
|
||||
Vector2 screen_min;
|
||||
Vector2 screen_max;
|
||||
// Loop through all corners and transform them to screen space
|
||||
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));
|
||||
if(i==0) {
|
||||
screen_min = screen_pos.xy();
|
||||
screen_max = screen_pos.xy();
|
||||
} else {
|
||||
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.x > screen_max.x) screen_max.x = screen_pos.x;
|
||||
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.y = KRCLAMP(screen_min.y, 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);
|
||||
|
||||
float c = (screen_max.x - screen_min.x) * (screen_max.y - screen_min.y);
|
||||
return KRCLAMP(c, 0.01f, 1.0f);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool KRViewport::visible(const AABB &b) const
|
||||
{
|
||||
// test if bounding box would be within the visible range of the clip space transformed by matViewProjection
|
||||
// This is used for view frustrum culling
|
||||
|
||||
int outside_count[6] = {0, 0, 0, 0, 0, 0};
|
||||
|
||||
for(int iCorner=0; iCorner<8; iCorner++) {
|
||||
Vector4 sourceCornerVertex = Vector4::Create(
|
||||
(iCorner & 1) == 0 ? b.min.x : b.max.x,
|
||||
(iCorner & 2) == 0 ? b.min.y : b.max.y,
|
||||
(iCorner & 4) == 0 ? b.min.z : b.max.z, 1.0f);
|
||||
|
||||
Vector4 cornerVertex = Matrix4::Dot4(m_matViewProjection, sourceCornerVertex);
|
||||
|
||||
if(cornerVertex.x < -cornerVertex.w) {
|
||||
outside_count[0]++;
|
||||
}
|
||||
if(cornerVertex.y < -cornerVertex.w) {
|
||||
outside_count[1]++;
|
||||
}
|
||||
if(cornerVertex.z < -cornerVertex.w) {
|
||||
outside_count[2]++;
|
||||
}
|
||||
if(cornerVertex.x > cornerVertex.w) {
|
||||
outside_count[3]++;
|
||||
}
|
||||
if(cornerVertex.y > cornerVertex.w) {
|
||||
outside_count[4]++;
|
||||
}
|
||||
if(cornerVertex.z > cornerVertex.w) {
|
||||
outside_count[5]++;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_visible = true;
|
||||
for(int iFace=0; iFace < 6; iFace++) {
|
||||
if(outside_count[iFace] == 8) {
|
||||
is_visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
return is_visible;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user