Updated Subrepos, hydra data types are now POD -- refactored Kraken to match. Eliminated some warnings
This commit is contained in:
12
.gitignore
vendored
12
.gitignore
vendored
@@ -1,4 +1,8 @@
|
|||||||
.vs/
|
.vs/
|
||||||
Kraken.xcodeproj/xcuserdata
|
Kraken.xcodeproj/xcuserdata
|
||||||
kraken_win/build/
|
kraken_win/build/
|
||||||
build/
|
build/
|
||||||
|
kraken.dir/
|
||||||
|
Win32/
|
||||||
|
x64/
|
||||||
|
kraken_win
|
||||||
|
|||||||
2
3rdparty/glad
vendored
2
3rdparty/glad
vendored
Submodule 3rdparty/glad updated: 5831fb7741...3ea14553f9
2
3rdparty/glfw
vendored
2
3rdparty/glfw
vendored
Submodule 3rdparty/glfw updated: 23dfeee4cb...0be4f3f75a
2
hydra
2
hydra
Submodule hydra updated: 00bb9b6689...759b7af066
@@ -1,91 +1,81 @@
|
|||||||
include_directories(public)
|
include_directories(public)
|
||||||
add_subdirectory(public)
|
add_subdirectory(public)
|
||||||
set(KRAKEN_PUBLIC_HEADERS "${KRAKEN_PUBLIC_HEADERS}" PARENT_SCOPE)
|
set(KRAKEN_PUBLIC_HEADERS "${KRAKEN_PUBLIC_HEADERS}" PARENT_SCOPE)
|
||||||
|
|
||||||
add_sources(scalar.cpp)
|
# Private Implementation
|
||||||
add_sources(vector2.cpp)
|
add_sources(KRAmbientZone.cpp)
|
||||||
add_sources(vector3.cpp)
|
add_sources(KRAnimation.cpp)
|
||||||
add_sources(vector4.cpp)
|
add_sources(KRAnimationAttribute.cpp)
|
||||||
add_sources(triangle3.cpp)
|
add_sources(KRAnimationCurve.cpp)
|
||||||
add_sources(quaternion.cpp)
|
add_sources(KRAnimationCurveManager.cpp)
|
||||||
add_sources(matrix4.cpp)
|
add_sources(KRAnimationLayer.cpp)
|
||||||
add_sources(aabb.cpp)
|
add_sources(KRAnimationManager.cpp)
|
||||||
add_sources(hitinfo.cpp)
|
add_sources(KRAudioBuffer.cpp)
|
||||||
|
add_sources(KRAudioManager.cpp)
|
||||||
# Private Implementation
|
add_sources(KRAudioSample.cpp)
|
||||||
add_sources(KRAmbientZone.cpp)
|
add_sources(KRAudioSource.cpp)
|
||||||
add_sources(KRAnimation.cpp)
|
add_sources(KRBehavior.cpp)
|
||||||
add_sources(KRAnimationAttribute.cpp)
|
add_sources(KRBone.cpp)
|
||||||
add_sources(KRAnimationCurve.cpp)
|
add_sources(KRBundle.cpp)
|
||||||
add_sources(KRAnimationCurveManager.cpp)
|
add_sources(KRBundleManager.cpp)
|
||||||
add_sources(KRAnimationLayer.cpp)
|
add_sources(KRCamera.cpp)
|
||||||
add_sources(KRAnimationManager.cpp)
|
add_sources(KRCollider.cpp)
|
||||||
add_sources(KRAudioBuffer.cpp)
|
add_sources(KRContext.cpp)
|
||||||
add_sources(KRAudioManager.cpp)
|
IF(APPLE)
|
||||||
add_sources(KRAudioSample.cpp)
|
add_sources(KREngine.mm)
|
||||||
add_sources(KRAudioSource.cpp)
|
add_sources(KRStreamer.mm)
|
||||||
add_sources(KRBehavior.cpp)
|
IF(IOS)
|
||||||
add_sources(KRBone.cpp)
|
add_sources(KRContext_ios.mm)
|
||||||
add_sources(KRBundle.cpp)
|
ELSE()
|
||||||
add_sources(KRBundleManager.cpp)
|
add_sources(KRContext_osx.mm)
|
||||||
add_sources(KRCamera.cpp)
|
ENDIF()
|
||||||
add_sources(KRCollider.cpp)
|
ENDIF (APPLE)
|
||||||
add_sources(KRContext.cpp)
|
add_sources(KRContextObject.cpp)
|
||||||
IF(APPLE)
|
add_sources(KRDataBlock.cpp)
|
||||||
add_sources(KREngine.mm)
|
add_sources(KRDirectionalLight.cpp)
|
||||||
add_sources(KRStreamer.mm)
|
IF(APPLE)
|
||||||
IF(IOS)
|
add_sources(KRDSP_vDSP.cpp)
|
||||||
add_sources(KRContext_ios.mm)
|
ELSE()
|
||||||
ELSE()
|
add_sources(KRDSP_slow.cpp)
|
||||||
add_sources(KRContext_osx.mm)
|
ENDIF()
|
||||||
ENDIF()
|
add_sources(KRHelpers.cpp)
|
||||||
ENDIF (APPLE)
|
add_sources(KRLight.cpp)
|
||||||
add_sources(KRContextObject.cpp)
|
add_sources(KRLocator.cpp)
|
||||||
add_sources(KRDataBlock.cpp)
|
add_sources(KRLODGroup.cpp)
|
||||||
add_sources(KRDirectionalLight.cpp)
|
add_sources(KRLODSet.cpp)
|
||||||
IF(APPLE)
|
add_sources(KRMaterial.cpp)
|
||||||
add_sources(KRDSP_vDSP.cpp)
|
add_sources(KRMaterialManager.cpp)
|
||||||
ELSE()
|
add_sources(KRMesh.cpp)
|
||||||
add_sources(KRDSP_slow.cpp)
|
add_sources(KRMeshCube.cpp)
|
||||||
ENDIF()
|
add_sources(KRMeshManager.cpp)
|
||||||
add_sources(KRHelpers.cpp)
|
add_sources(KRMeshQuad.cpp)
|
||||||
add_sources(KRLight.cpp)
|
add_sources(KRMeshSphere.cpp)
|
||||||
add_sources(KRLocator.cpp)
|
add_sources(KRModel.cpp)
|
||||||
add_sources(KRLODGroup.cpp)
|
add_sources(KRNode.cpp)
|
||||||
add_sources(KRLODSet.cpp)
|
add_sources(KROctree.cpp)
|
||||||
add_sources(KRMaterial.cpp)
|
add_sources(KROctreeNode.cpp)
|
||||||
add_sources(KRMaterialManager.cpp)
|
add_sources(KRParticleSystem.cpp)
|
||||||
add_sources(KRMesh.cpp)
|
add_sources(KRParticleSystemNewtonian.h)
|
||||||
add_sources(KRMeshCube.cpp)
|
add_sources(KRPointLight.cpp)
|
||||||
add_sources(KRMeshManager.cpp)
|
add_sources(KRRenderSettings.cpp)
|
||||||
add_sources(KRMeshQuad.cpp)
|
add_sources(KRResource+blend.cpp)
|
||||||
add_sources(KRMeshSphere.cpp)
|
# add_sources(KRResource+fbx.cpp) # TODO - Locate FBX SDK dependencies
|
||||||
add_sources(KRModel.cpp)
|
add_sources(KRResource+obj.cpp)
|
||||||
add_sources(KRNode.cpp)
|
add_sources(KRResource.cpp)
|
||||||
add_sources(KROctree.cpp)
|
add_sources(KRReverbZone.cpp)
|
||||||
add_sources(KROctreeNode.cpp)
|
add_sources(KRScene.cpp)
|
||||||
add_sources(KRParticleSystem.cpp)
|
add_sources(KRShader.cpp)
|
||||||
add_sources(KRParticleSystemNewtonian.h)
|
add_sources(KRShaderManager.cpp)
|
||||||
add_sources(KRPointLight.cpp)
|
add_sources(KRSpotLight.cpp)
|
||||||
add_sources(KRRenderSettings.cpp)
|
add_sources(KRSprite.cpp)
|
||||||
add_sources(KRResource+blend.cpp)
|
add_sources(KRTexture.cpp)
|
||||||
# add_sources(KRResource+fbx.cpp) # TODO - Locate FBX SDK dependencies
|
add_sources(KRTexture2D.cpp)
|
||||||
add_sources(KRResource+obj.cpp)
|
add_sources(KRTextureAnimated.cpp)
|
||||||
add_sources(KRResource.cpp)
|
add_sources(KRTextureCube.cpp)
|
||||||
add_sources(KRReverbZone.cpp)
|
add_sources(KRTextureKTX.cpp)
|
||||||
add_sources(KRScene.cpp)
|
add_sources(KRTextureManager.cpp)
|
||||||
add_sources(KRShader.cpp)
|
add_sources(KRTexturePVR.cpp)
|
||||||
add_sources(KRShaderManager.cpp)
|
add_sources(KRTextureTGA.cpp)
|
||||||
add_sources(KRSpotLight.cpp)
|
add_sources(KRUnknown.cpp)
|
||||||
add_sources(KRSprite.cpp)
|
add_sources(KRUnknownManager.cpp)
|
||||||
add_sources(KRTexture.cpp)
|
add_sources(KRViewport.cpp)
|
||||||
add_sources(KRTexture2D.cpp)
|
|
||||||
add_sources(KRTextureAnimated.cpp)
|
|
||||||
add_sources(KRTextureCube.cpp)
|
|
||||||
add_sources(KRTextureKTX.cpp)
|
|
||||||
add_sources(KRTextureManager.cpp)
|
|
||||||
add_sources(KRTexturePVR.cpp)
|
|
||||||
add_sources(KRTextureTGA.cpp)
|
|
||||||
add_sources(KRUnknown.cpp)
|
|
||||||
add_sources(KRUnknownManager.cpp)
|
|
||||||
add_sources(KRViewport.cpp)
|
|
||||||
|
|||||||
@@ -1,167 +1,167 @@
|
|||||||
//
|
//
|
||||||
// KRAmbientZone.cpp
|
// KRAmbientZone.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 2012-12-06.
|
// Created by Kearwood Gilbert on 2012-12-06.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KRAmbientZone.h"
|
#include "KRAmbientZone.h"
|
||||||
#include "KRContext.h"
|
#include "KRContext.h"
|
||||||
|
|
||||||
KRAmbientZone::KRAmbientZone(KRScene &scene, std::string name) : KRNode(scene, name)
|
KRAmbientZone::KRAmbientZone(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||||
{
|
{
|
||||||
m_ambient = "";
|
m_ambient = "";
|
||||||
m_ambient_gain = 1.0f;
|
m_ambient_gain = 1.0f;
|
||||||
|
|
||||||
m_gradient_distance = 0.25f;
|
m_gradient_distance = 0.25f;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KRAmbientZone::~KRAmbientZone()
|
KRAmbientZone::~KRAmbientZone()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KRAmbientZone::getElementName() {
|
std::string KRAmbientZone::getElementName() {
|
||||||
return "ambient_zone";
|
return "ambient_zone";
|
||||||
}
|
}
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRAmbientZone::saveXML( tinyxml2::XMLNode *parent)
|
tinyxml2::XMLElement *KRAmbientZone::saveXML( tinyxml2::XMLNode *parent)
|
||||||
{
|
{
|
||||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||||
e->SetAttribute("zone", m_zone.c_str());
|
e->SetAttribute("zone", m_zone.c_str());
|
||||||
e->SetAttribute("sample", m_ambient.c_str());
|
e->SetAttribute("sample", m_ambient.c_str());
|
||||||
e->SetAttribute("gain", m_ambient_gain);
|
e->SetAttribute("gain", m_ambient_gain);
|
||||||
e->SetAttribute("gradient", m_gradient_distance);
|
e->SetAttribute("gradient", m_gradient_distance);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRAmbientZone::loadXML(tinyxml2::XMLElement *e)
|
void KRAmbientZone::loadXML(tinyxml2::XMLElement *e)
|
||||||
{
|
{
|
||||||
KRNode::loadXML(e);
|
KRNode::loadXML(e);
|
||||||
|
|
||||||
m_zone = e->Attribute("zone");
|
m_zone = e->Attribute("zone");
|
||||||
|
|
||||||
m_gradient_distance = 0.25f;
|
m_gradient_distance = 0.25f;
|
||||||
if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
|
||||||
m_gradient_distance = 0.25f;
|
m_gradient_distance = 0.25f;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ambient = e->Attribute("sample");
|
m_ambient = e->Attribute("sample");
|
||||||
|
|
||||||
m_ambient_gain = 1.0f;
|
m_ambient_gain = 1.0f;
|
||||||
if(e->QueryFloatAttribute("gain", &m_ambient_gain) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("gain", &m_ambient_gain) != tinyxml2::XML_SUCCESS) {
|
||||||
m_ambient_gain = 1.0f;
|
m_ambient_gain = 1.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KRAmbientZone::getAmbient()
|
std::string KRAmbientZone::getAmbient()
|
||||||
{
|
{
|
||||||
return m_ambient;
|
return m_ambient;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRAmbientZone::setAmbient(const std::string &ambient)
|
void KRAmbientZone::setAmbient(const std::string &ambient)
|
||||||
{
|
{
|
||||||
m_ambient = ambient;
|
m_ambient = ambient;
|
||||||
}
|
}
|
||||||
|
|
||||||
float KRAmbientZone::getAmbientGain()
|
float KRAmbientZone::getAmbientGain()
|
||||||
{
|
{
|
||||||
return m_ambient_gain;
|
return m_ambient_gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRAmbientZone::setAmbientGain(float ambient_gain)
|
void KRAmbientZone::setAmbientGain(float ambient_gain)
|
||||||
{
|
{
|
||||||
m_ambient_gain = ambient_gain;
|
m_ambient_gain = ambient_gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KRAmbientZone::getZone()
|
std::string KRAmbientZone::getZone()
|
||||||
{
|
{
|
||||||
return m_zone;
|
return m_zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRAmbientZone::setZone(const std::string &zone)
|
void KRAmbientZone::setZone(const std::string &zone)
|
||||||
{
|
{
|
||||||
m_zone = zone;
|
m_zone = zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRAmbientZone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
|
void KRAmbientZone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
|
||||||
{
|
{
|
||||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||||
|
|
||||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||||
|
|
||||||
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_AMBIENT_ZONES;
|
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_AMBIENT_ZONES;
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
||||||
Matrix4 sphereModelMatrix = getModelMatrix();
|
Matrix4 sphereModelMatrix = getModelMatrix();
|
||||||
|
|
||||||
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
||||||
|
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||||
|
|
||||||
// Enable additive blending
|
// Enable additive blending
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
GLDEBUG(glEnable(GL_BLEND));
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||||
|
|
||||||
|
|
||||||
// Disable z-buffer write
|
// Disable z-buffer write
|
||||||
GLDEBUG(glDepthMask(GL_FALSE));
|
GLDEBUG(glDepthMask(GL_FALSE));
|
||||||
|
|
||||||
// Enable z-buffer test
|
// Enable z-buffer test
|
||||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
||||||
if(sphereModels.size()) {
|
if(sphereModels.size()) {
|
||||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable alpha blending
|
// Enable alpha blending
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
GLDEBUG(glEnable(GL_BLEND));
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float KRAmbientZone::getGradientDistance()
|
float KRAmbientZone::getGradientDistance()
|
||||||
{
|
{
|
||||||
return m_gradient_distance;
|
return m_gradient_distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRAmbientZone::setGradientDistance(float gradient_distance)
|
void KRAmbientZone::setGradientDistance(float gradient_distance)
|
||||||
{
|
{
|
||||||
m_gradient_distance = gradient_distance;
|
m_gradient_distance = gradient_distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
AABB KRAmbientZone::getBounds() {
|
AABB KRAmbientZone::getBounds() {
|
||||||
// Ambient zones always have a -1, -1, -1 to 1, 1, 1 bounding box
|
// Ambient zones always have a -1, -1, -1 to 1, 1, 1 bounding box
|
||||||
return AABB(-Vector3::One(), Vector3::One(), getModelMatrix());
|
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
|
||||||
}
|
}
|
||||||
|
|
||||||
float KRAmbientZone::getContainment(const Vector3 &pos)
|
float KRAmbientZone::getContainment(const Vector3 &pos)
|
||||||
{
|
{
|
||||||
AABB bounds = getBounds();
|
AABB bounds = getBounds();
|
||||||
if(bounds.contains(pos)) {
|
if(bounds.contains(pos)) {
|
||||||
Vector3 size = bounds.size();
|
Vector3 size = bounds.size();
|
||||||
Vector3 diff = pos - bounds.center();
|
Vector3 diff = pos - bounds.center();
|
||||||
diff = diff * 2.0f;
|
diff = diff * 2.0f;
|
||||||
diff = Vector3(diff.x / size.x, diff.y / size.y, diff.z / size.z);
|
diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z);
|
||||||
float d = diff.magnitude();
|
float d = diff.magnitude();
|
||||||
|
|
||||||
if(m_gradient_distance <= 0.0f) {
|
if(m_gradient_distance <= 0.0f) {
|
||||||
// Avoid division by zero
|
// Avoid division by zero
|
||||||
d = d > 1.0f ? 0.0f : 1.0f;
|
d = d > 1.0f ? 0.0f : 1.0f;
|
||||||
} else {
|
} else {
|
||||||
d = (1.0f - d) / m_gradient_distance;
|
d = (1.0f - d) / m_gradient_distance;
|
||||||
d = KRCLAMP(d, 0.0f, 1.0f);
|
d = KRCLAMP(d, 0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
return d;
|
return d;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,97 +1,97 @@
|
|||||||
//
|
//
|
||||||
// KRBone.cpp
|
// KRBone.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 2012-12-06.
|
// Created by Kearwood Gilbert on 2012-12-06.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KRBone.h"
|
#include "KRBone.h"
|
||||||
#include "KRContext.h"
|
#include "KRContext.h"
|
||||||
|
|
||||||
KRBone::KRBone(KRScene &scene, std::string name) : KRNode(scene, name)
|
KRBone::KRBone(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||||
{
|
{
|
||||||
setScaleCompensation(true);
|
setScaleCompensation(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
KRBone::~KRBone()
|
KRBone::~KRBone()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KRBone::getElementName() {
|
std::string KRBone::getElementName() {
|
||||||
return "bone";
|
return "bone";
|
||||||
}
|
}
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRBone::saveXML( tinyxml2::XMLNode *parent)
|
tinyxml2::XMLElement *KRBone::saveXML( tinyxml2::XMLNode *parent)
|
||||||
{
|
{
|
||||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRBone::loadXML(tinyxml2::XMLElement *e)
|
void KRBone::loadXML(tinyxml2::XMLElement *e)
|
||||||
{
|
{
|
||||||
KRNode::loadXML(e);
|
KRNode::loadXML(e);
|
||||||
setScaleCompensation(true);
|
setScaleCompensation(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
AABB KRBone::getBounds() {
|
AABB KRBone::getBounds() {
|
||||||
return AABB(-Vector3::One(), Vector3::One(), getModelMatrix()); // Only required for bone debug visualization
|
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix()); // Only required for bone debug visualization
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRBone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
|
void KRBone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
|
||||||
{
|
{
|
||||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||||
|
|
||||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||||
|
|
||||||
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_BONES;
|
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_BONES;
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
||||||
Matrix4 sphereModelMatrix = getModelMatrix();
|
Matrix4 sphereModelMatrix = getModelMatrix();
|
||||||
|
|
||||||
// Enable additive blending
|
// Enable additive blending
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
GLDEBUG(glEnable(GL_BLEND));
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||||
|
|
||||||
|
|
||||||
// Disable z-buffer write
|
// Disable z-buffer write
|
||||||
GLDEBUG(glDepthMask(GL_FALSE));
|
GLDEBUG(glDepthMask(GL_FALSE));
|
||||||
|
|
||||||
// Disable z-buffer test
|
// Disable z-buffer test
|
||||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||||
|
|
||||||
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
||||||
|
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
||||||
if(sphereModels.size()) {
|
if(sphereModels.size()) {
|
||||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable alpha blending
|
// Enable alpha blending
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
GLDEBUG(glEnable(GL_BLEND));
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||||
|
|
||||||
// Enable z-buffer test
|
// Enable z-buffer test
|
||||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void KRBone::setBindPose(const Matrix4 &pose)
|
void KRBone::setBindPose(const Matrix4 &pose)
|
||||||
{
|
{
|
||||||
m_bind_pose = pose;
|
m_bind_pose = pose;
|
||||||
}
|
}
|
||||||
const Matrix4 &KRBone::getBindPose()
|
const Matrix4 &KRBone::getBindPose()
|
||||||
{
|
{
|
||||||
return m_bind_pose;
|
return m_bind_pose;
|
||||||
}
|
}
|
||||||
|
|||||||
2246
kraken/KRCamera.cpp
2246
kraken/KRCamera.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,229 +1,229 @@
|
|||||||
//
|
//
|
||||||
// KRCollider.cpp
|
// KRCollider.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
// permitted provided that the following conditions are met:
|
// permitted provided that the following conditions are met:
|
||||||
//
|
//
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
// conditions and the following disclaimer.
|
// conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
// provided with the distribution.
|
// provided with the distribution.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
// or implied, of Kearwood Gilbert.
|
// or implied, of Kearwood Gilbert.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
#include "KRCollider.h"
|
#include "KRCollider.h"
|
||||||
#include "KRContext.h"
|
#include "KRContext.h"
|
||||||
#include "KRMesh.h"
|
#include "KRMesh.h"
|
||||||
|
|
||||||
|
|
||||||
KRCollider::KRCollider(KRScene &scene, std::string collider_name, std::string model_name, unsigned int layer_mask, float audio_occlusion) : KRNode(scene, collider_name) {
|
KRCollider::KRCollider(KRScene &scene, std::string collider_name, std::string model_name, unsigned int layer_mask, float audio_occlusion) : KRNode(scene, collider_name) {
|
||||||
m_model_name = model_name;
|
m_model_name = model_name;
|
||||||
m_layer_mask = layer_mask;
|
m_layer_mask = layer_mask;
|
||||||
m_audio_occlusion = audio_occlusion;
|
m_audio_occlusion = audio_occlusion;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRCollider::~KRCollider() {
|
KRCollider::~KRCollider() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KRCollider::getElementName() {
|
std::string KRCollider::getElementName() {
|
||||||
return "collider";
|
return "collider";
|
||||||
}
|
}
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRCollider::saveXML( tinyxml2::XMLNode *parent)
|
tinyxml2::XMLElement *KRCollider::saveXML( tinyxml2::XMLNode *parent)
|
||||||
{
|
{
|
||||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||||
e->SetAttribute("mesh", m_model_name.c_str());
|
e->SetAttribute("mesh", m_model_name.c_str());
|
||||||
e->SetAttribute("layer_mask", m_layer_mask);
|
e->SetAttribute("layer_mask", m_layer_mask);
|
||||||
e->SetAttribute("audio_occlusion", m_audio_occlusion);
|
e->SetAttribute("audio_occlusion", m_audio_occlusion);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRCollider::loadXML(tinyxml2::XMLElement *e) {
|
void KRCollider::loadXML(tinyxml2::XMLElement *e) {
|
||||||
KRNode::loadXML(e);
|
KRNode::loadXML(e);
|
||||||
|
|
||||||
m_model_name = e->Attribute("mesh");
|
m_model_name = e->Attribute("mesh");
|
||||||
|
|
||||||
m_layer_mask = 65535;
|
m_layer_mask = 65535;
|
||||||
if(e->QueryUnsignedAttribute("layer_mask", &m_layer_mask) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryUnsignedAttribute("layer_mask", &m_layer_mask) != tinyxml2::XML_SUCCESS) {
|
||||||
m_layer_mask = 65535;
|
m_layer_mask = 65535;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_audio_occlusion = 1.0f;
|
m_audio_occlusion = 1.0f;
|
||||||
if(e->QueryFloatAttribute("audio_occlusion", &m_audio_occlusion) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("audio_occlusion", &m_audio_occlusion) != tinyxml2::XML_SUCCESS) {
|
||||||
m_audio_occlusion = 1.0f;
|
m_audio_occlusion = 1.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRCollider::loadModel() {
|
void KRCollider::loadModel() {
|
||||||
if(m_models.size() == 0) {
|
if(m_models.size() == 0) {
|
||||||
m_models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first
|
m_models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first
|
||||||
if(m_models.size() > 0) {
|
if(m_models.size() > 0) {
|
||||||
getScene().notify_sceneGraphModify(this);
|
getScene().notify_sceneGraphModify(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AABB KRCollider::getBounds() {
|
AABB KRCollider::getBounds() {
|
||||||
loadModel();
|
loadModel();
|
||||||
if(m_models.size() > 0) {
|
if(m_models.size() > 0) {
|
||||||
return AABB(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
return AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||||
} else {
|
} else {
|
||||||
return AABB::Infinite();
|
return AABB::Infinite();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KRCollider::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask)
|
bool KRCollider::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask)
|
||||||
{
|
{
|
||||||
if(layer_mask & m_layer_mask ) { // Only test if layer masks have a common bit set
|
if(layer_mask & m_layer_mask ) { // Only test if layer masks have a common bit set
|
||||||
loadModel();
|
loadModel();
|
||||||
if(m_models.size()) {
|
if(m_models.size()) {
|
||||||
if(getBounds().intersectsLine(v0, v1)) {
|
if(getBounds().intersectsLine(v0, v1)) {
|
||||||
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
|
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
|
||||||
Vector3 v1_model_space = Matrix4::Dot(getInverseModelMatrix(), v1);
|
Vector3 v1_model_space = Matrix4::Dot(getInverseModelMatrix(), v1);
|
||||||
HitInfo hitinfo_model_space;
|
HitInfo hitinfo_model_space;
|
||||||
if(hitinfo.didHit()) {
|
if(hitinfo.didHit()) {
|
||||||
Vector3 hit_position_model_space = Matrix4::Dot(getInverseModelMatrix(), hitinfo.getPosition());
|
Vector3 hit_position_model_space = Matrix4::Dot(getInverseModelMatrix(), hitinfo.getPosition());
|
||||||
hitinfo_model_space = HitInfo(hit_position_model_space, Matrix4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal()), (hit_position_model_space - v0_model_space).magnitude(), hitinfo.getNode());
|
hitinfo_model_space = HitInfo(hit_position_model_space, Matrix4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal()), (hit_position_model_space - v0_model_space).magnitude(), hitinfo.getNode());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_models[0]->lineCast(v0_model_space, v1_model_space, hitinfo_model_space)) {
|
if(m_models[0]->lineCast(v0_model_space, v1_model_space, hitinfo_model_space)) {
|
||||||
Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition());
|
Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition());
|
||||||
hitinfo = HitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
|
hitinfo = HitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KRCollider::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
|
bool KRCollider::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
|
||||||
{
|
{
|
||||||
if(layer_mask & m_layer_mask) { // Only test if layer masks have a common bit set
|
if(layer_mask & m_layer_mask) { // Only test if layer masks have a common bit set
|
||||||
loadModel();
|
loadModel();
|
||||||
if(m_models.size()) {
|
if(m_models.size()) {
|
||||||
if(getBounds().intersectsRay(v0, dir)) {
|
if(getBounds().intersectsRay(v0, dir)) {
|
||||||
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
|
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
|
||||||
Vector3 dir_model_space = Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), dir));
|
Vector3 dir_model_space = Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), dir));
|
||||||
HitInfo hitinfo_model_space;
|
HitInfo hitinfo_model_space;
|
||||||
if(hitinfo.didHit()) {
|
if(hitinfo.didHit()) {
|
||||||
Vector3 hit_position_model_space = Matrix4::Dot(getInverseModelMatrix(), hitinfo.getPosition());
|
Vector3 hit_position_model_space = Matrix4::Dot(getInverseModelMatrix(), hitinfo.getPosition());
|
||||||
hitinfo_model_space = HitInfo(hit_position_model_space, Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal())), (hit_position_model_space - v0_model_space).magnitude(), hitinfo.getNode());
|
hitinfo_model_space = HitInfo(hit_position_model_space, Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal())), (hit_position_model_space - v0_model_space).magnitude(), hitinfo.getNode());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_models[0]->rayCast(v0_model_space, dir_model_space, hitinfo_model_space)) {
|
if(m_models[0]->rayCast(v0_model_space, dir_model_space, hitinfo_model_space)) {
|
||||||
Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition());
|
Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition());
|
||||||
hitinfo = HitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
|
hitinfo = HitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KRCollider::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
|
bool KRCollider::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
|
||||||
{
|
{
|
||||||
if(layer_mask & m_layer_mask) { // Only test if layer masks have a common bit set
|
if(layer_mask & m_layer_mask) { // Only test if layer masks have a common bit set
|
||||||
loadModel();
|
loadModel();
|
||||||
if(m_models.size()) {
|
if(m_models.size()) {
|
||||||
AABB sphereCastBounds = AABB( // TODO - Need to cache this; perhaps encasulate within a "spherecast" class to be passed through these functions
|
AABB sphereCastBounds = AABB::Create( // TODO - Need to cache this; perhaps encasulate within a "spherecast" class to be passed through these functions
|
||||||
Vector3(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius),
|
Vector3::Create(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius),
|
||||||
Vector3(KRMAX(v0.x, v1.x) + radius, KRMAX(v0.y, v1.y) + radius, KRMAX(v0.z, v1.z) + radius)
|
Vector3::Create(KRMAX(v0.x, v1.x) + radius, KRMAX(v0.y, v1.y) + radius, KRMAX(v0.z, v1.z) + radius)
|
||||||
);
|
);
|
||||||
|
|
||||||
if(getBounds().intersects(sphereCastBounds)) {
|
if(getBounds().intersects(sphereCastBounds)) {
|
||||||
if(m_models[0]->sphereCast(getModelMatrix(), v0, v1, radius, hitinfo)) {
|
if(m_models[0]->sphereCast(getModelMatrix(), v0, v1, radius, hitinfo)) {
|
||||||
hitinfo = HitInfo(hitinfo.getPosition(), hitinfo.getNormal(), hitinfo.getDistance(), this);
|
hitinfo = HitInfo(hitinfo.getPosition(), hitinfo.getNormal(), hitinfo.getDistance(), this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int KRCollider::getLayerMask()
|
unsigned int KRCollider::getLayerMask()
|
||||||
{
|
{
|
||||||
return m_layer_mask;
|
return m_layer_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRCollider::setLayerMask(unsigned int layer_mask)
|
void KRCollider::setLayerMask(unsigned int layer_mask)
|
||||||
{
|
{
|
||||||
m_layer_mask = layer_mask;
|
m_layer_mask = layer_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
float KRCollider::getAudioOcclusion()
|
float KRCollider::getAudioOcclusion()
|
||||||
{
|
{
|
||||||
return m_audio_occlusion;
|
return m_audio_occlusion;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRCollider::setAudioOcclusion(float audio_occlusion)
|
void KRCollider::setAudioOcclusion(float audio_occlusion)
|
||||||
{
|
{
|
||||||
m_audio_occlusion = audio_occlusion;
|
m_audio_occlusion = audio_occlusion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void KRCollider::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
|
void KRCollider::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
|
||||||
{
|
{
|
||||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||||
|
|
||||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_COLLIDERS) {
|
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_COLLIDERS) {
|
||||||
loadModel();
|
loadModel();
|
||||||
if(m_models.size()) {
|
if(m_models.size()) {
|
||||||
|
|
||||||
GL_PUSH_GROUP_MARKER("Debug Overlays");
|
GL_PUSH_GROUP_MARKER("Debug Overlays");
|
||||||
|
|
||||||
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
||||||
|
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||||
|
|
||||||
// Enable additive blending
|
// Enable additive blending
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
GLDEBUG(glEnable(GL_BLEND));
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||||
|
|
||||||
|
|
||||||
// Disable z-buffer write
|
// Disable z-buffer write
|
||||||
GLDEBUG(glDepthMask(GL_FALSE));
|
GLDEBUG(glDepthMask(GL_FALSE));
|
||||||
|
|
||||||
// Enable z-buffer test
|
// Enable z-buffer test
|
||||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||||
|
|
||||||
|
|
||||||
for(int i=0; i < m_models[0]->getSubmeshCount(); i++) {
|
for(int i=0; i < m_models[0]->getSubmeshCount(); i++) {
|
||||||
m_models[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
m_models[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable alpha blending
|
// Enable alpha blending
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
GLDEBUG(glEnable(GL_BLEND));
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_POP_GROUP_MARKER;
|
GL_POP_GROUP_MARKER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,207 +1,207 @@
|
|||||||
//
|
//
|
||||||
// KREngine.h
|
// KREngine.h
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
// permitted provided that the following conditions are met:
|
// permitted provided that the following conditions are met:
|
||||||
//
|
//
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
// conditions and the following disclaimer.
|
// conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
// provided with the distribution.
|
// provided with the distribution.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
// or implied, of Kearwood Gilbert.
|
// or implied, of Kearwood Gilbert.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KRDSP.h"
|
#include "KRDSP.h"
|
||||||
|
|
||||||
#ifdef KRDSP_SLOW
|
#ifdef KRDSP_SLOW
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
namespace KRDSP {
|
namespace KRDSP {
|
||||||
|
|
||||||
FFTWorkspace::FFTWorkspace()
|
FFTWorkspace::FFTWorkspace()
|
||||||
{
|
{
|
||||||
sin_table = nullptr;
|
sin_table = nullptr;
|
||||||
cos_table = nullptr;
|
cos_table = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
FFTWorkspace::~FFTWorkspace()
|
FFTWorkspace::~FFTWorkspace()
|
||||||
{
|
{
|
||||||
destroy();
|
destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FFTWorkspace::create(size_t length)
|
void FFTWorkspace::create(size_t length)
|
||||||
{
|
{
|
||||||
size_t size = (length / 2);
|
size_t size = (length / 2);
|
||||||
cos_table = new float[size];
|
cos_table = new float[size];
|
||||||
sin_table = new float[size];
|
sin_table = new float[size];
|
||||||
for (int i = 0; i < size / 2; i++) {
|
for (int i = 0; i < size / 2; i++) {
|
||||||
float a = 2 * M_PI * i / length;
|
float a = 2.0f * M_PI * i / length;
|
||||||
cos_table[i] = cos(a);
|
cos_table[i] = cos(a);
|
||||||
sin_table[i] = sin(a);
|
sin_table[i] = sin(a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FFTWorkspace::destroy()
|
void FFTWorkspace::destroy()
|
||||||
{
|
{
|
||||||
if (sin_table) {
|
if (sin_table) {
|
||||||
delete sin_table;
|
delete sin_table;
|
||||||
sin_table = nullptr;
|
sin_table = nullptr;
|
||||||
}
|
}
|
||||||
if (cos_table) {
|
if (cos_table) {
|
||||||
delete cos_table;
|
delete cos_table;
|
||||||
cos_table = nullptr;
|
cos_table = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
|
void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
|
||||||
{
|
{
|
||||||
// Radix-2 Decimation in Time FFT Algorithm
|
// Radix-2 Decimation in Time FFT Algorithm
|
||||||
// http://en.dsplib.org/content/fft_dec_in_time.html
|
// http://en.dsplib.org/content/fft_dec_in_time.html
|
||||||
|
|
||||||
// Only power-of-two sizes supported
|
// Only power-of-two sizes supported
|
||||||
assert((count & (count - 1)) == 0);
|
assert((count & (count - 1)) == 0);
|
||||||
|
|
||||||
int levels = 0;
|
int levels = 0;
|
||||||
while (1 << levels <= count) {
|
while (1 << levels <= count) {
|
||||||
levels++;
|
levels++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
size_t j = 0;
|
size_t j = 0;
|
||||||
for (int k = 0; k < levels; k++) {
|
for (int k = 0; k < levels; k++) {
|
||||||
j <<= 1;
|
j <<= 1;
|
||||||
j |= ((i >> k) & 1);
|
j |= ((i >> k) & 1);
|
||||||
}
|
}
|
||||||
if (j > i) {
|
if (j > i) {
|
||||||
float temp = src->realp[i];
|
float temp = src->realp[i];
|
||||||
src->realp[i] = src->realp[j];
|
src->realp[i] = src->realp[j];
|
||||||
src->realp[j] = temp;
|
src->realp[j] = temp;
|
||||||
temp = src->imagp[i];
|
temp = src->imagp[i];
|
||||||
src->imagp[i] = src->imagp[j];
|
src->imagp[i] = src->imagp[j];
|
||||||
src->imagp[j] = temp;
|
src->imagp[j] = temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t size = 2; size <= count; size *= 2) {
|
for (size_t size = 2; size <= count; size *= 2) {
|
||||||
size_t halfsize = size / 2;
|
size_t halfsize = size / 2;
|
||||||
size_t step = count / size;
|
size_t step = count / size;
|
||||||
for (size_t i = 0; i < count; i += size) {
|
for (size_t i = 0; i < count; i += size) {
|
||||||
for (size_t j = i, k = 0; j < i + halfsize; j++, k += step) {
|
for (size_t j = i, k = 0; j < i + halfsize; j++, k += step) {
|
||||||
float temp_real = src->realp[j + halfsize] * workspace.cos_table[k];
|
float temp_real = src->realp[j + halfsize] * workspace.cos_table[k];
|
||||||
temp_real += src->imagp[j + halfsize] * workspace.sin_table[k];
|
temp_real += src->imagp[j + halfsize] * workspace.sin_table[k];
|
||||||
float temp_imag = -src->realp[j + halfsize] * workspace.sin_table[k];
|
float temp_imag = -src->realp[j + halfsize] * workspace.sin_table[k];
|
||||||
temp_imag += src->imagp[j + halfsize] * workspace.cos_table[k];
|
temp_imag += src->imagp[j + halfsize] * workspace.cos_table[k];
|
||||||
src->realp[j + halfsize] = src->realp[j] - temp_real;
|
src->realp[j + halfsize] = src->realp[j] - temp_real;
|
||||||
src->imagp[j + halfsize] = src->imagp[j] - temp_imag;
|
src->imagp[j + halfsize] = src->imagp[j] - temp_imag;
|
||||||
src->realp[j] += temp_real;
|
src->realp[j] += temp_real;
|
||||||
src->imagp[j] += temp_imag;
|
src->imagp[j] += temp_imag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
|
void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
|
||||||
{
|
{
|
||||||
SplitComplex swapped;
|
SplitComplex swapped;
|
||||||
swapped.imagp = src->realp;
|
swapped.imagp = src->realp;
|
||||||
swapped.realp = src->imagp;
|
swapped.realp = src->imagp;
|
||||||
FFTForward(workspace, &swapped, count);
|
FFTForward(workspace, &swapped, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destStride, size_t count)
|
void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destStride, size_t count)
|
||||||
{
|
{
|
||||||
const short *r = src;
|
const short *r = src;
|
||||||
float *w = dest;
|
float *w = dest;
|
||||||
while (w < dest + destStride * count) {
|
while (w < dest + destStride * count) {
|
||||||
*w = (float)*r;
|
*w = (float)*r;
|
||||||
r += srcStride;
|
r += srcStride;
|
||||||
w += destStride;
|
w += destStride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scale(float *buffer, float scale, size_t count)
|
void Scale(float *buffer, float scale, size_t count)
|
||||||
{
|
{
|
||||||
float *w = buffer;
|
float *w = buffer;
|
||||||
while (w < buffer + count) {
|
while (w < buffer + count) {
|
||||||
*w *= scale;
|
*w *= scale;
|
||||||
w++;
|
w++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScaleCopy(const float *src, float scale, float *dest, size_t count)
|
void ScaleCopy(const float *src, float scale, float *dest, size_t count)
|
||||||
{
|
{
|
||||||
const float *r = src;
|
const float *r = src;
|
||||||
float *w = dest;
|
float *w = dest;
|
||||||
while (w < dest + count) {
|
while (w < dest + count) {
|
||||||
*w = *r * scale;
|
*w = *r * scale;
|
||||||
w++;
|
w++;
|
||||||
r++;
|
r++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScaleCopy(const SplitComplex *src, float scale, SplitComplex *dest, size_t count)
|
void ScaleCopy(const SplitComplex *src, float scale, SplitComplex *dest, size_t count)
|
||||||
{
|
{
|
||||||
ScaleCopy(src->realp, scale, dest->realp, count);
|
ScaleCopy(src->realp, scale, dest->realp, count);
|
||||||
ScaleCopy(src->imagp, scale, dest->imagp, count);
|
ScaleCopy(src->imagp, scale, dest->imagp, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count)
|
void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count)
|
||||||
{
|
{
|
||||||
float *w = buffer;
|
float *w = buffer;
|
||||||
float s = scaleStart;
|
float s = scaleStart;
|
||||||
while (w < buffer + count) {
|
while (w < buffer + count) {
|
||||||
*w *= s;
|
*w *= s;
|
||||||
w++;
|
w++;
|
||||||
s += scaleStep;
|
s += scaleStep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t buffer2Stride, size_t count)
|
void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t buffer2Stride, size_t count)
|
||||||
{
|
{
|
||||||
float *w = buffer;
|
float *w = buffer;
|
||||||
const float *r = buffer2;
|
const float *r = buffer2;
|
||||||
while (w < buffer + bufferStride * count) {
|
while (w < buffer + bufferStride * count) {
|
||||||
*w *= *r;
|
*w *= *r;
|
||||||
w += bufferStride;
|
w += bufferStride;
|
||||||
r += buffer2Stride;
|
r += buffer2Stride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count)
|
void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
buffer->imagp[i] += buffer2->imagp[i];
|
buffer->imagp[i] += buffer2->imagp[i];
|
||||||
buffer->realp[i] += buffer2->realp[i];
|
buffer->realp[i] += buffer2->realp[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Multiply(const SplitComplex *a, const SplitComplex *b, SplitComplex *c, size_t count)
|
void Multiply(const SplitComplex *a, const SplitComplex *b, SplitComplex *c, size_t count)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
c->realp[i] = a->realp[i] * b->realp[i] - a->imagp[i] * b->imagp[i];
|
c->realp[i] = a->realp[i] * b->realp[i] - a->imagp[i] * b->imagp[i];
|
||||||
c->imagp[i] = a->realp[i] * b->imagp[i] + a->imagp[i] * b->realp[i];
|
c->imagp[i] = a->realp[i] * b->imagp[i] + a->imagp[i] * b->realp[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace KRDSP
|
} // namespace KRDSP
|
||||||
|
|
||||||
#endif // KRDSP_SLOW
|
#endif // KRDSP_SLOW
|
||||||
|
|||||||
@@ -1,135 +1,135 @@
|
|||||||
//
|
//
|
||||||
// KRDirectionalLight.cpp
|
// KRDirectionalLight.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 12-04-05.
|
// Created by Kearwood Gilbert on 12-04-05.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
#include "KRDirectionalLight.h"
|
#include "KRDirectionalLight.h"
|
||||||
#include "KRShader.h"
|
#include "KRShader.h"
|
||||||
#include "KRContext.h"
|
#include "KRContext.h"
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "KRStockGeometry.h"
|
#include "KRStockGeometry.h"
|
||||||
|
|
||||||
KRDirectionalLight::KRDirectionalLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
KRDirectionalLight::KRDirectionalLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KRDirectionalLight::~KRDirectionalLight()
|
KRDirectionalLight::~KRDirectionalLight()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KRDirectionalLight::getElementName() {
|
std::string KRDirectionalLight::getElementName() {
|
||||||
return "directional_light";
|
return "directional_light";
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 KRDirectionalLight::getWorldLightDirection() {
|
Vector3 KRDirectionalLight::getWorldLightDirection() {
|
||||||
return Matrix4::Dot(getWorldRotation().rotationMatrix(), getLocalLightDirection());
|
return Matrix4::Dot(getWorldRotation().rotationMatrix(), getLocalLightDirection());
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 KRDirectionalLight::getLocalLightDirection() {
|
Vector3 KRDirectionalLight::getLocalLightDirection() {
|
||||||
return Vector3::Up(); //&KRF HACK changed from Vector3::Forward(); - to compensate for the way Maya handles post rotation.
|
return Vector3::Up(); //&KRF HACK changed from Vector3::Forward(); - to compensate for the way Maya handles post rotation.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int KRDirectionalLight::configureShadowBufferViewports(const KRViewport &viewport) {
|
int KRDirectionalLight::configureShadowBufferViewports(const KRViewport &viewport) {
|
||||||
|
|
||||||
const float KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE = 1.25f; // Scale to apply to view frustrum bounds so that we don't need to refresh shadows on every frame
|
const float KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE = 1.25f; // Scale to apply to view frustrum bounds so that we don't need to refresh shadows on every frame
|
||||||
int cShadows = 1;
|
int cShadows = 1;
|
||||||
for(int iShadow=0; iShadow < cShadows; iShadow++) {
|
for(int iShadow=0; iShadow < cShadows; iShadow++) {
|
||||||
/*
|
/*
|
||||||
TODO - Determine if we still need this...
|
TODO - Determine if we still need this...
|
||||||
|
|
||||||
GLfloat shadowMinDepths[3][3] = {{0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f},{0.0f, 0.05f, 0.3f}};
|
GLfloat shadowMinDepths[3][3] = {{0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f},{0.0f, 0.05f, 0.3f}};
|
||||||
GLfloat shadowMaxDepths[3][3] = {{0.0f, 0.0f, 1.0f},{0.1f, 0.0f, 0.0f},{0.1f, 0.3f, 1.0f}};
|
GLfloat shadowMaxDepths[3][3] = {{0.0f, 0.0f, 1.0f},{0.1f, 0.0f, 0.0f},{0.1f, 0.3f, 1.0f}};
|
||||||
|
|
||||||
float min_depth = 0.0f;
|
float min_depth = 0.0f;
|
||||||
float max_depth = 1.0f;
|
float max_depth = 1.0f;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AABB worldSpacefrustrumSliceBounds = AABB(Vector3(-1.0f, -1.0f, -1.0f), Vector3(1.0f, 1.0f, 1.0f), Matrix4::Invert(viewport.getViewProjectionMatrix()));
|
AABB worldSpacefrustrumSliceBounds = AABB::Create(Vector3::Create(-1.0f, -1.0f, -1.0f), Vector3::Create(1.0f, 1.0f, 1.0f), Matrix4::Invert(viewport.getViewProjectionMatrix()));
|
||||||
worldSpacefrustrumSliceBounds.scale(KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
|
worldSpacefrustrumSliceBounds.scale(KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
|
||||||
|
|
||||||
Vector3 shadowLook = -Vector3::Normalize(getWorldLightDirection());
|
Vector3 shadowLook = -Vector3::Normalize(getWorldLightDirection());
|
||||||
|
|
||||||
Vector3 shadowUp(0.0, 1.0, 0.0);
|
Vector3 shadowUp = Vector3::Create(0.0, 1.0, 0.0);
|
||||||
if(Vector3::Dot(shadowUp, shadowLook) > 0.99f) shadowUp = Vector3(0.0, 0.0, 1.0); // Ensure shadow look direction is not parallel with the shadowUp direction
|
if(Vector3::Dot(shadowUp, shadowLook) > 0.99f) shadowUp = Vector3::Create(0.0, 0.0, 1.0); // Ensure shadow look direction is not parallel with the shadowUp direction
|
||||||
|
|
||||||
// Matrix4 matShadowView = Matrix4::LookAt(viewport.getCameraPosition() - shadowLook, viewport.getCameraPosition(), shadowUp);
|
// Matrix4 matShadowView = Matrix4::LookAt(viewport.getCameraPosition() - shadowLook, viewport.getCameraPosition(), shadowUp);
|
||||||
// Matrix4 matShadowProjection = Matrix4();
|
// Matrix4 matShadowProjection = Matrix4();
|
||||||
// matShadowProjection.scale(0.001, 0.001, 0.001);
|
// matShadowProjection.scale(0.001, 0.001, 0.001);
|
||||||
|
|
||||||
Matrix4 matShadowView = Matrix4::LookAt(worldSpacefrustrumSliceBounds.center() - shadowLook, worldSpacefrustrumSliceBounds.center(), shadowUp);
|
Matrix4 matShadowView = Matrix4::LookAt(worldSpacefrustrumSliceBounds.center() - shadowLook, worldSpacefrustrumSliceBounds.center(), shadowUp);
|
||||||
Matrix4 matShadowProjection = Matrix4();
|
Matrix4 matShadowProjection = Matrix4();
|
||||||
AABB shadowSpaceFrustrumSliceBounds = AABB(worldSpacefrustrumSliceBounds.min, worldSpacefrustrumSliceBounds.max, Matrix4::Invert(matShadowProjection));
|
AABB shadowSpaceFrustrumSliceBounds = AABB::Create(worldSpacefrustrumSliceBounds.min, worldSpacefrustrumSliceBounds.max, Matrix4::Invert(matShadowProjection));
|
||||||
AABB shadowSpaceSceneBounds = AABB(getScene().getRootOctreeBounds().min, getScene().getRootOctreeBounds().max, Matrix4::Invert(matShadowProjection));
|
AABB shadowSpaceSceneBounds = AABB::Create(getScene().getRootOctreeBounds().min, getScene().getRootOctreeBounds().max, Matrix4::Invert(matShadowProjection));
|
||||||
if(shadowSpaceSceneBounds.min.z < shadowSpaceFrustrumSliceBounds.min.z) shadowSpaceFrustrumSliceBounds.min.z = shadowSpaceSceneBounds.min.z; // Include any potential shadow casters that are outside the view frustrum
|
if(shadowSpaceSceneBounds.min.z < shadowSpaceFrustrumSliceBounds.min.z) shadowSpaceFrustrumSliceBounds.min.z = shadowSpaceSceneBounds.min.z; // Include any potential shadow casters that are outside the view frustrum
|
||||||
matShadowProjection.scale(1.0f / shadowSpaceFrustrumSliceBounds.size().x, 1.0f / shadowSpaceFrustrumSliceBounds.size().y, 1.0f / shadowSpaceFrustrumSliceBounds.size().z);
|
matShadowProjection.scale(1.0f / shadowSpaceFrustrumSliceBounds.size().x, 1.0f / shadowSpaceFrustrumSliceBounds.size().y, 1.0f / shadowSpaceFrustrumSliceBounds.size().z);
|
||||||
|
|
||||||
Matrix4 matBias;
|
Matrix4 matBias;
|
||||||
matBias.bias();
|
matBias.bias();
|
||||||
matShadowProjection *= matBias;
|
matShadowProjection *= matBias;
|
||||||
|
|
||||||
KRViewport newShadowViewport = KRViewport(Vector2(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection);
|
KRViewport newShadowViewport = KRViewport(Vector2::Create(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection);
|
||||||
AABB prevShadowBounds = AABB(-Vector3::One(), Vector3::One(), Matrix4::Invert(m_shadowViewports[iShadow].getViewProjectionMatrix()));
|
AABB prevShadowBounds = AABB::Create(-Vector3::One(), Vector3::One(), Matrix4::Invert(m_shadowViewports[iShadow].getViewProjectionMatrix()));
|
||||||
AABB minimumShadowBounds = AABB(-Vector3::One(), Vector3::One(), Matrix4::Invert(newShadowViewport.getViewProjectionMatrix()));
|
AABB minimumShadowBounds = AABB::Create(-Vector3::One(), Vector3::One(), Matrix4::Invert(newShadowViewport.getViewProjectionMatrix()));
|
||||||
minimumShadowBounds.scale(1.0f / KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
|
minimumShadowBounds.scale(1.0f / KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
|
||||||
if(!prevShadowBounds.contains(minimumShadowBounds) || !shadowValid[iShadow] || true) { // FINDME, HACK - Re-generating the shadow map every frame. This should only be needed if the shadow contains non-static geometry
|
if(!prevShadowBounds.contains(minimumShadowBounds) || !shadowValid[iShadow] || true) { // FINDME, HACK - Re-generating the shadow map every frame. This should only be needed if the shadow contains non-static geometry
|
||||||
m_shadowViewports[iShadow] = newShadowViewport;
|
m_shadowViewports[iShadow] = newShadowViewport;
|
||||||
shadowValid[iShadow] = false;
|
shadowValid[iShadow] = false;
|
||||||
fprintf(stderr, "Kraken - Generate shadow maps...\n");
|
fprintf(stderr, "Kraken - Generate shadow maps...\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRDirectionalLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
|
void KRDirectionalLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
|
||||||
|
|
||||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||||
|
|
||||||
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) {
|
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) {
|
||||||
// Lights are rendered on the second pass of the deferred renderer
|
// Lights are rendered on the second pass of the deferred renderer
|
||||||
|
|
||||||
std::vector<KRDirectionalLight *> this_light;
|
std::vector<KRDirectionalLight *> this_light;
|
||||||
this_light.push_back(this);
|
this_light.push_back(this);
|
||||||
|
|
||||||
Matrix4 matModelViewInverseTranspose = viewport.getViewMatrix() * getModelMatrix();
|
Matrix4 matModelViewInverseTranspose = viewport.getViewMatrix() * getModelMatrix();
|
||||||
matModelViewInverseTranspose.transpose();
|
matModelViewInverseTranspose.transpose();
|
||||||
matModelViewInverseTranspose.invert();
|
matModelViewInverseTranspose.invert();
|
||||||
|
|
||||||
Vector3 light_direction_view_space = getWorldLightDirection();
|
Vector3 light_direction_view_space = getWorldLightDirection();
|
||||||
light_direction_view_space = Matrix4::Dot(matModelViewInverseTranspose, light_direction_view_space);
|
light_direction_view_space = Matrix4::Dot(matModelViewInverseTranspose, light_direction_view_space);
|
||||||
light_direction_view_space.normalize();
|
light_direction_view_space.normalize();
|
||||||
|
|
||||||
KRShader *pShader = getContext().getShaderManager()->getShader("light_directional", pCamera, std::vector<KRPointLight *>(), this_light, std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
KRShader *pShader = getContext().getShaderManager()->getShader("light_directional", pCamera, std::vector<KRPointLight *>(), this_light, std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), std::vector<KRPointLight *>(), this_light, std::vector<KRSpotLight *>(), 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), std::vector<KRPointLight *>(), this_light, std::vector<KRSpotLight *>(), 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||||
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_DIRECTION_VIEW_SPACE, light_direction_view_space);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_DIRECTION_VIEW_SPACE, light_direction_view_space);
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color);
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f);
|
||||||
|
|
||||||
// Disable z-buffer write
|
// Disable z-buffer write
|
||||||
GLDEBUG(glDepthMask(GL_FALSE));
|
GLDEBUG(glDepthMask(GL_FALSE));
|
||||||
|
|
||||||
// Disable z-buffer test
|
// Disable z-buffer test
|
||||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||||
|
|
||||||
// Render a full screen quad
|
// Render a full screen quad
|
||||||
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
||||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AABB KRDirectionalLight::getBounds()
|
AABB KRDirectionalLight::getBounds()
|
||||||
{
|
{
|
||||||
return AABB::Infinite();
|
return AABB::Infinite();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
#include "KRHelpers.h"
|
#include "KRHelpers.h"
|
||||||
using namespace kraken;
|
using namespace kraken;
|
||||||
|
|
||||||
|
#include "hydra.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
#ifndef KRHELPERS_H
|
#ifndef KRHELPERS_H
|
||||||
#define KRHELPERS_H
|
#define KRHELPERS_H
|
||||||
|
|
||||||
|
#include "vector2.h"
|
||||||
|
#include "vector3.h"
|
||||||
|
#include "matrix4.h"
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#elif defined(__linux__) || defined(__unix__) || defined(__posix__)
|
#elif defined(__linux__) || defined(__unix__) || defined(__posix__)
|
||||||
|
|||||||
@@ -1,173 +1,173 @@
|
|||||||
//
|
//
|
||||||
// KRLODGroup.cpp
|
// KRLODGroup.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 2012-12-06.
|
// Created by Kearwood Gilbert on 2012-12-06.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KRLODGroup.h"
|
#include "KRLODGroup.h"
|
||||||
#include "KRLODSet.h"
|
#include "KRLODSet.h"
|
||||||
#include "KRContext.h"
|
#include "KRContext.h"
|
||||||
|
|
||||||
KRLODGroup::KRLODGroup(KRScene &scene, std::string name) : KRNode(scene, name)
|
KRLODGroup::KRLODGroup(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||||
{
|
{
|
||||||
m_min_distance = 0.0f;
|
m_min_distance = 0.0f;
|
||||||
m_max_distance = 0.0f;
|
m_max_distance = 0.0f;
|
||||||
m_reference = AABB(Vector3::Zero(), Vector3::Zero());
|
m_reference = AABB::Create(Vector3::Zero(), Vector3::Zero());
|
||||||
m_use_world_units = true;
|
m_use_world_units = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRLODGroup::~KRLODGroup()
|
KRLODGroup::~KRLODGroup()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KRLODGroup::getElementName() {
|
std::string KRLODGroup::getElementName() {
|
||||||
return "lod_group";
|
return "lod_group";
|
||||||
}
|
}
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRLODGroup::saveXML( tinyxml2::XMLNode *parent)
|
tinyxml2::XMLElement *KRLODGroup::saveXML( tinyxml2::XMLNode *parent)
|
||||||
{
|
{
|
||||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||||
e->SetAttribute("min_distance", m_min_distance);
|
e->SetAttribute("min_distance", m_min_distance);
|
||||||
e->SetAttribute("max_distance", m_max_distance);
|
e->SetAttribute("max_distance", m_max_distance);
|
||||||
|
|
||||||
e->SetAttribute("reference_min_x", m_reference.min.x);
|
e->SetAttribute("reference_min_x", m_reference.min.x);
|
||||||
e->SetAttribute("reference_min_y", m_reference.min.y);
|
e->SetAttribute("reference_min_y", m_reference.min.y);
|
||||||
e->SetAttribute("reference_min_z", m_reference.min.z);
|
e->SetAttribute("reference_min_z", m_reference.min.z);
|
||||||
|
|
||||||
|
|
||||||
e->SetAttribute("reference_max_x", m_reference.max.x);
|
e->SetAttribute("reference_max_x", m_reference.max.x);
|
||||||
e->SetAttribute("reference_max_y", m_reference.max.y);
|
e->SetAttribute("reference_max_y", m_reference.max.y);
|
||||||
e->SetAttribute("reference_max_z", m_reference.max.z);
|
e->SetAttribute("reference_max_z", m_reference.max.z);
|
||||||
|
|
||||||
e->SetAttribute("use_world_units", m_use_world_units ? "true" : "false");
|
e->SetAttribute("use_world_units", m_use_world_units ? "true" : "false");
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRLODGroup::loadXML(tinyxml2::XMLElement *e)
|
void KRLODGroup::loadXML(tinyxml2::XMLElement *e)
|
||||||
{
|
{
|
||||||
KRNode::loadXML(e);
|
KRNode::loadXML(e);
|
||||||
|
|
||||||
m_min_distance = 0.0f;
|
m_min_distance = 0.0f;
|
||||||
if(e->QueryFloatAttribute("min_distance", &m_min_distance) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("min_distance", &m_min_distance) != tinyxml2::XML_SUCCESS) {
|
||||||
m_min_distance = 0.0f;
|
m_min_distance = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_max_distance = 0.0f;
|
m_max_distance = 0.0f;
|
||||||
if(e->QueryFloatAttribute("max_distance", &m_max_distance) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("max_distance", &m_max_distance) != tinyxml2::XML_SUCCESS) {
|
||||||
m_max_distance = 0.0f;
|
m_max_distance = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float x=0.0f, y=0.0f, z=0.0f;
|
float x=0.0f, y=0.0f, z=0.0f;
|
||||||
if(e->QueryFloatAttribute("reference_min_x", &x) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("reference_min_x", &x) != tinyxml2::XML_SUCCESS) {
|
||||||
x = 0.0f;
|
x = 0.0f;
|
||||||
}
|
}
|
||||||
if(e->QueryFloatAttribute("reference_min_y", &y) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("reference_min_y", &y) != tinyxml2::XML_SUCCESS) {
|
||||||
y = 0.0f;
|
y = 0.0f;
|
||||||
}
|
}
|
||||||
if(e->QueryFloatAttribute("reference_min_z", &z) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("reference_min_z", &z) != tinyxml2::XML_SUCCESS) {
|
||||||
z = 0.0f;
|
z = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_reference.min = Vector3(x,y,z);
|
m_reference.min = Vector3::Create(x,y,z);
|
||||||
|
|
||||||
x=0.0f; y=0.0f; z=0.0f;
|
x=0.0f; y=0.0f; z=0.0f;
|
||||||
if(e->QueryFloatAttribute("reference_max_x", &x) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("reference_max_x", &x) != tinyxml2::XML_SUCCESS) {
|
||||||
x = 0.0f;
|
x = 0.0f;
|
||||||
}
|
}
|
||||||
if(e->QueryFloatAttribute("reference_max_y", &y) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("reference_max_y", &y) != tinyxml2::XML_SUCCESS) {
|
||||||
y = 0.0f;
|
y = 0.0f;
|
||||||
}
|
}
|
||||||
if(e->QueryFloatAttribute("reference_max_z", &z) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("reference_max_z", &z) != tinyxml2::XML_SUCCESS) {
|
||||||
z = 0.0f;
|
z = 0.0f;
|
||||||
}
|
}
|
||||||
m_reference.max = Vector3(x,y,z);
|
m_reference.max = Vector3::Create(x,y,z);
|
||||||
|
|
||||||
m_use_world_units = true;
|
m_use_world_units = true;
|
||||||
if(e->QueryBoolAttribute("use_world_units", &m_use_world_units) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryBoolAttribute("use_world_units", &m_use_world_units) != tinyxml2::XML_SUCCESS) {
|
||||||
m_use_world_units = true;
|
m_use_world_units = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const AABB &KRLODGroup::getReference() const
|
const AABB &KRLODGroup::getReference() const
|
||||||
{
|
{
|
||||||
return m_reference;
|
return m_reference;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRLODGroup::setReference(const AABB &reference)
|
void KRLODGroup::setReference(const AABB &reference)
|
||||||
{
|
{
|
||||||
m_reference = reference;
|
m_reference = reference;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRNode::LodVisibility KRLODGroup::calcLODVisibility(const KRViewport &viewport)
|
KRNode::LodVisibility KRLODGroup::calcLODVisibility(const KRViewport &viewport)
|
||||||
{
|
{
|
||||||
if(m_min_distance == 0 && m_max_distance == 0) {
|
if(m_min_distance == 0 && m_max_distance == 0) {
|
||||||
return LOD_VISIBILITY_VISIBLE;
|
return LOD_VISIBILITY_VISIBLE;
|
||||||
} else {
|
} else {
|
||||||
float lod_bias = viewport.getLODBias();
|
float lod_bias = viewport.getLODBias();
|
||||||
lod_bias = pow(2.0f, -lod_bias);
|
lod_bias = pow(2.0f, -lod_bias);
|
||||||
|
|
||||||
// Compare using squared distances as sqrt is expensive
|
// Compare using squared distances as sqrt is expensive
|
||||||
float sqr_distance;
|
float sqr_distance;
|
||||||
float sqr_prestream_distance;
|
float sqr_prestream_distance;
|
||||||
|
|
||||||
Vector3 world_camera_position = viewport.getCameraPosition();
|
Vector3 world_camera_position = viewport.getCameraPosition();
|
||||||
Vector3 local_camera_position = worldToLocal(world_camera_position);
|
Vector3 local_camera_position = worldToLocal(world_camera_position);
|
||||||
Vector3 local_reference_point = m_reference.nearestPoint(local_camera_position);
|
Vector3 local_reference_point = m_reference.nearestPoint(local_camera_position);
|
||||||
|
|
||||||
if(m_use_world_units) {
|
if(m_use_world_units) {
|
||||||
Vector3 world_reference_point = localToWorld(local_reference_point);
|
Vector3 world_reference_point = localToWorld(local_reference_point);
|
||||||
sqr_distance = (world_camera_position - world_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
|
sqr_distance = (world_camera_position - world_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
|
||||||
sqr_prestream_distance = getContext().KRENGINE_PRESTREAM_DISTANCE * getContext().KRENGINE_PRESTREAM_DISTANCE;
|
sqr_prestream_distance = getContext().KRENGINE_PRESTREAM_DISTANCE * getContext().KRENGINE_PRESTREAM_DISTANCE;
|
||||||
} else {
|
} else {
|
||||||
sqr_distance = (local_camera_position - local_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
|
sqr_distance = (local_camera_position - local_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
|
||||||
|
|
||||||
Vector3 world_reference_point = localToWorld(local_reference_point);
|
Vector3 world_reference_point = localToWorld(local_reference_point);
|
||||||
sqr_prestream_distance = worldToLocal(Vector3::Normalize(world_reference_point - world_camera_position) * getContext().KRENGINE_PRESTREAM_DISTANCE).sqrMagnitude(); // TODO, FINDME - Optimize with precalc?
|
sqr_prestream_distance = worldToLocal(Vector3::Normalize(world_reference_point - world_camera_position) * getContext().KRENGINE_PRESTREAM_DISTANCE).sqrMagnitude(); // TODO, FINDME - Optimize with precalc?
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float sqr_min_visible_distance = m_min_distance * m_min_distance;
|
float sqr_min_visible_distance = m_min_distance * m_min_distance;
|
||||||
float sqr_max_visible_distance = m_max_distance * m_max_distance;
|
float sqr_max_visible_distance = m_max_distance * m_max_distance;
|
||||||
if((sqr_distance >= sqr_min_visible_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance || m_max_distance == 0)) {
|
if((sqr_distance >= sqr_min_visible_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance || m_max_distance == 0)) {
|
||||||
return LOD_VISIBILITY_VISIBLE;
|
return LOD_VISIBILITY_VISIBLE;
|
||||||
} else if((sqr_distance >= sqr_min_visible_distance - sqr_prestream_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance + sqr_prestream_distance || m_max_distance == 0)) {
|
} else if((sqr_distance >= sqr_min_visible_distance - sqr_prestream_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance + sqr_prestream_distance || m_max_distance == 0)) {
|
||||||
return LOD_VISIBILITY_PRESTREAM;
|
return LOD_VISIBILITY_PRESTREAM;
|
||||||
} else {
|
} else {
|
||||||
return LOD_VISIBILITY_HIDDEN;
|
return LOD_VISIBILITY_HIDDEN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float KRLODGroup::getMinDistance()
|
float KRLODGroup::getMinDistance()
|
||||||
{
|
{
|
||||||
return m_min_distance;
|
return m_min_distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
float KRLODGroup::getMaxDistance()
|
float KRLODGroup::getMaxDistance()
|
||||||
{
|
{
|
||||||
return m_max_distance;
|
return m_max_distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRLODGroup::setMinDistance(float min_distance)
|
void KRLODGroup::setMinDistance(float min_distance)
|
||||||
{
|
{
|
||||||
m_min_distance = min_distance;
|
m_min_distance = min_distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRLODGroup::setMaxDistance(float max_distance)
|
void KRLODGroup::setMaxDistance(float max_distance)
|
||||||
{
|
{
|
||||||
m_max_distance = max_distance;
|
m_max_distance = max_distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRLODGroup::setUseWorldUnits(bool use_world_units)
|
void KRLODGroup::setUseWorldUnits(bool use_world_units)
|
||||||
{
|
{
|
||||||
m_use_world_units = use_world_units;
|
m_use_world_units = use_world_units;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KRLODGroup::getUseWorldUnits() const
|
bool KRLODGroup::getUseWorldUnits() const
|
||||||
{
|
{
|
||||||
return m_use_world_units;
|
return m_use_world_units;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,485 +1,485 @@
|
|||||||
//
|
//
|
||||||
// KRLight.cpp
|
// KRLight.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 12-04-05.
|
// Created by Kearwood Gilbert on 12-04-05.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
#include "KRLight.h"
|
#include "KRLight.h"
|
||||||
|
|
||||||
#include "KRNode.h"
|
#include "KRNode.h"
|
||||||
#include "KRCamera.h"
|
#include "KRCamera.h"
|
||||||
#include "KRContext.h"
|
#include "KRContext.h"
|
||||||
|
|
||||||
#include "KRShaderManager.h"
|
#include "KRShaderManager.h"
|
||||||
#include "KRShader.h"
|
#include "KRShader.h"
|
||||||
#include "KRStockGeometry.h"
|
#include "KRStockGeometry.h"
|
||||||
#include "KRDirectionalLight.h"
|
#include "KRDirectionalLight.h"
|
||||||
#include "KRSpotLight.h"
|
#include "KRSpotLight.h"
|
||||||
#include "KRPointLight.h"
|
#include "KRPointLight.h"
|
||||||
|
|
||||||
|
|
||||||
KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name)
|
KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||||
{
|
{
|
||||||
m_intensity = 1.0f;
|
m_intensity = 1.0f;
|
||||||
m_dust_particle_intensity = 1.0f;
|
m_dust_particle_intensity = 1.0f;
|
||||||
m_color = Vector3::One();
|
m_color = Vector3::One();
|
||||||
m_flareTexture = "";
|
m_flareTexture = "";
|
||||||
m_pFlareTexture = NULL;
|
m_pFlareTexture = NULL;
|
||||||
m_flareSize = 0.0;
|
m_flareSize = 0.0f;
|
||||||
m_flareOcclusionSize = 0.05;
|
m_flareOcclusionSize = 0.05f;
|
||||||
m_casts_shadow = true;
|
m_casts_shadow = true;
|
||||||
m_light_shafts = true;
|
m_light_shafts = true;
|
||||||
m_dust_particle_density = 0.1f;
|
m_dust_particle_density = 0.1f;
|
||||||
m_dust_particle_size = 1.0f;
|
m_dust_particle_size = 1.0f;
|
||||||
m_occlusionQuery = 0;
|
m_occlusionQuery = 0;
|
||||||
|
|
||||||
// Initialize shadow buffers
|
// Initialize shadow buffers
|
||||||
m_cShadowBuffers = 0;
|
m_cShadowBuffers = 0;
|
||||||
for(int iBuffer=0; iBuffer < KRENGINE_MAX_SHADOW_BUFFERS; iBuffer++) {
|
for(int iBuffer=0; iBuffer < KRENGINE_MAX_SHADOW_BUFFERS; iBuffer++) {
|
||||||
shadowFramebuffer[iBuffer] = 0;
|
shadowFramebuffer[iBuffer] = 0;
|
||||||
shadowDepthTexture[iBuffer] = 0;
|
shadowDepthTexture[iBuffer] = 0;
|
||||||
shadowValid[iBuffer] = false;
|
shadowValid[iBuffer] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KRLight::~KRLight()
|
KRLight::~KRLight()
|
||||||
{
|
{
|
||||||
if(m_occlusionQuery) {
|
if(m_occlusionQuery) {
|
||||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
||||||
m_occlusionQuery = 0;
|
m_occlusionQuery = 0;
|
||||||
}
|
}
|
||||||
allocateShadowBuffers(0);
|
allocateShadowBuffers(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRLight::saveXML( tinyxml2::XMLNode *parent)
|
tinyxml2::XMLElement *KRLight::saveXML( tinyxml2::XMLNode *parent)
|
||||||
{
|
{
|
||||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||||
e->SetAttribute("intensity", m_intensity);
|
e->SetAttribute("intensity", m_intensity);
|
||||||
e->SetAttribute("color_r", m_color.x);
|
e->SetAttribute("color_r", m_color.x);
|
||||||
e->SetAttribute("color_g", m_color.y);
|
e->SetAttribute("color_g", m_color.y);
|
||||||
e->SetAttribute("color_b", m_color.z);
|
e->SetAttribute("color_b", m_color.z);
|
||||||
e->SetAttribute("decay_start", m_decayStart);
|
e->SetAttribute("decay_start", m_decayStart);
|
||||||
e->SetAttribute("flare_size", m_flareSize);
|
e->SetAttribute("flare_size", m_flareSize);
|
||||||
e->SetAttribute("flare_occlusion_size", m_flareOcclusionSize);
|
e->SetAttribute("flare_occlusion_size", m_flareOcclusionSize);
|
||||||
e->SetAttribute("flare_texture", m_flareTexture.c_str());
|
e->SetAttribute("flare_texture", m_flareTexture.c_str());
|
||||||
e->SetAttribute("casts_shadow", m_casts_shadow ? "true" : "false");
|
e->SetAttribute("casts_shadow", m_casts_shadow ? "true" : "false");
|
||||||
e->SetAttribute("light_shafts", m_light_shafts ? "true" : "false");
|
e->SetAttribute("light_shafts", m_light_shafts ? "true" : "false");
|
||||||
e->SetAttribute("dust_particle_density", m_dust_particle_density);
|
e->SetAttribute("dust_particle_density", m_dust_particle_density);
|
||||||
e->SetAttribute("dust_particle_size", m_dust_particle_size);
|
e->SetAttribute("dust_particle_size", m_dust_particle_size);
|
||||||
e->SetAttribute("dust_particle_intensity", m_dust_particle_intensity);
|
e->SetAttribute("dust_particle_intensity", m_dust_particle_intensity);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRLight::loadXML(tinyxml2::XMLElement *e) {
|
void KRLight::loadXML(tinyxml2::XMLElement *e) {
|
||||||
KRNode::loadXML(e);
|
KRNode::loadXML(e);
|
||||||
float x=1.0f,y=1.0f,z=1.0f;
|
float x=1.0f,y=1.0f,z=1.0f;
|
||||||
if(e->QueryFloatAttribute("color_r", &x) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("color_r", &x) != tinyxml2::XML_SUCCESS) {
|
||||||
x = 1.0;
|
x = 1.0;
|
||||||
}
|
}
|
||||||
if(e->QueryFloatAttribute("color_g", &y) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("color_g", &y) != tinyxml2::XML_SUCCESS) {
|
||||||
y = 1.0;
|
y = 1.0;
|
||||||
}
|
}
|
||||||
if(e->QueryFloatAttribute("color_b", &z) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("color_b", &z) != tinyxml2::XML_SUCCESS) {
|
||||||
z = 1.0;
|
z = 1.0;
|
||||||
}
|
}
|
||||||
m_color = Vector3(x,y,z);
|
m_color = Vector3::Create(x,y,z);
|
||||||
|
|
||||||
if(e->QueryFloatAttribute("intensity", &m_intensity) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("intensity", &m_intensity) != tinyxml2::XML_SUCCESS) {
|
||||||
m_intensity = 100.0;
|
m_intensity = 100.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(e->QueryFloatAttribute("decay_start", &m_decayStart) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("decay_start", &m_decayStart) != tinyxml2::XML_SUCCESS) {
|
||||||
m_decayStart = 0.0;
|
m_decayStart = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(e->QueryFloatAttribute("flare_size", &m_flareSize) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("flare_size", &m_flareSize) != tinyxml2::XML_SUCCESS) {
|
||||||
m_flareSize = 0.0;
|
m_flareSize = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(e->QueryFloatAttribute("flare_occlusion_size", &m_flareOcclusionSize) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("flare_occlusion_size", &m_flareOcclusionSize) != tinyxml2::XML_SUCCESS) {
|
||||||
m_flareOcclusionSize = 0.05;
|
m_flareOcclusionSize = 0.05f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(e->QueryBoolAttribute("casts_shadow", &m_casts_shadow) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryBoolAttribute("casts_shadow", &m_casts_shadow) != tinyxml2::XML_SUCCESS) {
|
||||||
m_casts_shadow = true;
|
m_casts_shadow = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(e->QueryBoolAttribute("light_shafts", &m_light_shafts) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryBoolAttribute("light_shafts", &m_light_shafts) != tinyxml2::XML_SUCCESS) {
|
||||||
m_light_shafts = true;
|
m_light_shafts = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_dust_particle_density = 0.1f;
|
m_dust_particle_density = 0.1f;
|
||||||
if(e->QueryFloatAttribute("dust_particle_density", &m_dust_particle_density) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("dust_particle_density", &m_dust_particle_density) != tinyxml2::XML_SUCCESS) {
|
||||||
m_dust_particle_density = 0.1f;
|
m_dust_particle_density = 0.1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_dust_particle_size = 1.0f;
|
m_dust_particle_size = 1.0f;
|
||||||
if(e->QueryFloatAttribute("dust_particle_size", &m_dust_particle_size) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("dust_particle_size", &m_dust_particle_size) != tinyxml2::XML_SUCCESS) {
|
||||||
m_dust_particle_size = 1.0f;
|
m_dust_particle_size = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_dust_particle_intensity = 1.0f;
|
m_dust_particle_intensity = 1.0f;
|
||||||
if(e->QueryFloatAttribute("dust_particle_intensity", &m_dust_particle_intensity) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("dust_particle_intensity", &m_dust_particle_intensity) != tinyxml2::XML_SUCCESS) {
|
||||||
m_dust_particle_intensity = 1.0f;
|
m_dust_particle_intensity = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *szFlareTexture = e->Attribute("flare_texture");
|
const char *szFlareTexture = e->Attribute("flare_texture");
|
||||||
if(szFlareTexture) {
|
if(szFlareTexture) {
|
||||||
m_flareTexture = szFlareTexture;
|
m_flareTexture = szFlareTexture;
|
||||||
} else {
|
} else {
|
||||||
m_flareTexture = "";
|
m_flareTexture = "";
|
||||||
}
|
}
|
||||||
m_pFlareTexture = NULL;
|
m_pFlareTexture = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRLight::setFlareTexture(std::string flare_texture) {
|
void KRLight::setFlareTexture(std::string flare_texture) {
|
||||||
m_flareTexture = flare_texture;
|
m_flareTexture = flare_texture;
|
||||||
m_pFlareTexture = NULL;
|
m_pFlareTexture = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRLight::setFlareSize(float flare_size) {
|
void KRLight::setFlareSize(float flare_size) {
|
||||||
m_flareSize = flare_size;
|
m_flareSize = flare_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRLight::setFlareOcclusionSize(float occlusion_size) {
|
void KRLight::setFlareOcclusionSize(float occlusion_size) {
|
||||||
m_flareOcclusionSize = occlusion_size;
|
m_flareOcclusionSize = occlusion_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRLight::setIntensity(float intensity) {
|
void KRLight::setIntensity(float intensity) {
|
||||||
m_intensity = intensity;
|
m_intensity = intensity;
|
||||||
}
|
}
|
||||||
float KRLight::getIntensity() {
|
float KRLight::getIntensity() {
|
||||||
return m_intensity;
|
return m_intensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vector3 &KRLight::getColor() {
|
const Vector3 &KRLight::getColor() {
|
||||||
return m_color;
|
return m_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRLight::setColor(const Vector3 &color) {
|
void KRLight::setColor(const Vector3 &color) {
|
||||||
m_color = color;
|
m_color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRLight::setDecayStart(float decayStart) {
|
void KRLight::setDecayStart(float decayStart) {
|
||||||
m_decayStart = decayStart;
|
m_decayStart = decayStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
float KRLight::getDecayStart() {
|
float KRLight::getDecayStart() {
|
||||||
return m_decayStart;
|
return m_decayStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
|
void KRLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
|
||||||
|
|
||||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||||
|
|
||||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && (pCamera->settings.volumetric_environment_enable || pCamera->settings.dust_particle_enable || (pCamera->settings.m_cShadowBuffers > 0 && m_casts_shadow))) {
|
if(renderPass == KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && (pCamera->settings.volumetric_environment_enable || pCamera->settings.dust_particle_enable || (pCamera->settings.m_cShadowBuffers > 0 && m_casts_shadow))) {
|
||||||
allocateShadowBuffers(configureShadowBufferViewports(viewport));
|
allocateShadowBuffers(configureShadowBufferViewports(viewport));
|
||||||
renderShadowBuffers(pCamera);
|
renderShadowBuffers(pCamera);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES && pCamera->settings.dust_particle_enable) {
|
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES && pCamera->settings.dust_particle_enable) {
|
||||||
// Render brownian particles for dust floating in air
|
// Render brownian particles for dust floating in air
|
||||||
if(m_cShadowBuffers >= 1 && shadowValid[0] && m_dust_particle_density > 0.0f && m_dust_particle_size > 0.0f && m_dust_particle_intensity > 0.0f) {
|
if(m_cShadowBuffers >= 1 && shadowValid[0] && m_dust_particle_density > 0.0f && m_dust_particle_size > 0.0f && m_dust_particle_intensity > 0.0f) {
|
||||||
|
|
||||||
if(viewport.visible(getBounds()) || true) { // FINDME, HACK need to remove "|| true"?
|
if(viewport.visible(getBounds()) || true) { // FINDME, HACK need to remove "|| true"?
|
||||||
|
|
||||||
float particle_range = 600.0f;
|
float particle_range = 600.0f;
|
||||||
|
|
||||||
int particle_count = m_dust_particle_density * pow(particle_range, 3);
|
int particle_count = m_dust_particle_density * pow(particle_range, 3);
|
||||||
if(particle_count > KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES) particle_count = KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES;
|
if(particle_count > KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES) particle_count = KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES;
|
||||||
|
|
||||||
// Enable z-buffer test
|
// Enable z-buffer test
|
||||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||||
|
|
||||||
Matrix4 particleModelMatrix;
|
Matrix4 particleModelMatrix;
|
||||||
particleModelMatrix.scale(particle_range); // Scale the box symetrically to ensure that we don't have an uneven distribution of particles for different angles of the view frustrum
|
particleModelMatrix.scale(particle_range); // Scale the box symetrically to ensure that we don't have an uneven distribution of particles for different angles of the view frustrum
|
||||||
particleModelMatrix.translate(viewport.getCameraPosition());
|
particleModelMatrix.translate(viewport.getCameraPosition());
|
||||||
|
|
||||||
std::vector<KRDirectionalLight *> this_directional_light;
|
std::vector<KRDirectionalLight *> this_directional_light;
|
||||||
std::vector<KRSpotLight *> this_spot_light;
|
std::vector<KRSpotLight *> this_spot_light;
|
||||||
std::vector<KRPointLight *> this_point_light;
|
std::vector<KRPointLight *> this_point_light;
|
||||||
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
|
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
|
||||||
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
|
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
|
||||||
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
|
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
|
||||||
if(directional_light) {
|
if(directional_light) {
|
||||||
this_directional_light.push_back(directional_light);
|
this_directional_light.push_back(directional_light);
|
||||||
}
|
}
|
||||||
if(spot_light) {
|
if(spot_light) {
|
||||||
this_spot_light.push_back(spot_light);
|
this_spot_light.push_back(spot_light);
|
||||||
}
|
}
|
||||||
if(point_light) {
|
if(point_light) {
|
||||||
this_point_light.push_back(point_light);
|
this_point_light.push_back(point_light);
|
||||||
}
|
}
|
||||||
|
|
||||||
KRShader *pParticleShader = m_pContext->getShaderManager()->getShader("dust_particle", pCamera, this_point_light, this_directional_light, this_spot_light, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
KRShader *pParticleShader = m_pContext->getShaderManager()->getShader("dust_particle", pCamera, this_point_light, this_directional_light, this_spot_light, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
||||||
|
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pParticleShader, viewport, particleModelMatrix, this_point_light, this_directional_light, this_spot_light, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
if(getContext().getShaderManager()->selectShader(*pCamera, pParticleShader, viewport, particleModelMatrix, this_point_light, this_directional_light, this_spot_light, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||||
|
|
||||||
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color * pCamera->settings.dust_particle_intensity * m_dust_particle_intensity * m_intensity);
|
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color * pCamera->settings.dust_particle_intensity * m_dust_particle_intensity * m_intensity);
|
||||||
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_PARTICLE_ORIGIN, Matrix4::DotWDiv(Matrix4::Invert(particleModelMatrix), Vector3::Zero()));
|
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_PARTICLE_ORIGIN, Matrix4::DotWDiv(Matrix4::Invert(particleModelMatrix), Vector3::Zero()));
|
||||||
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_dust_particle_size);
|
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_dust_particle_size);
|
||||||
|
|
||||||
KRDataBlock particle_index_data;
|
KRDataBlock particle_index_data;
|
||||||
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getRandomParticles(), particle_index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), true, 1.0f);
|
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getRandomParticles(), particle_index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), true, 1.0f);
|
||||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
|
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && pCamera->settings.volumetric_environment_enable && m_light_shafts) {
|
if(renderPass == KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && pCamera->settings.volumetric_environment_enable && m_light_shafts) {
|
||||||
std::string shader_name = pCamera->settings.volumetric_environment_downsample != 0 ? "volumetric_fog_downsampled" : "volumetric_fog";
|
std::string shader_name = pCamera->settings.volumetric_environment_downsample != 0 ? "volumetric_fog_downsampled" : "volumetric_fog";
|
||||||
|
|
||||||
std::vector<KRDirectionalLight *> this_directional_light;
|
std::vector<KRDirectionalLight *> this_directional_light;
|
||||||
std::vector<KRSpotLight *> this_spot_light;
|
std::vector<KRSpotLight *> this_spot_light;
|
||||||
std::vector<KRPointLight *> this_point_light;
|
std::vector<KRPointLight *> this_point_light;
|
||||||
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
|
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
|
||||||
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
|
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
|
||||||
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
|
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
|
||||||
if(directional_light) {
|
if(directional_light) {
|
||||||
this_directional_light.push_back(directional_light);
|
this_directional_light.push_back(directional_light);
|
||||||
}
|
}
|
||||||
if(spot_light) {
|
if(spot_light) {
|
||||||
this_spot_light.push_back(spot_light);
|
this_spot_light.push_back(spot_light);
|
||||||
}
|
}
|
||||||
if(point_light) {
|
if(point_light) {
|
||||||
this_point_light.push_back(point_light);
|
this_point_light.push_back(point_light);
|
||||||
}
|
}
|
||||||
|
|
||||||
KRShader *pFogShader = m_pContext->getShaderManager()->getShader(shader_name, pCamera, this_point_light, this_directional_light, this_spot_light, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_ADDITIVE_PARTICLES);
|
KRShader *pFogShader = m_pContext->getShaderManager()->getShader(shader_name, pCamera, this_point_light, this_directional_light, this_spot_light, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_ADDITIVE_PARTICLES);
|
||||||
|
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pFogShader, viewport, Matrix4(), this_point_light, this_directional_light, this_spot_light, 0, KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
if(getContext().getShaderManager()->selectShader(*pCamera, pFogShader, viewport, Matrix4(), this_point_light, this_directional_light, this_spot_light, 0, KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||||
int slice_count = (int)(pCamera->settings.volumetric_environment_quality * 495.0) + 5;
|
int slice_count = (int)(pCamera->settings.volumetric_environment_quality * 495.0) + 5;
|
||||||
|
|
||||||
float slice_near = -pCamera->settings.getPerspectiveNearZ();
|
float slice_near = -pCamera->settings.getPerspectiveNearZ();
|
||||||
float slice_far = -pCamera->settings.volumetric_environment_max_distance;
|
float slice_far = -pCamera->settings.volumetric_environment_max_distance;
|
||||||
float slice_spacing = (slice_far - slice_near) / slice_count;
|
float slice_spacing = (slice_far - slice_near) / slice_count;
|
||||||
|
|
||||||
pFogShader->setUniform(KRShader::KRENGINE_UNIFORM_SLICE_DEPTH_SCALE, Vector2(slice_near, slice_spacing));
|
pFogShader->setUniform(KRShader::KRENGINE_UNIFORM_SLICE_DEPTH_SCALE, Vector2::Create(slice_near, slice_spacing));
|
||||||
pFogShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, (m_color * pCamera->settings.volumetric_environment_intensity * m_intensity * -slice_spacing / 1000.0f));
|
pFogShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, (m_color * pCamera->settings.volumetric_environment_intensity * m_intensity * -slice_spacing / 1000.0f));
|
||||||
|
|
||||||
KRDataBlock index_data;
|
KRDataBlock index_data;
|
||||||
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getVolumetricLightingVertexes(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX), true, 1.0f);
|
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getVolumetricLightingVertexes(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX), true, 1.0f);
|
||||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, slice_count*6));
|
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, slice_count*6));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_PARTICLE_OCCLUSION) {
|
if(renderPass == KRNode::RENDER_PASS_PARTICLE_OCCLUSION) {
|
||||||
if(m_flareTexture.size() && m_flareSize > 0.0f) {
|
if(m_flareTexture.size() && m_flareSize > 0.0f) {
|
||||||
|
|
||||||
|
|
||||||
Matrix4 occlusion_test_sphere_matrix = Matrix4();
|
Matrix4 occlusion_test_sphere_matrix = Matrix4();
|
||||||
occlusion_test_sphere_matrix.scale(m_localScale * m_flareOcclusionSize);
|
occlusion_test_sphere_matrix.scale(m_localScale * m_flareOcclusionSize);
|
||||||
occlusion_test_sphere_matrix.translate(m_localTranslation);
|
occlusion_test_sphere_matrix.translate(m_localTranslation);
|
||||||
if(m_parentNode) {
|
if(m_parentNode) {
|
||||||
occlusion_test_sphere_matrix *= m_parentNode->getModelMatrix();
|
occlusion_test_sphere_matrix *= m_parentNode->getModelMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getContext().getShaderManager()->selectShader("occlusion_test", *pCamera, point_lights, directional_lights, spot_lights, 0, viewport, occlusion_test_sphere_matrix, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
if(getContext().getShaderManager()->selectShader("occlusion_test", *pCamera, point_lights, directional_lights, spot_lights, 0, viewport, occlusion_test_sphere_matrix, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||||
|
|
||||||
GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery));
|
GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery));
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
|
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
|
||||||
#else
|
#else
|
||||||
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
|
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
||||||
if(sphereModels.size()) {
|
if(sphereModels.size()) {
|
||||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "occlusion_test", 1.0f);
|
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "occlusion_test", 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
|
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
|
||||||
#else
|
#else
|
||||||
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
|
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
|
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
|
||||||
if(m_flareTexture.size() && m_flareSize > 0.0f) {
|
if(m_flareTexture.size() && m_flareSize > 0.0f) {
|
||||||
|
|
||||||
if(m_occlusionQuery) {
|
if(m_occlusionQuery) {
|
||||||
GLuint params = 0;
|
GLuint params = 0;
|
||||||
GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, ¶ms));
|
GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, ¶ms));
|
||||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
||||||
|
|
||||||
if(params) {
|
if(params) {
|
||||||
|
|
||||||
if(!m_pFlareTexture && m_flareTexture.size()) {
|
if(!m_pFlareTexture && m_flareTexture.size()) {
|
||||||
m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture);
|
m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pFlareTexture) {
|
if(m_pFlareTexture) {
|
||||||
// Disable z-buffer test
|
// Disable z-buffer test
|
||||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||||
|
|
||||||
// Render light flare on transparency pass
|
// Render light flare on transparency pass
|
||||||
KRShader *pShader = getContext().getShaderManager()->getShader("flare", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
KRShader *pShader = getContext().getShaderManager()->getShader("flare", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
||||||
|
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, 1.0f);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, 1.0f);
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_flareSize);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_flareSize);
|
||||||
m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture, 0.0f, KRTexture::TEXTURE_USAGE_LIGHT_FLARE);
|
m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture, 0.0f, KRTexture::TEXTURE_USAGE_LIGHT_FLARE);
|
||||||
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
||||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRLight::allocateShadowBuffers(int cBuffers) {
|
void KRLight::allocateShadowBuffers(int cBuffers) {
|
||||||
// First deallocate buffers no longer needed
|
// First deallocate buffers no longer needed
|
||||||
for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) {
|
for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) {
|
||||||
if (shadowDepthTexture[iShadow]) {
|
if (shadowDepthTexture[iShadow]) {
|
||||||
GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow));
|
GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow));
|
||||||
shadowDepthTexture[iShadow] = 0;
|
shadowDepthTexture[iShadow] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shadowFramebuffer[iShadow]) {
|
if (shadowFramebuffer[iShadow]) {
|
||||||
GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow));
|
GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow));
|
||||||
shadowFramebuffer[iShadow] = 0;
|
shadowFramebuffer[iShadow] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate newly required buffers
|
// Allocate newly required buffers
|
||||||
for(int iShadow = 0; iShadow < cBuffers; iShadow++) {
|
for(int iShadow = 0; iShadow < cBuffers; iShadow++) {
|
||||||
Vector2 viewportSize = m_shadowViewports[iShadow].getSize();
|
Vector2 viewportSize = m_shadowViewports[iShadow].getSize();
|
||||||
|
|
||||||
if(!shadowDepthTexture[iShadow]) {
|
if(!shadowDepthTexture[iShadow]) {
|
||||||
shadowValid[iShadow] = false;
|
shadowValid[iShadow] = false;
|
||||||
|
|
||||||
GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow));
|
GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow));
|
||||||
GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow));
|
GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow));
|
||||||
// ===== Create offscreen shadow framebuffer object =====
|
// ===== Create offscreen shadow framebuffer object =====
|
||||||
|
|
||||||
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
|
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
|
||||||
|
|
||||||
// ----- Create Depth Texture for shadowFramebuffer -----
|
// ----- Create Depth Texture for shadowFramebuffer -----
|
||||||
GLDEBUG( glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow]));
|
GLDEBUG( glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow]));
|
||||||
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
||||||
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
||||||
m_pContext->getTextureManager()->_setWrapModeS(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
|
m_pContext->getTextureManager()->_setWrapModeS(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
|
||||||
m_pContext->getTextureManager()->_setWrapModeT(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
|
m_pContext->getTextureManager()->_setWrapModeT(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
|
||||||
#if GL_EXT_shadow_samplers
|
#if GL_EXT_shadow_samplers
|
||||||
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_COMPARE_REF_TO_TEXTURE_EXT)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
|
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_COMPARE_REF_TO_TEXTURE_EXT)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
|
||||||
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_EXT, GL_LEQUAL)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
|
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_EXT, GL_LEQUAL)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
|
||||||
#endif
|
#endif
|
||||||
GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, viewportSize.x, viewportSize.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL));
|
GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, viewportSize.x, viewportSize.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL));
|
||||||
|
|
||||||
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
|
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cShadowBuffers = cBuffers;
|
m_cShadowBuffers = cBuffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void KRLight::deleteBuffers()
|
void KRLight::deleteBuffers()
|
||||||
{
|
{
|
||||||
// Called when this light wasn't used in the last frame, so we can free the resources for use by other lights
|
// Called when this light wasn't used in the last frame, so we can free the resources for use by other lights
|
||||||
allocateShadowBuffers(0);
|
allocateShadowBuffers(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRLight::invalidateShadowBuffers()
|
void KRLight::invalidateShadowBuffers()
|
||||||
{
|
{
|
||||||
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
|
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
|
||||||
shadowValid[iShadow] = false;
|
shadowValid[iShadow] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int KRLight::configureShadowBufferViewports(const KRViewport &viewport)
|
int KRLight::configureShadowBufferViewports(const KRViewport &viewport)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRLight::renderShadowBuffers(KRCamera *pCamera)
|
void KRLight::renderShadowBuffers(KRCamera *pCamera)
|
||||||
{
|
{
|
||||||
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
|
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
|
||||||
if(!shadowValid[iShadow]) {
|
if(!shadowValid[iShadow]) {
|
||||||
shadowValid[iShadow] = true;
|
shadowValid[iShadow] = true;
|
||||||
|
|
||||||
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
|
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
|
||||||
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
|
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
|
||||||
|
|
||||||
GLDEBUG(glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y));
|
GLDEBUG(glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y));
|
||||||
|
|
||||||
GLDEBUG(glClearDepthf(0.0f));
|
GLDEBUG(glClearDepthf(0.0f));
|
||||||
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
|
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
|
||||||
|
|
||||||
GLDEBUG(glViewport(1, 1, m_shadowViewports[iShadow].getSize().x - 2, m_shadowViewports[iShadow].getSize().y - 2));
|
GLDEBUG(glViewport(1, 1, m_shadowViewports[iShadow].getSize().x - 2, m_shadowViewports[iShadow].getSize().y - 2));
|
||||||
|
|
||||||
GLDEBUG(glClearDepthf(1.0f));
|
GLDEBUG(glClearDepthf(1.0f));
|
||||||
|
|
||||||
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
|
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
|
||||||
|
|
||||||
GLDEBUG(glDisable(GL_DITHER));
|
GLDEBUG(glDisable(GL_DITHER));
|
||||||
|
|
||||||
//GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts
|
//GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts
|
||||||
//GLDEBUG(glEnable(GL_CULL_FACE));
|
//GLDEBUG(glEnable(GL_CULL_FACE));
|
||||||
GLDEBUG(glDisable(GL_CULL_FACE));
|
GLDEBUG(glDisable(GL_CULL_FACE));
|
||||||
|
|
||||||
// Enable z-buffer test
|
// Enable z-buffer test
|
||||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||||
GLDEBUG(glDepthFunc(GL_LESS));
|
GLDEBUG(glDepthFunc(GL_LESS));
|
||||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||||
|
|
||||||
// Disable alpha blending as we are using alpha channel for packed depth info
|
// Disable alpha blending as we are using alpha channel for packed depth info
|
||||||
GLDEBUG(glDisable(GL_BLEND));
|
GLDEBUG(glDisable(GL_BLEND));
|
||||||
|
|
||||||
// Use shader program
|
// Use shader program
|
||||||
KRShader *shadowShader = m_pContext->getShaderManager()->getShader("ShadowShader", pCamera, std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
|
KRShader *shadowShader = m_pContext->getShaderManager()->getShader("ShadowShader", pCamera, std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
|
||||||
|
|
||||||
getContext().getShaderManager()->selectShader(*pCamera, shadowShader, m_shadowViewports[iShadow], Matrix4(), std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, KRNode::RENDER_PASS_SHADOWMAP, Vector3::Zero(), 0.0f, Vector4::Zero());
|
getContext().getShaderManager()->selectShader(*pCamera, shadowShader, m_shadowViewports[iShadow], Matrix4(), std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, KRNode::RENDER_PASS_SHADOWMAP, Vector3::Zero(), 0.0f, Vector4::Zero());
|
||||||
|
|
||||||
|
|
||||||
getScene().render(pCamera, m_shadowViewports[iShadow].getVisibleBounds(), m_shadowViewports[iShadow], KRNode::RENDER_PASS_SHADOWMAP, true);
|
getScene().render(pCamera, m_shadowViewports[iShadow].getVisibleBounds(), m_shadowViewports[iShadow], KRNode::RENDER_PASS_SHADOWMAP, true);
|
||||||
|
|
||||||
GLDEBUG(glEnable(GL_CULL_FACE));
|
GLDEBUG(glEnable(GL_CULL_FACE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int KRLight::getShadowBufferCount()
|
int KRLight::getShadowBufferCount()
|
||||||
{
|
{
|
||||||
int cBuffers=0;
|
int cBuffers=0;
|
||||||
for(int iBuffer=0; iBuffer < m_cShadowBuffers; iBuffer++) {
|
for(int iBuffer=0; iBuffer < m_cShadowBuffers; iBuffer++) {
|
||||||
if(shadowValid[iBuffer]) {
|
if(shadowValid[iBuffer]) {
|
||||||
cBuffers++;
|
cBuffers++;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cBuffers;
|
return cBuffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint *KRLight::getShadowTextures()
|
GLuint *KRLight::getShadowTextures()
|
||||||
{
|
{
|
||||||
return shadowDepthTexture;
|
return shadowDepthTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRViewport *KRLight::getShadowViewports()
|
KRViewport *KRLight::getShadowViewports()
|
||||||
{
|
{
|
||||||
return m_shadowViewports;
|
return m_shadowViewports;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,422 +1,422 @@
|
|||||||
//
|
//
|
||||||
// KRMaterial.cpp
|
// KRMaterial.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
// permitted provided that the following conditions are met:
|
// permitted provided that the following conditions are met:
|
||||||
//
|
//
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
// conditions and the following disclaimer.
|
// conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
// provided with the distribution.
|
// provided with the distribution.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
// or implied, of Kearwood Gilbert.
|
// or implied, of Kearwood Gilbert.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
#include "KRMaterial.h"
|
#include "KRMaterial.h"
|
||||||
#include "KRTextureManager.h"
|
#include "KRTextureManager.h"
|
||||||
|
|
||||||
#include "KRContext.h"
|
#include "KRContext.h"
|
||||||
|
|
||||||
KRMaterial::KRMaterial(KRContext &context, const char *szName) : KRResource(context, szName) {
|
KRMaterial::KRMaterial(KRContext &context, const char *szName) : KRResource(context, szName) {
|
||||||
m_name = szName;
|
m_name = szName;
|
||||||
m_pAmbientMap = NULL;
|
m_pAmbientMap = NULL;
|
||||||
m_pDiffuseMap = NULL;
|
m_pDiffuseMap = NULL;
|
||||||
m_pSpecularMap = NULL;
|
m_pSpecularMap = NULL;
|
||||||
m_pNormalMap = NULL;
|
m_pNormalMap = NULL;
|
||||||
m_pReflectionMap = NULL;
|
m_pReflectionMap = NULL;
|
||||||
m_pReflectionCube = NULL;
|
m_pReflectionCube = NULL;
|
||||||
m_ambientColor = Vector3::Zero();
|
m_ambientColor = Vector3::Zero();
|
||||||
m_diffuseColor = Vector3::One();
|
m_diffuseColor = Vector3::One();
|
||||||
m_specularColor = Vector3::One();
|
m_specularColor = Vector3::One();
|
||||||
m_reflectionColor = Vector3::Zero();
|
m_reflectionColor = Vector3::Zero();
|
||||||
m_tr = (GLfloat)1.0f;
|
m_tr = (GLfloat)1.0f;
|
||||||
m_ns = (GLfloat)0.0f;
|
m_ns = (GLfloat)0.0f;
|
||||||
m_ambientMap = "";
|
m_ambientMap = "";
|
||||||
m_diffuseMap = "";
|
m_diffuseMap = "";
|
||||||
m_specularMap = "";
|
m_specularMap = "";
|
||||||
m_normalMap = "";
|
m_normalMap = "";
|
||||||
m_reflectionMap = "";
|
m_reflectionMap = "";
|
||||||
m_reflectionCube = "";
|
m_reflectionCube = "";
|
||||||
m_ambientMapOffset = Vector2(0.0f, 0.0f);
|
m_ambientMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||||
m_specularMapOffset = Vector2(0.0f, 0.0f);
|
m_specularMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||||
m_diffuseMapOffset = Vector2(0.0f, 0.0f);
|
m_diffuseMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||||
m_ambientMapScale = Vector2(1.0f, 1.0f);
|
m_ambientMapScale = Vector2::Create(1.0f, 1.0f);
|
||||||
m_specularMapScale = Vector2(1.0f, 1.0f);
|
m_specularMapScale = Vector2::Create(1.0f, 1.0f);
|
||||||
m_diffuseMapScale = Vector2(1.0f, 1.0f);
|
m_diffuseMapScale = Vector2::Create(1.0f, 1.0f);
|
||||||
m_reflectionMapOffset = Vector2(0.0f, 0.0f);
|
m_reflectionMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||||
m_reflectionMapScale = Vector2(1.0f, 1.0f);
|
m_reflectionMapScale = Vector2::Create(1.0f, 1.0f);
|
||||||
m_alpha_mode = KRMATERIAL_ALPHA_MODE_OPAQUE;
|
m_alpha_mode = KRMATERIAL_ALPHA_MODE_OPAQUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRMaterial::~KRMaterial() {
|
KRMaterial::~KRMaterial() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KRMaterial::getExtension() {
|
std::string KRMaterial::getExtension() {
|
||||||
return "mtl";
|
return "mtl";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KRMaterial::needsVertexTangents()
|
bool KRMaterial::needsVertexTangents()
|
||||||
{
|
{
|
||||||
return m_normalMap.size() > 0;
|
return m_normalMap.size() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KRMaterial::save(KRDataBlock &data) {
|
bool KRMaterial::save(KRDataBlock &data) {
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
stream.precision(std::numeric_limits<long double>::digits10);
|
stream.precision(std::numeric_limits<long double>::digits10);
|
||||||
stream.setf(std::ios::fixed,std::ios::floatfield);
|
stream.setf(std::ios::fixed,std::ios::floatfield);
|
||||||
|
|
||||||
stream << "newmtl " << m_name;
|
stream << "newmtl " << m_name;
|
||||||
stream << "\nka " << m_ambientColor.x << " " << m_ambientColor.y << " " << m_ambientColor.z;
|
stream << "\nka " << m_ambientColor.x << " " << m_ambientColor.y << " " << m_ambientColor.z;
|
||||||
stream << "\nkd " << m_diffuseColor.x << " " << m_diffuseColor.y << " " << m_diffuseColor.z;
|
stream << "\nkd " << m_diffuseColor.x << " " << m_diffuseColor.y << " " << m_diffuseColor.z;
|
||||||
stream << "\nks " << m_specularColor.x << " " << m_specularColor.y << " " << m_specularColor.z;
|
stream << "\nks " << m_specularColor.x << " " << m_specularColor.y << " " << m_specularColor.z;
|
||||||
stream << "\nkr " << m_reflectionColor.x << " " << m_reflectionColor.y << " " << m_reflectionColor.z;
|
stream << "\nkr " << m_reflectionColor.x << " " << m_reflectionColor.y << " " << m_reflectionColor.z;
|
||||||
stream << "\nTr " << m_tr;
|
stream << "\nTr " << m_tr;
|
||||||
stream << "\nNs " << m_ns;
|
stream << "\nNs " << m_ns;
|
||||||
if(m_ambientMap.size()) {
|
if(m_ambientMap.size()) {
|
||||||
stream << "\nmap_Ka " << m_ambientMap << ".pvr -s " << m_ambientMapScale.x << " " << m_ambientMapScale.y << " -o " << m_ambientMapOffset.x << " " << m_ambientMapOffset.y;
|
stream << "\nmap_Ka " << m_ambientMap << ".pvr -s " << m_ambientMapScale.x << " " << m_ambientMapScale.y << " -o " << m_ambientMapOffset.x << " " << m_ambientMapOffset.y;
|
||||||
} else {
|
} else {
|
||||||
stream << "\n# map_Ka filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
stream << "\n# map_Ka filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||||
}
|
}
|
||||||
if(m_diffuseMap.size()) {
|
if(m_diffuseMap.size()) {
|
||||||
stream << "\nmap_Kd " << m_diffuseMap << ".pvr -s " << m_diffuseMapScale.x << " " << m_diffuseMapScale.y << " -o " << m_diffuseMapOffset.x << " " << m_diffuseMapOffset.y;
|
stream << "\nmap_Kd " << m_diffuseMap << ".pvr -s " << m_diffuseMapScale.x << " " << m_diffuseMapScale.y << " -o " << m_diffuseMapOffset.x << " " << m_diffuseMapOffset.y;
|
||||||
} else {
|
} else {
|
||||||
stream << "\n# map_Kd filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
stream << "\n# map_Kd filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||||
}
|
}
|
||||||
if(m_specularMap.size()) {
|
if(m_specularMap.size()) {
|
||||||
stream << "\nmap_Ks " << m_specularMap << ".pvr -s " << m_specularMapScale.x << " " << m_specularMapScale.y << " -o " << m_specularMapOffset.x << " " << m_specularMapOffset.y << "\n";
|
stream << "\nmap_Ks " << m_specularMap << ".pvr -s " << m_specularMapScale.x << " " << m_specularMapScale.y << " -o " << m_specularMapOffset.x << " " << m_specularMapOffset.y << "\n";
|
||||||
} else {
|
} else {
|
||||||
stream << "\n# map_Ks filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
stream << "\n# map_Ks filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||||
}
|
}
|
||||||
if(m_normalMap.size()) {
|
if(m_normalMap.size()) {
|
||||||
stream << "\nmap_Normal " << m_normalMap << ".pvr -s " << m_normalMapScale.x << " " << m_normalMapScale.y << " -o " << m_normalMapOffset.x << " " << m_normalMapOffset.y;
|
stream << "\nmap_Normal " << m_normalMap << ".pvr -s " << m_normalMapScale.x << " " << m_normalMapScale.y << " -o " << m_normalMapOffset.x << " " << m_normalMapOffset.y;
|
||||||
} else {
|
} else {
|
||||||
stream << "\n# map_Normal filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
stream << "\n# map_Normal filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||||
}
|
}
|
||||||
if(m_reflectionMap.size()) {
|
if(m_reflectionMap.size()) {
|
||||||
stream << "\nmap_Reflection " << m_reflectionMap << ".pvr -s " << m_reflectionMapScale.x << " " << m_reflectionMapScale.y << " -o " << m_reflectionMapOffset.x << " " << m_reflectionMapOffset.y;
|
stream << "\nmap_Reflection " << m_reflectionMap << ".pvr -s " << m_reflectionMapScale.x << " " << m_reflectionMapScale.y << " -o " << m_reflectionMapOffset.x << " " << m_reflectionMapOffset.y;
|
||||||
} else {
|
} else {
|
||||||
stream << "\n# map_Reflection filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
stream << "\n# map_Reflection filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||||
}
|
}
|
||||||
if(m_reflectionCube.size()) {
|
if(m_reflectionCube.size()) {
|
||||||
stream << "\nmap_ReflectionCube " << m_reflectionCube << ".pvr";
|
stream << "\nmap_ReflectionCube " << m_reflectionCube << ".pvr";
|
||||||
} else {
|
} else {
|
||||||
stream << "\n# map_ReflectionCube cubemapname";
|
stream << "\n# map_ReflectionCube cubemapname";
|
||||||
}
|
}
|
||||||
switch(m_alpha_mode) {
|
switch(m_alpha_mode) {
|
||||||
case KRMATERIAL_ALPHA_MODE_OPAQUE:
|
case KRMATERIAL_ALPHA_MODE_OPAQUE:
|
||||||
stream << "\nalpha_mode opaque";
|
stream << "\nalpha_mode opaque";
|
||||||
break;
|
break;
|
||||||
case KRMATERIAL_ALPHA_MODE_TEST:
|
case KRMATERIAL_ALPHA_MODE_TEST:
|
||||||
stream << "\nalpha_mode test";
|
stream << "\nalpha_mode test";
|
||||||
break;
|
break;
|
||||||
case KRMATERIAL_ALPHA_MODE_BLENDONESIDE:
|
case KRMATERIAL_ALPHA_MODE_BLENDONESIDE:
|
||||||
stream << "\nalpha_mode blendoneside";
|
stream << "\nalpha_mode blendoneside";
|
||||||
break;
|
break;
|
||||||
case KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE:
|
case KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE:
|
||||||
stream << "\nalpha_mode blendtwoside";
|
stream << "\nalpha_mode blendtwoside";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
stream << "\n# alpha_mode opaque, test, blendoneside, or blendtwoside";
|
stream << "\n# alpha_mode opaque, test, blendoneside, or blendtwoside";
|
||||||
|
|
||||||
stream << "\n";
|
stream << "\n";
|
||||||
data.append(stream.str());
|
data.append(stream.str());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRMaterial::setAmbientMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
void KRMaterial::setAmbientMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||||
m_ambientMap = texture_name;
|
m_ambientMap = texture_name;
|
||||||
m_ambientMapScale = texture_scale;
|
m_ambientMapScale = texture_scale;
|
||||||
m_ambientMapOffset = texture_offset;
|
m_ambientMapOffset = texture_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRMaterial::setDiffuseMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
void KRMaterial::setDiffuseMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||||
m_diffuseMap = texture_name;
|
m_diffuseMap = texture_name;
|
||||||
m_diffuseMapScale = texture_scale;
|
m_diffuseMapScale = texture_scale;
|
||||||
m_diffuseMapOffset = texture_offset;
|
m_diffuseMapOffset = texture_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRMaterial::setSpecularMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
void KRMaterial::setSpecularMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||||
m_specularMap = texture_name;
|
m_specularMap = texture_name;
|
||||||
m_specularMapScale = texture_scale;
|
m_specularMapScale = texture_scale;
|
||||||
m_specularMapOffset = texture_offset;
|
m_specularMapOffset = texture_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRMaterial::setNormalMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
void KRMaterial::setNormalMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||||
m_normalMap = texture_name;
|
m_normalMap = texture_name;
|
||||||
m_normalMapScale = texture_scale;
|
m_normalMapScale = texture_scale;
|
||||||
m_normalMapOffset = texture_offset;
|
m_normalMapOffset = texture_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRMaterial::setReflectionMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
void KRMaterial::setReflectionMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||||
m_reflectionMap = texture_name;
|
m_reflectionMap = texture_name;
|
||||||
m_reflectionMapScale = texture_scale;
|
m_reflectionMapScale = texture_scale;
|
||||||
m_reflectionMapOffset = texture_offset;
|
m_reflectionMapOffset = texture_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRMaterial::setReflectionCube(std::string texture_name) {
|
void KRMaterial::setReflectionCube(std::string texture_name) {
|
||||||
m_reflectionCube = texture_name;
|
m_reflectionCube = texture_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRMaterial::setAlphaMode(KRMaterial::alpha_mode_type alpha_mode) {
|
void KRMaterial::setAlphaMode(KRMaterial::alpha_mode_type alpha_mode) {
|
||||||
m_alpha_mode = alpha_mode;
|
m_alpha_mode = alpha_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRMaterial::alpha_mode_type KRMaterial::getAlphaMode() {
|
KRMaterial::alpha_mode_type KRMaterial::getAlphaMode() {
|
||||||
return m_alpha_mode;
|
return m_alpha_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRMaterial::setAmbient(const Vector3 &c) {
|
void KRMaterial::setAmbient(const Vector3 &c) {
|
||||||
m_ambientColor = c;
|
m_ambientColor = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRMaterial::setDiffuse(const Vector3 &c) {
|
void KRMaterial::setDiffuse(const Vector3 &c) {
|
||||||
m_diffuseColor = c;
|
m_diffuseColor = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRMaterial::setSpecular(const Vector3 &c) {
|
void KRMaterial::setSpecular(const Vector3 &c) {
|
||||||
m_specularColor = c;
|
m_specularColor = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRMaterial::setReflection(const Vector3 &c) {
|
void KRMaterial::setReflection(const Vector3 &c) {
|
||||||
m_reflectionColor = c;
|
m_reflectionColor = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRMaterial::setTransparency(GLfloat a) {
|
void KRMaterial::setTransparency(GLfloat a) {
|
||||||
if(a < 1.0f && m_alpha_mode == KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE) {
|
if(a < 1.0f && m_alpha_mode == KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE) {
|
||||||
setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
|
setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
|
||||||
}
|
}
|
||||||
m_tr = a;
|
m_tr = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRMaterial::setShininess(GLfloat s) {
|
void KRMaterial::setShininess(GLfloat s) {
|
||||||
m_ns = s;
|
m_ns = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KRMaterial::isTransparent() {
|
bool KRMaterial::isTransparent() {
|
||||||
return m_tr < 1.0 || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE;
|
return m_tr < 1.0 || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRMaterial::preStream(float lodCoverage)
|
void KRMaterial::preStream(float lodCoverage)
|
||||||
{
|
{
|
||||||
getTextures();
|
getTextures();
|
||||||
|
|
||||||
if(m_pAmbientMap) {
|
if(m_pAmbientMap) {
|
||||||
m_pAmbientMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_AMBIENT_MAP);
|
m_pAmbientMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_AMBIENT_MAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pDiffuseMap) {
|
if(m_pDiffuseMap) {
|
||||||
m_pDiffuseMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
|
m_pDiffuseMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pNormalMap) {
|
if(m_pNormalMap) {
|
||||||
m_pNormalMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
|
m_pNormalMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pSpecularMap) {
|
if(m_pSpecularMap) {
|
||||||
m_pSpecularMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
|
m_pSpecularMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pReflectionMap) {
|
if(m_pReflectionMap) {
|
||||||
m_pReflectionMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
|
m_pReflectionMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pReflectionCube) {
|
if(m_pReflectionCube) {
|
||||||
m_pReflectionCube->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
|
m_pReflectionCube->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
kraken_stream_level KRMaterial::getStreamLevel()
|
kraken_stream_level KRMaterial::getStreamLevel()
|
||||||
{
|
{
|
||||||
kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ;
|
kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ;
|
||||||
|
|
||||||
getTextures();
|
getTextures();
|
||||||
|
|
||||||
if(m_pAmbientMap) {
|
if(m_pAmbientMap) {
|
||||||
stream_level = KRMIN(stream_level, m_pAmbientMap->getStreamLevel(KRTexture::TEXTURE_USAGE_AMBIENT_MAP));
|
stream_level = KRMIN(stream_level, m_pAmbientMap->getStreamLevel(KRTexture::TEXTURE_USAGE_AMBIENT_MAP));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pDiffuseMap) {
|
if(m_pDiffuseMap) {
|
||||||
stream_level = KRMIN(stream_level, m_pDiffuseMap->getStreamLevel(KRTexture::TEXTURE_USAGE_DIFFUSE_MAP));
|
stream_level = KRMIN(stream_level, m_pDiffuseMap->getStreamLevel(KRTexture::TEXTURE_USAGE_DIFFUSE_MAP));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pNormalMap) {
|
if(m_pNormalMap) {
|
||||||
stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(KRTexture::TEXTURE_USAGE_NORMAL_MAP));
|
stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(KRTexture::TEXTURE_USAGE_NORMAL_MAP));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pSpecularMap) {
|
if(m_pSpecularMap) {
|
||||||
stream_level = KRMIN(stream_level, m_pSpecularMap->getStreamLevel(KRTexture::TEXTURE_USAGE_SPECULAR_MAP));
|
stream_level = KRMIN(stream_level, m_pSpecularMap->getStreamLevel(KRTexture::TEXTURE_USAGE_SPECULAR_MAP));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pReflectionMap) {
|
if(m_pReflectionMap) {
|
||||||
stream_level = KRMIN(stream_level, m_pReflectionMap->getStreamLevel(KRTexture::TEXTURE_USAGE_REFLECTION_MAP));
|
stream_level = KRMIN(stream_level, m_pReflectionMap->getStreamLevel(KRTexture::TEXTURE_USAGE_REFLECTION_MAP));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pReflectionCube) {
|
if(m_pReflectionCube) {
|
||||||
stream_level = KRMIN(stream_level, m_pReflectionCube->getStreamLevel(KRTexture::TEXTURE_USAGE_REFECTION_CUBE));
|
stream_level = KRMIN(stream_level, m_pReflectionCube->getStreamLevel(KRTexture::TEXTURE_USAGE_REFECTION_CUBE));
|
||||||
}
|
}
|
||||||
|
|
||||||
return stream_level;
|
return stream_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRMaterial::getTextures()
|
void KRMaterial::getTextures()
|
||||||
{
|
{
|
||||||
if(!m_pAmbientMap && m_ambientMap.size()) {
|
if(!m_pAmbientMap && m_ambientMap.size()) {
|
||||||
m_pAmbientMap = getContext().getTextureManager()->getTexture(m_ambientMap);
|
m_pAmbientMap = getContext().getTextureManager()->getTexture(m_ambientMap);
|
||||||
}
|
}
|
||||||
if(!m_pDiffuseMap && m_diffuseMap.size()) {
|
if(!m_pDiffuseMap && m_diffuseMap.size()) {
|
||||||
m_pDiffuseMap = getContext().getTextureManager()->getTexture(m_diffuseMap);
|
m_pDiffuseMap = getContext().getTextureManager()->getTexture(m_diffuseMap);
|
||||||
}
|
}
|
||||||
if(!m_pNormalMap && m_normalMap.size()) {
|
if(!m_pNormalMap && m_normalMap.size()) {
|
||||||
m_pNormalMap = getContext().getTextureManager()->getTexture(m_normalMap);
|
m_pNormalMap = getContext().getTextureManager()->getTexture(m_normalMap);
|
||||||
}
|
}
|
||||||
if(!m_pSpecularMap && m_specularMap.size()) {
|
if(!m_pSpecularMap && m_specularMap.size()) {
|
||||||
m_pSpecularMap = getContext().getTextureManager()->getTexture(m_specularMap);
|
m_pSpecularMap = getContext().getTextureManager()->getTexture(m_specularMap);
|
||||||
}
|
}
|
||||||
if(!m_pReflectionMap && m_reflectionMap.size()) {
|
if(!m_pReflectionMap && m_reflectionMap.size()) {
|
||||||
m_pReflectionMap = getContext().getTextureManager()->getTexture(m_reflectionMap);
|
m_pReflectionMap = getContext().getTextureManager()->getTexture(m_reflectionMap);
|
||||||
}
|
}
|
||||||
if(!m_pReflectionCube && m_reflectionCube.size()) {
|
if(!m_pReflectionCube && m_reflectionCube.size()) {
|
||||||
m_pReflectionCube = getContext().getTextureManager()->getTextureCube(m_reflectionCube.c_str());
|
m_pReflectionCube = getContext().getTextureManager()->getTextureCube(m_reflectionCube.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KRMaterial::bind(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const std::vector<KRBone *> &bones, const std::vector<Matrix4> &bind_poses, const KRViewport &viewport, const Matrix4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const Vector3 &rim_color, float rim_power, float lod_coverage) {
|
bool KRMaterial::bind(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const std::vector<KRBone *> &bones, const std::vector<Matrix4> &bind_poses, const KRViewport &viewport, const Matrix4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const Vector3 &rim_color, float rim_power, float lod_coverage) {
|
||||||
bool bLightMap = pLightMap && pCamera->settings.bEnableLightMap;
|
bool bLightMap = pLightMap && pCamera->settings.bEnableLightMap;
|
||||||
|
|
||||||
getTextures();
|
getTextures();
|
||||||
|
|
||||||
Vector2 default_scale = Vector2::One();
|
Vector2 default_scale = Vector2::One();
|
||||||
Vector2 default_offset = Vector2::Zero();
|
Vector2 default_offset = Vector2::Zero();
|
||||||
|
|
||||||
bool bHasReflection = m_reflectionColor != Vector3::Zero();
|
bool bHasReflection = m_reflectionColor != Vector3::Zero();
|
||||||
bool bDiffuseMap = m_pDiffuseMap != NULL && pCamera->settings.bEnableDiffuseMap;
|
bool bDiffuseMap = m_pDiffuseMap != NULL && pCamera->settings.bEnableDiffuseMap;
|
||||||
bool bNormalMap = m_pNormalMap != NULL && pCamera->settings.bEnableNormalMap;
|
bool bNormalMap = m_pNormalMap != NULL && pCamera->settings.bEnableNormalMap;
|
||||||
bool bSpecMap = m_pSpecularMap != NULL && pCamera->settings.bEnableSpecMap;
|
bool bSpecMap = m_pSpecularMap != NULL && pCamera->settings.bEnableSpecMap;
|
||||||
bool bReflectionMap = m_pReflectionMap != NULL && pCamera->settings.bEnableReflectionMap && pCamera->settings.bEnableReflection && bHasReflection;
|
bool bReflectionMap = m_pReflectionMap != NULL && pCamera->settings.bEnableReflectionMap && pCamera->settings.bEnableReflection && bHasReflection;
|
||||||
bool bReflectionCubeMap = m_pReflectionCube != NULL && pCamera->settings.bEnableReflection && bHasReflection;
|
bool bReflectionCubeMap = m_pReflectionCube != NULL && pCamera->settings.bEnableReflection && bHasReflection;
|
||||||
bool bAlphaTest = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_TEST) && bDiffuseMap;
|
bool bAlphaTest = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_TEST) && bDiffuseMap;
|
||||||
bool bAlphaBlend = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE) || (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
|
bool bAlphaBlend = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE) || (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
|
||||||
|
|
||||||
KRShader *pShader = getContext().getShaderManager()->getShader("ObjectShader", pCamera, point_lights, directional_lights, spot_lights, bones.size(), bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, bLightMap, m_diffuseMapScale != default_scale && bDiffuseMap, m_specularMapScale != default_scale && bSpecMap, m_normalMapScale != default_scale && bNormalMap, m_reflectionMapScale != default_scale && bReflectionMap, m_diffuseMapOffset != default_offset && bDiffuseMap, m_specularMapOffset != default_offset && bSpecMap, m_normalMapOffset != default_offset && bNormalMap, m_reflectionMapOffset != default_offset && bReflectionMap, bAlphaTest, bAlphaBlend, renderPass, rim_power != 0.0f);
|
KRShader *pShader = getContext().getShaderManager()->getShader("ObjectShader", pCamera, point_lights, directional_lights, spot_lights, bones.size(), bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, bLightMap, m_diffuseMapScale != default_scale && bDiffuseMap, m_specularMapScale != default_scale && bSpecMap, m_normalMapScale != default_scale && bNormalMap, m_reflectionMapScale != default_scale && bReflectionMap, m_diffuseMapOffset != default_offset && bDiffuseMap, m_specularMapOffset != default_offset && bSpecMap, m_normalMapOffset != default_offset && bNormalMap, m_reflectionMapOffset != default_offset && bReflectionMap, bAlphaTest, bAlphaBlend, renderPass, rim_power != 0.0f);
|
||||||
|
|
||||||
|
|
||||||
Vector4 fade_color;
|
Vector4 fade_color;
|
||||||
if(!getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, matModel, point_lights, directional_lights, spot_lights, 0, renderPass, rim_color, rim_power, fade_color)) {
|
if(!getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, matModel, point_lights, directional_lights, spot_lights, 0, renderPass, rim_color, rim_power, fade_color)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind bones
|
// Bind bones
|
||||||
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
|
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
|
||||||
GLfloat bone_mats[256 * 16];
|
GLfloat bone_mats[256 * 16];
|
||||||
GLfloat *bone_mat_component = bone_mats;
|
GLfloat *bone_mat_component = bone_mats;
|
||||||
for(int bone_index=0; bone_index < bones.size(); bone_index++) {
|
for(int bone_index=0; bone_index < bones.size(); bone_index++) {
|
||||||
KRBone *bone = bones[bone_index];
|
KRBone *bone = bones[bone_index];
|
||||||
|
|
||||||
// Vector3 initialRotation = bone->getInitialLocalRotation();
|
// Vector3 initialRotation = bone->getInitialLocalRotation();
|
||||||
// Vector3 rotation = bone->getLocalRotation();
|
// Vector3 rotation = bone->getLocalRotation();
|
||||||
// Vector3 initialTranslation = bone->getInitialLocalTranslation();
|
// Vector3 initialTranslation = bone->getInitialLocalTranslation();
|
||||||
// Vector3 translation = bone->getLocalTranslation();
|
// Vector3 translation = bone->getLocalTranslation();
|
||||||
// Vector3 initialScale = bone->getInitialLocalScale();
|
// Vector3 initialScale = bone->getInitialLocalScale();
|
||||||
// Vector3 scale = bone->getLocalScale();
|
// Vector3 scale = bone->getLocalScale();
|
||||||
//
|
//
|
||||||
//printf("%s - delta rotation: %.4f %.4f %.4f\n", bone->getName().c_str(), (rotation.x - initialRotation.x) * 180.0 / M_PI, (rotation.y - initialRotation.y) * 180.0 / M_PI, (rotation.z - initialRotation.z) * 180.0 / M_PI);
|
//printf("%s - delta rotation: %.4f %.4f %.4f\n", bone->getName().c_str(), (rotation.x - initialRotation.x) * 180.0 / M_PI, (rotation.y - initialRotation.y) * 180.0 / M_PI, (rotation.z - initialRotation.z) * 180.0 / M_PI);
|
||||||
//printf("%s - delta translation: %.4f %.4f %.4f\n", bone->getName().c_str(), translation.x - initialTranslation.x, translation.y - initialTranslation.y, translation.z - initialTranslation.z);
|
//printf("%s - delta translation: %.4f %.4f %.4f\n", bone->getName().c_str(), translation.x - initialTranslation.x, translation.y - initialTranslation.y, translation.z - initialTranslation.z);
|
||||||
// printf("%s - delta scale: %.4f %.4f %.4f\n", bone->getName().c_str(), scale.x - initialScale.x, scale.y - initialScale.y, scale.z - initialScale.z);
|
// printf("%s - delta scale: %.4f %.4f %.4f\n", bone->getName().c_str(), scale.x - initialScale.x, scale.y - initialScale.y, scale.z - initialScale.z);
|
||||||
|
|
||||||
Matrix4 skin_bone_bind_pose = bind_poses[bone_index];
|
Matrix4 skin_bone_bind_pose = bind_poses[bone_index];
|
||||||
Matrix4 active_mat = bone->getActivePoseMatrix();
|
Matrix4 active_mat = bone->getActivePoseMatrix();
|
||||||
Matrix4 inv_bind_mat = bone->getInverseBindPoseMatrix();
|
Matrix4 inv_bind_mat = bone->getInverseBindPoseMatrix();
|
||||||
Matrix4 inv_bind_mat2 = Matrix4::Invert(bind_poses[bone_index]);
|
Matrix4 inv_bind_mat2 = Matrix4::Invert(bind_poses[bone_index]);
|
||||||
Matrix4 t = (inv_bind_mat * active_mat);
|
Matrix4 t = (inv_bind_mat * active_mat);
|
||||||
Matrix4 t2 = inv_bind_mat2 * bone->getModelMatrix();
|
Matrix4 t2 = inv_bind_mat2 * bone->getModelMatrix();
|
||||||
for(int i=0; i < 16; i++) {
|
for(int i=0; i < 16; i++) {
|
||||||
*bone_mat_component++ = t[i];
|
*bone_mat_component++ = t[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
|
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
|
||||||
glUniformMatrix4fv(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS], bones.size(), GL_FALSE, bone_mats);
|
glUniformMatrix4fv(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS], bones.size(), GL_FALSE, bone_mats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_AMBIENT, m_ambientColor + pCamera->settings.ambient_intensity);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_AMBIENT, m_ambientColor + pCamera->settings.ambient_intensity);
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
|
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
|
||||||
// We pre-multiply the light color with the material color in the forward renderer
|
// We pre-multiply the light color with the material color in the forward renderer
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, Vector3(m_diffuseColor.x * pCamera->settings.light_intensity.x, m_diffuseColor.y * pCamera->settings.light_intensity.y, m_diffuseColor.z * pCamera->settings.light_intensity.z));
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, Vector3::Create(m_diffuseColor.x * pCamera->settings.light_intensity.x, m_diffuseColor.y * pCamera->settings.light_intensity.y, m_diffuseColor.z * pCamera->settings.light_intensity.z));
|
||||||
} else {
|
} else {
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, m_diffuseColor);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, m_diffuseColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
|
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
|
||||||
// We pre-multiply the light color with the material color in the forward renderer
|
// We pre-multiply the light color with the material color in the forward renderer
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SPECULAR, Vector3(m_specularColor.x * pCamera->settings.light_intensity.x, m_specularColor.y * pCamera->settings.light_intensity.y, m_specularColor.z * pCamera->settings.light_intensity.z));
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SPECULAR, Vector3::Create(m_specularColor.x * pCamera->settings.light_intensity.x, m_specularColor.y * pCamera->settings.light_intensity.y, m_specularColor.z * pCamera->settings.light_intensity.z));
|
||||||
} else {
|
} else {
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SPECULAR, m_specularColor);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SPECULAR, m_specularColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SHININESS, m_ns);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SHININESS, m_ns);
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_REFLECTION, m_reflectionColor);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_REFLECTION, m_reflectionColor);
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_SCALE, m_diffuseMapScale);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_SCALE, m_diffuseMapScale);
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_SCALE, m_specularMapScale);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_SCALE, m_specularMapScale);
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_SCALE, m_reflectionMapScale);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_SCALE, m_reflectionMapScale);
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_SCALE, m_normalMapScale);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_SCALE, m_normalMapScale);
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_OFFSET, m_diffuseMapOffset);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_OFFSET, m_diffuseMapOffset);
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_OFFSET, m_specularMapOffset);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_OFFSET, m_specularMapOffset);
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_OFFSET, m_reflectionMapOffset);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_OFFSET, m_reflectionMapOffset);
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_OFFSET, m_normalMapOffset);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_OFFSET, m_normalMapOffset);
|
||||||
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_tr);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_tr);
|
||||||
|
|
||||||
if(bDiffuseMap) {
|
if(bDiffuseMap) {
|
||||||
m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap, lod_coverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
|
m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap, lod_coverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bSpecMap) {
|
if(bSpecMap) {
|
||||||
m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap, lod_coverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
|
m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap, lod_coverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bNormalMap) {
|
if(bNormalMap) {
|
||||||
m_pContext->getTextureManager()->selectTexture(2, m_pNormalMap, lod_coverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
|
m_pContext->getTextureManager()->selectTexture(2, m_pNormalMap, lod_coverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bReflectionCubeMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) {
|
if(bReflectionCubeMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) {
|
||||||
m_pContext->getTextureManager()->selectTexture(4, m_pReflectionCube, lod_coverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
|
m_pContext->getTextureManager()->selectTexture(4, m_pReflectionCube, lod_coverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bReflectionMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) {
|
if(bReflectionMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) {
|
||||||
// GL_TEXTURE7 is used for reading the depth buffer in gBuffer pass 2 and re-used for the reflection map in gBuffer Pass 3 and in forward rendering
|
// GL_TEXTURE7 is used for reading the depth buffer in gBuffer pass 2 and re-used for the reflection map in gBuffer Pass 3 and in forward rendering
|
||||||
m_pContext->getTextureManager()->selectTexture(7, m_pReflectionMap, lod_coverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
|
m_pContext->getTextureManager()->selectTexture(7, m_pReflectionMap, lod_coverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &KRMaterial::getName() const
|
const std::string &KRMaterial::getName() const
|
||||||
{
|
{
|
||||||
return m_name;
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,288 +1,288 @@
|
|||||||
//
|
//
|
||||||
// KRMaterialManager.cpp
|
// KRMaterialManager.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
// permitted provided that the following conditions are met:
|
// permitted provided that the following conditions are met:
|
||||||
//
|
//
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
// conditions and the following disclaimer.
|
// conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
// provided with the distribution.
|
// provided with the distribution.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
// or implied, of Kearwood Gilbert.
|
// or implied, of Kearwood Gilbert.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
#include "KRMaterialManager.h"
|
#include "KRMaterialManager.h"
|
||||||
|
|
||||||
|
|
||||||
KRMaterialManager::KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRShaderManager *pShaderManager) : KRContextObject(context)
|
KRMaterialManager::KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRShaderManager *pShaderManager) : KRContextObject(context)
|
||||||
{
|
{
|
||||||
m_pTextureManager = pTextureManager;
|
m_pTextureManager = pTextureManager;
|
||||||
m_pShaderManager = pShaderManager;
|
m_pShaderManager = pShaderManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRMaterialManager::~KRMaterialManager() {
|
KRMaterialManager::~KRMaterialManager() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unordered_map<std::string, KRMaterial *> &KRMaterialManager::getMaterials()
|
unordered_map<std::string, KRMaterial *> &KRMaterialManager::getMaterials()
|
||||||
{
|
{
|
||||||
return m_materials;
|
return m_materials;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRMaterialManager::configure(bool blend_enable, GLenum blend_src, GLenum blend_dest, bool depth_test_enable, GLenum depth_func, bool depth_write_enable) {
|
void KRMaterialManager::configure(bool blend_enable, GLenum blend_src, GLenum blend_dest, bool depth_test_enable, GLenum depth_func, bool depth_write_enable) {
|
||||||
if(blend_enable) {
|
if(blend_enable) {
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
GLDEBUG(glEnable(GL_BLEND));
|
||||||
GLDEBUG(glBlendFunc(blend_src, blend_dest));
|
GLDEBUG(glBlendFunc(blend_src, blend_dest));
|
||||||
} else {
|
} else {
|
||||||
GLDEBUG(glDisable(GL_BLEND));
|
GLDEBUG(glDisable(GL_BLEND));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(depth_test_enable) {
|
if(depth_test_enable) {
|
||||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||||
GLDEBUG(glDepthFunc(depth_func));
|
GLDEBUG(glDepthFunc(depth_func));
|
||||||
} else {
|
} else {
|
||||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(depth_write_enable) {
|
if(depth_write_enable) {
|
||||||
GLDEBUG(glDepthMask(GL_TRUE));
|
GLDEBUG(glDepthMask(GL_TRUE));
|
||||||
} else {
|
} else {
|
||||||
GLDEBUG(glDepthMask(GL_FALSE));
|
GLDEBUG(glDepthMask(GL_FALSE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
KRMaterial *KRMaterialManager::getMaterial(const std::string &name) {
|
KRMaterial *KRMaterialManager::getMaterial(const std::string &name) {
|
||||||
std::string lowerName = name;
|
std::string lowerName = name;
|
||||||
std::transform(lowerName.begin(), lowerName.end(),
|
std::transform(lowerName.begin(), lowerName.end(),
|
||||||
lowerName.begin(), ::tolower);
|
lowerName.begin(), ::tolower);
|
||||||
|
|
||||||
|
|
||||||
unordered_map<std::string, KRMaterial *>::iterator itr = m_materials.find(lowerName);
|
unordered_map<std::string, KRMaterial *>::iterator itr = m_materials.find(lowerName);
|
||||||
if(itr == m_materials.end()) {
|
if(itr == m_materials.end()) {
|
||||||
KRContext::Log(KRContext::LOG_LEVEL_WARNING, "Material not found: %s", name.c_str());
|
KRContext::Log(KRContext::LOG_LEVEL_WARNING, "Material not found: %s", name.c_str());
|
||||||
// Not found
|
// Not found
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
return (*itr).second;
|
return (*itr).second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRMaterialManager::add(KRMaterial *new_material) {
|
void KRMaterialManager::add(KRMaterial *new_material) {
|
||||||
// FINDME, TODO - Potential memory leak if multiple materials with the same name are added
|
// FINDME, TODO - Potential memory leak if multiple materials with the same name are added
|
||||||
std::string lowerName = new_material->getName();
|
std::string lowerName = new_material->getName();
|
||||||
std::transform(lowerName.begin(), lowerName.end(),
|
std::transform(lowerName.begin(), lowerName.end(),
|
||||||
lowerName.begin(), ::tolower);
|
lowerName.begin(), ::tolower);
|
||||||
|
|
||||||
m_materials[lowerName] = new_material;
|
m_materials[lowerName] = new_material;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KRMaterialManager::load(const char *szName, KRDataBlock *data) {
|
bool KRMaterialManager::load(const char *szName, KRDataBlock *data) {
|
||||||
KRMaterial *pMaterial = NULL;
|
KRMaterial *pMaterial = NULL;
|
||||||
char szSymbol[16][256];
|
char szSymbol[16][256];
|
||||||
data->lock();
|
data->lock();
|
||||||
|
|
||||||
char *pScan = (char *)data->getStart();
|
char *pScan = (char *)data->getStart();
|
||||||
char *pEnd = (char *)data->getEnd();
|
char *pEnd = (char *)data->getEnd();
|
||||||
while(pScan < pEnd) {
|
while(pScan < pEnd) {
|
||||||
|
|
||||||
// Scan through whitespace
|
// Scan through whitespace
|
||||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||||
pScan++;
|
pScan++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(*pScan == '#') {
|
if(*pScan == '#') {
|
||||||
// Line is a comment line
|
// Line is a comment line
|
||||||
|
|
||||||
// Scan to the end of the line
|
// Scan to the end of the line
|
||||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||||
pScan++;
|
pScan++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int cSymbols = 0;
|
int cSymbols = 0;
|
||||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||||
|
|
||||||
char *pDest = szSymbol[cSymbols++];
|
char *pDest = szSymbol[cSymbols++];
|
||||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||||
if(*pScan >= 'A' && *pScan <= 'Z') {
|
if(*pScan >= 'A' && *pScan <= 'Z') {
|
||||||
*pDest++ = *pScan++ + 'a' - 'A'; // convert to lower case for case sensitve comparison later
|
*pDest++ = *pScan++ + 'a' - 'A'; // convert to lower case for case sensitve comparison later
|
||||||
} else {
|
} else {
|
||||||
*pDest++ = *pScan++;
|
*pDest++ = *pScan++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*pDest = '\0';
|
*pDest = '\0';
|
||||||
|
|
||||||
// Scan through whitespace, but don't advance to next line
|
// Scan through whitespace, but don't advance to next line
|
||||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
||||||
pScan++;
|
pScan++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cSymbols > 0) {
|
if(cSymbols > 0) {
|
||||||
|
|
||||||
if(strcmp(szSymbol[0], "newmtl") == 0 && cSymbols >= 2) {
|
if(strcmp(szSymbol[0], "newmtl") == 0 && cSymbols >= 2) {
|
||||||
|
|
||||||
pMaterial = new KRMaterial(*m_pContext, szSymbol[1]);
|
pMaterial = new KRMaterial(*m_pContext, szSymbol[1]);
|
||||||
m_materials[szSymbol[1]] = pMaterial;
|
m_materials[szSymbol[1]] = pMaterial;
|
||||||
}
|
}
|
||||||
if(pMaterial != NULL) {
|
if(pMaterial != NULL) {
|
||||||
if(strcmp(szSymbol[0], "alpha_mode") == 0) {
|
if(strcmp(szSymbol[0], "alpha_mode") == 0) {
|
||||||
if(cSymbols == 2) {
|
if(cSymbols == 2) {
|
||||||
if(strcmp(szSymbol[1], "test") == 0) {
|
if(strcmp(szSymbol[1], "test") == 0) {
|
||||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_TEST);
|
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_TEST);
|
||||||
} else if(strcmp(szSymbol[1], "blendoneside") == 0) {
|
} else if(strcmp(szSymbol[1], "blendoneside") == 0) {
|
||||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
|
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
|
||||||
} else if(strcmp(szSymbol[1], "blendtwoside") == 0) {
|
} else if(strcmp(szSymbol[1], "blendtwoside") == 0) {
|
||||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
|
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
|
||||||
} else {
|
} else {
|
||||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE);
|
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(strcmp(szSymbol[0], "ka") == 0) {
|
} else if(strcmp(szSymbol[0], "ka") == 0) {
|
||||||
char *pScan2 = szSymbol[1];
|
char *pScan2 = szSymbol[1];
|
||||||
float r = strtof(pScan2, &pScan2);
|
float r = strtof(pScan2, &pScan2);
|
||||||
if(cSymbols == 2) {
|
if(cSymbols == 2) {
|
||||||
pMaterial->setAmbient(Vector3(r, r, r));
|
pMaterial->setAmbient(Vector3::Create(r, r, r));
|
||||||
} else if(cSymbols == 4) {
|
} else if(cSymbols == 4) {
|
||||||
pScan2 = szSymbol[2];
|
pScan2 = szSymbol[2];
|
||||||
float g = strtof(pScan2, &pScan2);
|
float g = strtof(pScan2, &pScan2);
|
||||||
pScan2 = szSymbol[3];
|
pScan2 = szSymbol[3];
|
||||||
float b = strtof(pScan2, &pScan2);
|
float b = strtof(pScan2, &pScan2);
|
||||||
pMaterial->setAmbient(Vector3(r, g, b));
|
pMaterial->setAmbient(Vector3::Create(r, g, b));
|
||||||
}
|
}
|
||||||
} else if(strcmp(szSymbol[0], "kd") == 0) {
|
} else if(strcmp(szSymbol[0], "kd") == 0) {
|
||||||
char *pScan2 = szSymbol[1];
|
char *pScan2 = szSymbol[1];
|
||||||
float r = strtof(pScan2, &pScan2);
|
float r = strtof(pScan2, &pScan2);
|
||||||
if(cSymbols == 2) {
|
if(cSymbols == 2) {
|
||||||
pMaterial->setDiffuse(Vector3(r, r, r));
|
pMaterial->setDiffuse(Vector3::Create(r, r, r));
|
||||||
} else if(cSymbols == 4) {
|
} else if(cSymbols == 4) {
|
||||||
pScan2 = szSymbol[2];
|
pScan2 = szSymbol[2];
|
||||||
float g = strtof(pScan2, &pScan2);
|
float g = strtof(pScan2, &pScan2);
|
||||||
pScan2 = szSymbol[3];
|
pScan2 = szSymbol[3];
|
||||||
float b = strtof(pScan2, &pScan2);
|
float b = strtof(pScan2, &pScan2);
|
||||||
pMaterial->setDiffuse(Vector3(r, g, b));
|
pMaterial->setDiffuse(Vector3::Create(r, g, b));
|
||||||
}
|
}
|
||||||
} else if(strcmp(szSymbol[0], "ks") == 0) {
|
} else if(strcmp(szSymbol[0], "ks") == 0) {
|
||||||
char *pScan2 = szSymbol[1];
|
char *pScan2 = szSymbol[1];
|
||||||
float r = strtof(pScan2, &pScan2);
|
float r = strtof(pScan2, &pScan2);
|
||||||
if(cSymbols == 2) {
|
if(cSymbols == 2) {
|
||||||
pMaterial->setSpecular(Vector3(r, r, r));
|
pMaterial->setSpecular(Vector3::Create(r, r, r));
|
||||||
} else if(cSymbols == 4) {
|
} else if(cSymbols == 4) {
|
||||||
pScan2 = szSymbol[2];
|
pScan2 = szSymbol[2];
|
||||||
float g = strtof(pScan2, &pScan2);
|
float g = strtof(pScan2, &pScan2);
|
||||||
pScan2 = szSymbol[3];
|
pScan2 = szSymbol[3];
|
||||||
float b = strtof(pScan2, &pScan2);
|
float b = strtof(pScan2, &pScan2);
|
||||||
pMaterial->setSpecular(Vector3(r, g, b));
|
pMaterial->setSpecular(Vector3::Create(r, g, b));
|
||||||
}
|
}
|
||||||
} else if(strcmp(szSymbol[0], "kr") == 0) {
|
} else if(strcmp(szSymbol[0], "kr") == 0) {
|
||||||
char *pScan2 = szSymbol[1];
|
char *pScan2 = szSymbol[1];
|
||||||
float r = strtof(pScan2, &pScan2);
|
float r = strtof(pScan2, &pScan2);
|
||||||
if(cSymbols == 2) {
|
if(cSymbols == 2) {
|
||||||
pMaterial->setReflection(Vector3(r, r, r));
|
pMaterial->setReflection(Vector3::Create(r, r, r));
|
||||||
} else if(cSymbols == 4) {
|
} else if(cSymbols == 4) {
|
||||||
pScan2 = szSymbol[2];
|
pScan2 = szSymbol[2];
|
||||||
float g = strtof(pScan2, &pScan2);
|
float g = strtof(pScan2, &pScan2);
|
||||||
pScan2 = szSymbol[3];
|
pScan2 = szSymbol[3];
|
||||||
float b = strtof(pScan2, &pScan2);
|
float b = strtof(pScan2, &pScan2);
|
||||||
pMaterial->setReflection(Vector3(r, g, b));
|
pMaterial->setReflection(Vector3::Create(r, g, b));
|
||||||
}
|
}
|
||||||
} else if(strcmp(szSymbol[0], "tr") == 0) {
|
} else if(strcmp(szSymbol[0], "tr") == 0) {
|
||||||
char *pScan2 = szSymbol[1];
|
char *pScan2 = szSymbol[1];
|
||||||
float a = strtof(pScan2, &pScan2);
|
float a = strtof(pScan2, &pScan2);
|
||||||
pMaterial->setTransparency(a);
|
pMaterial->setTransparency(a);
|
||||||
} else if(strcmp(szSymbol[0], "ns") == 0) {
|
} else if(strcmp(szSymbol[0], "ns") == 0) {
|
||||||
char *pScan2 = szSymbol[1];
|
char *pScan2 = szSymbol[1];
|
||||||
float a = strtof(pScan2, &pScan2);
|
float a = strtof(pScan2, &pScan2);
|
||||||
pMaterial->setShininess(a);
|
pMaterial->setShininess(a);
|
||||||
} else if(strncmp(szSymbol[0], "map", 3) == 0) {
|
} else if(strncmp(szSymbol[0], "map", 3) == 0) {
|
||||||
// Truncate file extension
|
// Truncate file extension
|
||||||
char *pScan2 = szSymbol[1];
|
char *pScan2 = szSymbol[1];
|
||||||
char *pLastPeriod = NULL;
|
char *pLastPeriod = NULL;
|
||||||
while(*pScan2 != '\0') {
|
while(*pScan2 != '\0') {
|
||||||
if(*pScan2 == '.') {
|
if(*pScan2 == '.') {
|
||||||
pLastPeriod = pScan2;
|
pLastPeriod = pScan2;
|
||||||
}
|
}
|
||||||
pScan2++;
|
pScan2++;
|
||||||
}
|
}
|
||||||
if(pLastPeriod) {
|
if(pLastPeriod) {
|
||||||
*pLastPeriod = '\0';
|
*pLastPeriod = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 texture_scale = Vector2(1.0f, 1.0f);
|
Vector2 texture_scale = Vector2::Create(1.0f, 1.0f);
|
||||||
Vector2 texture_offset = Vector2(0.0f, 0.0f);
|
Vector2 texture_offset = Vector2::Create(0.0f, 0.0f);
|
||||||
|
|
||||||
int iScanSymbol = 2;
|
int iScanSymbol = 2;
|
||||||
int iScaleParam = -1;
|
int iScaleParam = -1;
|
||||||
int iOffsetParam = -1;
|
int iOffsetParam = -1;
|
||||||
while(iScanSymbol < cSymbols) {
|
while(iScanSymbol < cSymbols) {
|
||||||
if(strcmp(szSymbol[iScanSymbol], "-s") == 0) {
|
if(strcmp(szSymbol[iScanSymbol], "-s") == 0) {
|
||||||
// Scale
|
// Scale
|
||||||
iScaleParam = 0;
|
iScaleParam = 0;
|
||||||
iOffsetParam = -1;
|
iOffsetParam = -1;
|
||||||
} else if(strcmp(szSymbol[iScanSymbol], "-o") == 0) {
|
} else if(strcmp(szSymbol[iScanSymbol], "-o") == 0) {
|
||||||
// Offset
|
// Offset
|
||||||
iOffsetParam = 0;
|
iOffsetParam = 0;
|
||||||
iScaleParam = -1;
|
iScaleParam = -1;
|
||||||
} else {
|
} else {
|
||||||
char *pScan3 = szSymbol[iScanSymbol];
|
char *pScan3 = szSymbol[iScanSymbol];
|
||||||
float v = strtof(pScan3, &pScan3);
|
float v = strtof(pScan3, &pScan3);
|
||||||
if(iScaleParam == 0) {
|
if(iScaleParam == 0) {
|
||||||
texture_scale.x = v;
|
texture_scale.x = v;
|
||||||
iScaleParam++;
|
iScaleParam++;
|
||||||
} else if(iScaleParam == 1) {
|
} else if(iScaleParam == 1) {
|
||||||
texture_scale.y = v;
|
texture_scale.y = v;
|
||||||
iScaleParam++;
|
iScaleParam++;
|
||||||
} else if(iOffsetParam == 0) {
|
} else if(iOffsetParam == 0) {
|
||||||
texture_offset.x = v;
|
texture_offset.x = v;
|
||||||
iOffsetParam++;
|
iOffsetParam++;
|
||||||
} else if(iOffsetParam == 1) {
|
} else if(iOffsetParam == 1) {
|
||||||
texture_offset.y = v;
|
texture_offset.y = v;
|
||||||
iOffsetParam++;
|
iOffsetParam++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iScanSymbol++;
|
iScanSymbol++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strcmp(szSymbol[0], "map_ka") == 0) {
|
if(strcmp(szSymbol[0], "map_ka") == 0) {
|
||||||
pMaterial->setAmbientMap(szSymbol[1], texture_scale, texture_offset);
|
pMaterial->setAmbientMap(szSymbol[1], texture_scale, texture_offset);
|
||||||
} else if(strcmp(szSymbol[0], "map_kd") == 0) {
|
} else if(strcmp(szSymbol[0], "map_kd") == 0) {
|
||||||
pMaterial->setDiffuseMap(szSymbol[1], texture_scale, texture_offset);
|
pMaterial->setDiffuseMap(szSymbol[1], texture_scale, texture_offset);
|
||||||
} else if(strcmp(szSymbol[0], "map_ks") == 0) {
|
} else if(strcmp(szSymbol[0], "map_ks") == 0) {
|
||||||
pMaterial->setSpecularMap(szSymbol[1], texture_scale, texture_offset);
|
pMaterial->setSpecularMap(szSymbol[1], texture_scale, texture_offset);
|
||||||
} else if(strcmp(szSymbol[0], "map_normal") == 0) {
|
} else if(strcmp(szSymbol[0], "map_normal") == 0) {
|
||||||
pMaterial->setNormalMap(szSymbol[1], texture_scale, texture_offset);
|
pMaterial->setNormalMap(szSymbol[1], texture_scale, texture_offset);
|
||||||
} else if(strcmp(szSymbol[0], "map_reflection") == 0) {
|
} else if(strcmp(szSymbol[0], "map_reflection") == 0) {
|
||||||
pMaterial->setReflectionMap(szSymbol[1], texture_scale, texture_offset);
|
pMaterial->setReflectionMap(szSymbol[1], texture_scale, texture_offset);
|
||||||
} else if(strcmp(szSymbol[0], "map_reflectioncube") == 0) {
|
} else if(strcmp(szSymbol[0], "map_reflectioncube") == 0) {
|
||||||
pMaterial->setReflectionCube(szSymbol[1]);
|
pMaterial->setReflectionCube(szSymbol[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
data->unlock();
|
data->unlock();
|
||||||
delete data;
|
delete data;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
3208
kraken/KRMesh.cpp
3208
kraken/KRMesh.cpp
File diff suppressed because it is too large
Load Diff
580
kraken/KRMesh.h
580
kraken/KRMesh.h
@@ -1,290 +1,292 @@
|
|||||||
//
|
//
|
||||||
// KRMesh.h
|
// KRMesh.h
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
// permitted provided that the following conditions are met:
|
// permitted provided that the following conditions are met:
|
||||||
//
|
//
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
// conditions and the following disclaimer.
|
// conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
// provided with the distribution.
|
// provided with the distribution.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
// or implied, of Kearwood Gilbert.
|
// or implied, of Kearwood Gilbert.
|
||||||
//
|
//
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
#include "KRContext.h"
|
#include "KRContext.h"
|
||||||
#include "KRBone.h"
|
#include "KRBone.h"
|
||||||
#include "KRMeshManager.h"
|
#include "KRMeshManager.h"
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
using namespace kraken;
|
#include "hydra.h"
|
||||||
|
|
||||||
#define MAX_VBO_SIZE 65535
|
using namespace kraken;
|
||||||
#define KRENGINE_MAX_BONE_WEIGHTS_PER_VERTEX 4
|
|
||||||
#define KRENGINE_MAX_NAME_LENGTH 256
|
#define MAX_VBO_SIZE 65535
|
||||||
// MAX_VBO_SIZE must be divisible by 3 so triangles aren't split across VBO objects...
|
#define KRENGINE_MAX_BONE_WEIGHTS_PER_VERTEX 4
|
||||||
|
#define KRENGINE_MAX_NAME_LENGTH 256
|
||||||
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
// MAX_VBO_SIZE must be divisible by 3 so triangles aren't split across VBO objects...
|
||||||
|
|
||||||
#ifndef KRMesh_I
|
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
||||||
#define KRMesh_I
|
|
||||||
|
#ifndef KRMesh_I
|
||||||
#include "KRMaterialManager.h"
|
#define KRMesh_I
|
||||||
#include "KRCamera.h"
|
|
||||||
#include "KRViewport.h"
|
#include "KRMaterialManager.h"
|
||||||
|
#include "KRCamera.h"
|
||||||
class KRMaterial;
|
#include "KRViewport.h"
|
||||||
class KRNode;
|
|
||||||
|
class KRMaterial;
|
||||||
class KRMesh : public KRResource {
|
class KRNode;
|
||||||
|
|
||||||
public:
|
class KRMesh : public KRResource {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
KRMesh(KRContext &context, std::string name, KRDataBlock *data);
|
|
||||||
KRMesh(KRContext &context, std::string name);
|
|
||||||
virtual ~KRMesh();
|
KRMesh(KRContext &context, std::string name, KRDataBlock *data);
|
||||||
|
KRMesh(KRContext &context, std::string name);
|
||||||
kraken_stream_level getStreamLevel();
|
virtual ~KRMesh();
|
||||||
void preStream(float lodCoverage);
|
|
||||||
|
kraken_stream_level getStreamLevel();
|
||||||
bool hasTransparency();
|
void preStream(float lodCoverage);
|
||||||
|
|
||||||
typedef enum {
|
bool hasTransparency();
|
||||||
KRENGINE_ATTRIB_VERTEX = 0,
|
|
||||||
KRENGINE_ATTRIB_NORMAL,
|
typedef enum {
|
||||||
KRENGINE_ATTRIB_TANGENT,
|
KRENGINE_ATTRIB_VERTEX = 0,
|
||||||
KRENGINE_ATTRIB_TEXUVA,
|
KRENGINE_ATTRIB_NORMAL,
|
||||||
KRENGINE_ATTRIB_TEXUVB,
|
KRENGINE_ATTRIB_TANGENT,
|
||||||
KRENGINE_ATTRIB_BONEINDEXES,
|
KRENGINE_ATTRIB_TEXUVA,
|
||||||
KRENGINE_ATTRIB_BONEWEIGHTS,
|
KRENGINE_ATTRIB_TEXUVB,
|
||||||
KRENGINE_ATTRIB_VERTEX_SHORT,
|
KRENGINE_ATTRIB_BONEINDEXES,
|
||||||
KRENGINE_ATTRIB_NORMAL_SHORT,
|
KRENGINE_ATTRIB_BONEWEIGHTS,
|
||||||
KRENGINE_ATTRIB_TANGENT_SHORT,
|
KRENGINE_ATTRIB_VERTEX_SHORT,
|
||||||
KRENGINE_ATTRIB_TEXUVA_SHORT,
|
KRENGINE_ATTRIB_NORMAL_SHORT,
|
||||||
KRENGINE_ATTRIB_TEXUVB_SHORT,
|
KRENGINE_ATTRIB_TANGENT_SHORT,
|
||||||
KRENGINE_NUM_ATTRIBUTES
|
KRENGINE_ATTRIB_TEXUVA_SHORT,
|
||||||
} vertex_attrib_t;
|
KRENGINE_ATTRIB_TEXUVB_SHORT,
|
||||||
|
KRENGINE_NUM_ATTRIBUTES
|
||||||
typedef enum {
|
} vertex_attrib_t;
|
||||||
KRENGINE_MODEL_FORMAT_TRIANGLES = 0,
|
|
||||||
KRENGINE_MODEL_FORMAT_STRIP,
|
typedef enum {
|
||||||
KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES,
|
KRENGINE_MODEL_FORMAT_TRIANGLES = 0,
|
||||||
KRENGINE_MODEL_FORMAT_INDEXED_STRIP
|
KRENGINE_MODEL_FORMAT_STRIP,
|
||||||
} model_format_t;
|
KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES,
|
||||||
|
KRENGINE_MODEL_FORMAT_INDEXED_STRIP
|
||||||
typedef struct {
|
} model_format_t;
|
||||||
model_format_t format;
|
|
||||||
std::vector<Vector3> vertices;
|
typedef struct {
|
||||||
std::vector<__uint16_t> vertex_indexes;
|
model_format_t format;
|
||||||
std::vector<std::pair<int, int> > vertex_index_bases;
|
std::vector<Vector3> vertices;
|
||||||
std::vector<Vector2> uva;
|
std::vector<__uint16_t> vertex_indexes;
|
||||||
std::vector<Vector2> uvb;
|
std::vector<std::pair<int, int> > vertex_index_bases;
|
||||||
std::vector<Vector3> normals;
|
std::vector<Vector2> uva;
|
||||||
std::vector<Vector3> tangents;
|
std::vector<Vector2> uvb;
|
||||||
std::vector<int> submesh_starts;
|
std::vector<Vector3> normals;
|
||||||
std::vector<int> submesh_lengths;
|
std::vector<Vector3> tangents;
|
||||||
std::vector<std::string> material_names;
|
std::vector<int> submesh_starts;
|
||||||
std::vector<std::string> bone_names;
|
std::vector<int> submesh_lengths;
|
||||||
std::vector<std::vector<int> > bone_indexes;
|
std::vector<std::string> material_names;
|
||||||
std::vector<Matrix4> bone_bind_poses;
|
std::vector<std::string> bone_names;
|
||||||
std::vector<std::vector<float> > bone_weights;
|
std::vector<std::vector<int> > bone_indexes;
|
||||||
} mesh_info;
|
std::vector<Matrix4> bone_bind_poses;
|
||||||
|
std::vector<std::vector<float> > bone_weights;
|
||||||
void render(const std::string &object_name, KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, const Matrix4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const std::vector<KRBone *> &bones, const Vector3 &rim_color, float rim_power, float lod_coverage = 0.0f);
|
} mesh_info;
|
||||||
|
|
||||||
std::string m_lodBaseName;
|
void render(const std::string &object_name, KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, const Matrix4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const std::vector<KRBone *> &bones, const Vector3 &rim_color, float rim_power, float lod_coverage = 0.0f);
|
||||||
|
|
||||||
virtual std::string getExtension();
|
std::string m_lodBaseName;
|
||||||
virtual bool save(const std::string& path);
|
|
||||||
virtual bool save(KRDataBlock &data);
|
virtual std::string getExtension();
|
||||||
|
virtual bool save(const std::string& path);
|
||||||
void LoadData(const mesh_info &mi, bool calculate_normals, bool calculate_tangents);
|
virtual bool save(KRDataBlock &data);
|
||||||
void loadPack(KRDataBlock *data);
|
|
||||||
|
void LoadData(const mesh_info &mi, bool calculate_normals, bool calculate_tangents);
|
||||||
void convertToIndexed();
|
void loadPack(KRDataBlock *data);
|
||||||
void optimize();
|
|
||||||
void optimizeIndexes();
|
void convertToIndexed();
|
||||||
|
void optimize();
|
||||||
void renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const std::string &object_name, const std::string &material_name, float lodCoverage);
|
void optimizeIndexes();
|
||||||
|
|
||||||
GLfloat getMaxDimension();
|
void renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const std::string &object_name, const std::string &material_name, float lodCoverage);
|
||||||
|
|
||||||
Vector3 getMinPoint() const;
|
GLfloat getMaxDimension();
|
||||||
Vector3 getMaxPoint() const;
|
|
||||||
|
Vector3 getMinPoint() const;
|
||||||
class Submesh {
|
Vector3 getMaxPoint() const;
|
||||||
public:
|
|
||||||
Submesh() {};
|
class Submesh {
|
||||||
~Submesh() {
|
public:
|
||||||
for(auto itr = vbo_data_blocks.begin(); itr != vbo_data_blocks.end(); itr++) {
|
Submesh() {};
|
||||||
delete (*itr);
|
~Submesh() {
|
||||||
}
|
for(auto itr = vbo_data_blocks.begin(); itr != vbo_data_blocks.end(); itr++) {
|
||||||
for(auto itr = vertex_data_blocks.begin(); itr != vertex_data_blocks.end(); itr++) {
|
delete (*itr);
|
||||||
delete (*itr);
|
}
|
||||||
}
|
for(auto itr = vertex_data_blocks.begin(); itr != vertex_data_blocks.end(); itr++) {
|
||||||
for(auto itr = index_data_blocks.begin(); itr != index_data_blocks.end(); itr++) {
|
delete (*itr);
|
||||||
delete (*itr);
|
}
|
||||||
}
|
for(auto itr = index_data_blocks.begin(); itr != index_data_blocks.end(); itr++) {
|
||||||
};
|
delete (*itr);
|
||||||
|
}
|
||||||
GLint start_vertex;
|
};
|
||||||
GLsizei vertex_count;
|
|
||||||
char szMaterialName[KRENGINE_MAX_NAME_LENGTH];
|
GLint start_vertex;
|
||||||
vector<KRDataBlock *> vertex_data_blocks;
|
GLsizei vertex_count;
|
||||||
vector<KRDataBlock *> index_data_blocks;
|
char szMaterialName[KRENGINE_MAX_NAME_LENGTH];
|
||||||
vector<KRMeshManager::KRVBOData *> vbo_data_blocks;
|
vector<KRDataBlock *> vertex_data_blocks;
|
||||||
};
|
vector<KRDataBlock *> index_data_blocks;
|
||||||
|
vector<KRMeshManager::KRVBOData *> vbo_data_blocks;
|
||||||
typedef struct {
|
};
|
||||||
union {
|
|
||||||
struct { // For Indexed triangles / strips
|
typedef struct {
|
||||||
uint16_t index_group;
|
union {
|
||||||
uint16_t index_group_offset;
|
struct { // For Indexed triangles / strips
|
||||||
};
|
uint16_t index_group;
|
||||||
int32_t start_vertex; // For non-indexed trigangles / strips
|
uint16_t index_group_offset;
|
||||||
};
|
};
|
||||||
int32_t vertex_count;
|
int32_t start_vertex; // For non-indexed trigangles / strips
|
||||||
char szName[KRENGINE_MAX_NAME_LENGTH];
|
};
|
||||||
} pack_material;
|
int32_t vertex_count;
|
||||||
|
char szName[KRENGINE_MAX_NAME_LENGTH];
|
||||||
typedef struct {
|
} pack_material;
|
||||||
char szName[KRENGINE_MAX_NAME_LENGTH];
|
|
||||||
float bind_pose[16];
|
typedef struct {
|
||||||
} pack_bone;
|
char szName[KRENGINE_MAX_NAME_LENGTH];
|
||||||
|
float bind_pose[16];
|
||||||
int getLODCoverage() const;
|
} pack_bone;
|
||||||
std::string getLODBaseName() const;
|
|
||||||
|
int getLODCoverage() const;
|
||||||
|
std::string getLODBaseName() const;
|
||||||
static bool lod_sort_predicate(const KRMesh *m1, const KRMesh *m2);
|
|
||||||
bool has_vertex_attribute(vertex_attrib_t attribute_type) const;
|
|
||||||
static bool has_vertex_attribute(int vertex_attrib_flags, vertex_attrib_t attribute_type);
|
static bool lod_sort_predicate(const KRMesh *m1, const KRMesh *m2);
|
||||||
|
bool has_vertex_attribute(vertex_attrib_t attribute_type) const;
|
||||||
int getSubmeshCount() const;
|
static bool has_vertex_attribute(int vertex_attrib_flags, vertex_attrib_t attribute_type);
|
||||||
int getVertexCount(int submesh) const;
|
|
||||||
int getTriangleVertexIndex(int submesh, int index) const;
|
int getSubmeshCount() const;
|
||||||
Vector3 getVertexPosition(int index) const;
|
int getVertexCount(int submesh) const;
|
||||||
Vector3 getVertexNormal(int index) const;
|
int getTriangleVertexIndex(int submesh, int index) const;
|
||||||
Vector3 getVertexTangent(int index) const;
|
Vector3 getVertexPosition(int index) const;
|
||||||
Vector2 getVertexUVA(int index) const;
|
Vector3 getVertexNormal(int index) const;
|
||||||
Vector2 getVertexUVB(int index) const;
|
Vector3 getVertexTangent(int index) const;
|
||||||
int getBoneIndex(int index, int weight_index) const;
|
Vector2 getVertexUVA(int index) const;
|
||||||
float getBoneWeight(int index, int weight_index) const;
|
Vector2 getVertexUVB(int index) const;
|
||||||
|
int getBoneIndex(int index, int weight_index) const;
|
||||||
void setVertexPosition(int index, const Vector3 &v);
|
float getBoneWeight(int index, int weight_index) const;
|
||||||
void setVertexNormal(int index, const Vector3 &v);
|
|
||||||
void setVertexTangent(int index, const Vector3 & v);
|
void setVertexPosition(int index, const Vector3 &v);
|
||||||
void setVertexUVA(int index, const Vector2 &v);
|
void setVertexNormal(int index, const Vector3 &v);
|
||||||
void setVertexUVB(int index, const Vector2 &v);
|
void setVertexTangent(int index, const Vector3 & v);
|
||||||
void setBoneIndex(int index, int weight_index, int bone_index);
|
void setVertexUVA(int index, const Vector2 &v);
|
||||||
void setBoneWeight(int index, int weight_index, float bone_weight);
|
void setVertexUVB(int index, const Vector2 &v);
|
||||||
|
void setBoneIndex(int index, int weight_index, int bone_index);
|
||||||
static size_t VertexSizeForAttributes(__int32_t vertex_attrib_flags);
|
void setBoneWeight(int index, int weight_index, float bone_weight);
|
||||||
static size_t AttributeOffset(__int32_t vertex_attrib, __int32_t vertex_attrib_flags);
|
|
||||||
|
static size_t VertexSizeForAttributes(__int32_t vertex_attrib_flags);
|
||||||
int getBoneCount();
|
static size_t AttributeOffset(__int32_t vertex_attrib, __int32_t vertex_attrib_flags);
|
||||||
char *getBoneName(int bone_index);
|
|
||||||
Matrix4 getBoneBindPose(int bone_index);
|
int getBoneCount();
|
||||||
|
char *getBoneName(int bone_index);
|
||||||
|
Matrix4 getBoneBindPose(int bone_index);
|
||||||
model_format_t getModelFormat() const;
|
|
||||||
|
|
||||||
bool lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo) const;
|
model_format_t getModelFormat() const;
|
||||||
bool rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo) const;
|
|
||||||
bool sphereCast(const Matrix4 &model_to_world, const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo) const;
|
bool lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo) const;
|
||||||
|
bool rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo) const;
|
||||||
static int GetLODCoverage(const std::string &name);
|
bool sphereCast(const Matrix4 &model_to_world, const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo) const;
|
||||||
|
|
||||||
void load(); // Load immediately into the GPU rather than passing through the streamer
|
static int GetLODCoverage(const std::string &name);
|
||||||
|
|
||||||
protected:
|
void load(); // Load immediately into the GPU rather than passing through the streamer
|
||||||
bool m_constant; // TRUE if this should be always loaded and should not be passed through the streamer
|
|
||||||
|
protected:
|
||||||
private:
|
bool m_constant; // TRUE if this should be always loaded and should not be passed through the streamer
|
||||||
KRDataBlock *m_pData;
|
|
||||||
KRDataBlock *m_pMetaData;
|
private:
|
||||||
KRDataBlock *m_pIndexBaseData;
|
KRDataBlock *m_pData;
|
||||||
|
KRDataBlock *m_pMetaData;
|
||||||
void getSubmeshes();
|
KRDataBlock *m_pIndexBaseData;
|
||||||
void getMaterials();
|
|
||||||
|
void getSubmeshes();
|
||||||
static bool rayCast(const Vector3 &start, const Vector3 &dir, const Triangle3 &tri, const Vector3 &tri_n0, const Vector3 &tri_n1, const Vector3 &tri_n2, HitInfo &hitinfo);
|
void getMaterials();
|
||||||
static bool sphereCast(const Matrix4 &model_to_world, const Vector3 &v0, const Vector3 &v1, float radius, const Triangle3 &tri, HitInfo &hitinfo);
|
|
||||||
|
static bool rayCast(const Vector3 &start, const Vector3 &dir, const Triangle3 &tri, const Vector3 &tri_n0, const Vector3 &tri_n1, const Vector3 &tri_n2, HitInfo &hitinfo);
|
||||||
int m_lodCoverage; // This LOD level is activated when the bounding box of the model will cover less than this percent of the screen (100 = highest detail model)
|
static bool sphereCast(const Matrix4 &model_to_world, const Vector3 &v0, const Vector3 &v1, float radius, const Triangle3 &tri, HitInfo &hitinfo);
|
||||||
vector<KRMaterial *> m_materials;
|
|
||||||
set<KRMaterial *> m_uniqueMaterials;
|
int m_lodCoverage; // This LOD level is activated when the bounding box of the model will cover less than this percent of the screen (100 = highest detail model)
|
||||||
|
vector<KRMaterial *> m_materials;
|
||||||
bool m_hasTransparency;
|
set<KRMaterial *> m_uniqueMaterials;
|
||||||
|
|
||||||
|
bool m_hasTransparency;
|
||||||
Vector3 m_minPoint, m_maxPoint;
|
|
||||||
|
|
||||||
|
Vector3 m_minPoint, m_maxPoint;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char szTag[16];
|
|
||||||
int32_t model_format; // 0 == Triangle list, 1 == Triangle strips, 2 == Indexed triangle list, 3 == Indexed triangle strips, rest are reserved (model_format_t enum)
|
typedef struct {
|
||||||
int32_t vertex_attrib_flags;
|
char szTag[16];
|
||||||
int32_t vertex_count;
|
int32_t model_format; // 0 == Triangle list, 1 == Triangle strips, 2 == Indexed triangle list, 3 == Indexed triangle strips, rest are reserved (model_format_t enum)
|
||||||
int32_t submesh_count;
|
int32_t vertex_attrib_flags;
|
||||||
int32_t bone_count;
|
int32_t vertex_count;
|
||||||
float minx, miny, minz, maxx, maxy, maxz; // Axis aligned bounding box, in model's coordinate space
|
int32_t submesh_count;
|
||||||
int32_t index_count;
|
int32_t bone_count;
|
||||||
int32_t index_base_count;
|
float minx, miny, minz, maxx, maxy, maxz; // Axis aligned bounding box, in model's coordinate space
|
||||||
unsigned char reserved[444]; // Pad out to 512 bytes
|
int32_t index_count;
|
||||||
} pack_header;
|
int32_t index_base_count;
|
||||||
|
unsigned char reserved[444]; // Pad out to 512 bytes
|
||||||
vector<Submesh *> m_submeshes;
|
} pack_header;
|
||||||
int m_vertex_attribute_offset[KRENGINE_NUM_ATTRIBUTES];
|
|
||||||
int m_vertex_size;
|
vector<Submesh *> m_submeshes;
|
||||||
void updateAttributeOffsets();
|
int m_vertex_attribute_offset[KRENGINE_NUM_ATTRIBUTES];
|
||||||
|
int m_vertex_size;
|
||||||
void setName(const std::string name);
|
void updateAttributeOffsets();
|
||||||
|
|
||||||
|
void setName(const std::string name);
|
||||||
|
|
||||||
pack_material *getSubmesh(int mesh_index) const;
|
|
||||||
unsigned char *getVertexData() const;
|
|
||||||
size_t getVertexDataOffset() const;
|
pack_material *getSubmesh(int mesh_index) const;
|
||||||
unsigned char *getVertexData(int index) const;
|
unsigned char *getVertexData() const;
|
||||||
__uint16_t *getIndexData() const;
|
size_t getVertexDataOffset() const;
|
||||||
size_t getIndexDataOffset() const;
|
unsigned char *getVertexData(int index) const;
|
||||||
__uint32_t *getIndexBaseData() const;
|
__uint16_t *getIndexData() const;
|
||||||
pack_header *getHeader() const;
|
size_t getIndexDataOffset() const;
|
||||||
pack_bone *getBone(int index);
|
__uint32_t *getIndexBaseData() const;
|
||||||
|
pack_header *getHeader() const;
|
||||||
|
pack_bone *getBone(int index);
|
||||||
void getIndexedRange(int index_group, int &start_index_offset, int &start_vertex_offset, int &index_count, int &vertex_count) const;
|
|
||||||
|
|
||||||
void releaseData();
|
void getIndexedRange(int index_group, int &start_index_offset, int &start_vertex_offset, int &index_count, int &vertex_count) const;
|
||||||
|
|
||||||
void createDataBlocks(KRMeshManager::KRVBOData::vbo_type t);
|
void releaseData();
|
||||||
|
|
||||||
|
void createDataBlocks(KRMeshManager::KRVBOData::vbo_type t);
|
||||||
};
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // KRMesh_I
|
#endif // KRMesh_I
|
||||||
@@ -1,69 +1,69 @@
|
|||||||
//
|
//
|
||||||
// KRMeshCube.cpp
|
// KRMeshCube.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
// permitted provided that the following conditions are met:
|
// permitted provided that the following conditions are met:
|
||||||
//
|
//
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
// conditions and the following disclaimer.
|
// conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
// provided with the distribution.
|
// provided with the distribution.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
// or implied, of Kearwood Gilbert.
|
// or implied, of Kearwood Gilbert.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KRMeshCube.h"
|
#include "KRMeshCube.h"
|
||||||
|
|
||||||
|
|
||||||
KRMeshCube::KRMeshCube(KRContext &context) : KRMesh(context, "__cube")
|
KRMeshCube::KRMeshCube(KRContext &context) : KRMesh(context, "__cube")
|
||||||
{
|
{
|
||||||
m_constant = true;
|
m_constant = true;
|
||||||
|
|
||||||
KRMesh::mesh_info mi;
|
KRMesh::mesh_info mi;
|
||||||
|
|
||||||
mi.vertices.push_back(Vector3(1.0, 1.0, 1.0));
|
mi.vertices.push_back(Vector3::Create(1.0, 1.0, 1.0));
|
||||||
mi.vertices.push_back(Vector3(-1.0, 1.0, 1.0));
|
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, 1.0));
|
||||||
mi.vertices.push_back(Vector3(1.0,-1.0, 1.0));
|
mi.vertices.push_back(Vector3::Create(1.0,-1.0, 1.0));
|
||||||
mi.vertices.push_back(Vector3(-1.0,-1.0, 1.0));
|
mi.vertices.push_back(Vector3::Create(-1.0,-1.0, 1.0));
|
||||||
mi.vertices.push_back(Vector3(-1.0,-1.0,-1.0));
|
mi.vertices.push_back(Vector3::Create(-1.0,-1.0,-1.0));
|
||||||
mi.vertices.push_back(Vector3(-1.0, 1.0, 1.0));
|
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, 1.0));
|
||||||
mi.vertices.push_back(Vector3(-1.0, 1.0,-1.0));
|
mi.vertices.push_back(Vector3::Create(-1.0, 1.0,-1.0));
|
||||||
mi.vertices.push_back(Vector3(1.0, 1.0, 1.0));
|
mi.vertices.push_back(Vector3::Create(1.0, 1.0, 1.0));
|
||||||
mi.vertices.push_back(Vector3(1.0, 1.0,-1.0));
|
mi.vertices.push_back(Vector3::Create(1.0, 1.0,-1.0));
|
||||||
mi.vertices.push_back(Vector3(1.0,-1.0, 1.0));
|
mi.vertices.push_back(Vector3::Create(1.0,-1.0, 1.0));
|
||||||
mi.vertices.push_back(Vector3(1.0,-1.0,-1.0));
|
mi.vertices.push_back(Vector3::Create(1.0,-1.0,-1.0));
|
||||||
mi.vertices.push_back(Vector3(-1.0,-1.0,-1.0));
|
mi.vertices.push_back(Vector3::Create(-1.0,-1.0,-1.0));
|
||||||
mi.vertices.push_back(Vector3(1.0, 1.0,-1.0));
|
mi.vertices.push_back(Vector3::Create(1.0, 1.0,-1.0));
|
||||||
mi.vertices.push_back(Vector3(-1.0, 1.0,-1.0));
|
mi.vertices.push_back(Vector3::Create(-1.0, 1.0,-1.0));
|
||||||
|
|
||||||
|
|
||||||
mi.submesh_starts.push_back(0);
|
mi.submesh_starts.push_back(0);
|
||||||
mi.submesh_lengths.push_back(mi.vertices.size());
|
mi.submesh_lengths.push_back(mi.vertices.size());
|
||||||
mi.material_names.push_back("");
|
mi.material_names.push_back("");
|
||||||
mi.format = KRENGINE_MODEL_FORMAT_STRIP;
|
mi.format = KRENGINE_MODEL_FORMAT_STRIP;
|
||||||
|
|
||||||
|
|
||||||
LoadData(mi, true, true);
|
LoadData(mi, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
KRMeshCube::~KRMeshCube()
|
KRMeshCube::~KRMeshCube()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,207 +1,207 @@
|
|||||||
//
|
//
|
||||||
// KRMeshManager.h
|
// KRMeshManager.h
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
// permitted provided that the following conditions are met:
|
// permitted provided that the following conditions are met:
|
||||||
//
|
//
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
// conditions and the following disclaimer.
|
// conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
// provided with the distribution.
|
// provided with the distribution.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
// or implied, of Kearwood Gilbert.
|
// or implied, of Kearwood Gilbert.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef KRMESHMANAGER_H
|
#ifndef KRMESHMANAGER_H
|
||||||
#define KRMESHMANAGER_H
|
#define KRMESHMANAGER_H
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
#include "KRContextObject.h"
|
#include "KRContextObject.h"
|
||||||
#include "KRDataBlock.h"
|
#include "KRDataBlock.h"
|
||||||
#include "KRNode.h"
|
#include "KRNode.h"
|
||||||
|
|
||||||
class KRContext;
|
class KRContext;
|
||||||
class KRMesh;
|
class KRMesh;
|
||||||
|
|
||||||
class KRMeshManager : public KRContextObject {
|
class KRMeshManager : public KRContextObject {
|
||||||
public:
|
public:
|
||||||
static const int KRENGINE_MAX_VOLUMETRIC_PLANES=500;
|
static const int KRENGINE_MAX_VOLUMETRIC_PLANES=500;
|
||||||
static const int KRENGINE_MAX_RANDOM_PARTICLES=150000;
|
static const int KRENGINE_MAX_RANDOM_PARTICLES=150000;
|
||||||
|
|
||||||
KRMeshManager(KRContext &context);
|
KRMeshManager(KRContext &context);
|
||||||
virtual ~KRMeshManager();
|
virtual ~KRMeshManager();
|
||||||
|
|
||||||
void startFrame(float deltaTime);
|
void startFrame(float deltaTime);
|
||||||
void endFrame(float deltaTime);
|
void endFrame(float deltaTime);
|
||||||
void firstFrame();
|
void firstFrame();
|
||||||
|
|
||||||
KRMesh *loadModel(const char *szName, KRDataBlock *pData);
|
KRMesh *loadModel(const char *szName, KRDataBlock *pData);
|
||||||
std::vector<KRMesh *> getModel(const char *szName);
|
std::vector<KRMesh *> getModel(const char *szName);
|
||||||
void addModel(KRMesh *model);
|
void addModel(KRMesh *model);
|
||||||
|
|
||||||
std::vector<std::string> getModelNames();
|
std::vector<std::string> getModelNames();
|
||||||
unordered_multimap<std::string, KRMesh *> &getModels();
|
unordered_multimap<std::string, KRMesh *> &getModels();
|
||||||
|
|
||||||
class KRVBOData {
|
class KRVBOData {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
STREAMING,
|
STREAMING,
|
||||||
CONSTANT,
|
CONSTANT,
|
||||||
TEMPORARY
|
TEMPORARY
|
||||||
} vbo_type;
|
} vbo_type;
|
||||||
|
|
||||||
KRVBOData();
|
KRVBOData();
|
||||||
KRVBOData(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t);
|
KRVBOData(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t);
|
||||||
void init(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t);
|
void init(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t);
|
||||||
~KRVBOData();
|
~KRVBOData();
|
||||||
|
|
||||||
|
|
||||||
KRDataBlock *m_data;
|
KRDataBlock *m_data;
|
||||||
KRDataBlock *m_index_data;
|
KRDataBlock *m_index_data;
|
||||||
|
|
||||||
bool isVBOLoaded() { return m_is_vbo_loaded; }
|
bool isVBOLoaded() { return m_is_vbo_loaded; }
|
||||||
bool isVBOReady() { return m_is_vbo_ready; }
|
bool isVBOReady() { return m_is_vbo_ready; }
|
||||||
void load();
|
void load();
|
||||||
void unload();
|
void unload();
|
||||||
void bind();
|
void bind();
|
||||||
|
|
||||||
// Disable copy constructors
|
// Disable copy constructors
|
||||||
KRVBOData(const KRVBOData& o) = delete;
|
KRVBOData(const KRVBOData& o) = delete;
|
||||||
KRVBOData(KRVBOData& o) = delete;
|
KRVBOData& operator=(const KRVBOData& o) = delete;
|
||||||
|
|
||||||
long getSize() { return m_size; }
|
long getSize() { return m_size; }
|
||||||
|
|
||||||
void resetPoolExpiry(float lodCoverage);
|
void resetPoolExpiry(float lodCoverage);
|
||||||
long getLastFrameUsed() { return m_last_frame_used; }
|
long getLastFrameUsed() { return m_last_frame_used; }
|
||||||
|
|
||||||
vbo_type getType() { return m_type; }
|
vbo_type getType() { return m_type; }
|
||||||
|
|
||||||
float getStreamPriority();
|
float getStreamPriority();
|
||||||
|
|
||||||
void _swapHandles();
|
void _swapHandles();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KRMeshManager *m_manager;
|
KRMeshManager *m_manager;
|
||||||
int m_vertex_attrib_flags;
|
int m_vertex_attrib_flags;
|
||||||
GLuint m_vbo_handle;
|
GLuint m_vbo_handle;
|
||||||
GLuint m_vbo_handle_indexes;
|
GLuint m_vbo_handle_indexes;
|
||||||
GLuint m_vao_handle;
|
GLuint m_vao_handle;
|
||||||
GLsizeiptr m_size;
|
GLsizeiptr m_size;
|
||||||
|
|
||||||
long m_last_frame_used;
|
long m_last_frame_used;
|
||||||
float m_last_frame_max_lod_coverage;
|
float m_last_frame_max_lod_coverage;
|
||||||
vbo_type m_type;
|
vbo_type m_type;
|
||||||
bool m_static_vbo;
|
bool m_static_vbo;
|
||||||
bool m_is_vbo_loaded;
|
bool m_is_vbo_loaded;
|
||||||
bool m_is_vbo_ready;
|
bool m_is_vbo_ready;
|
||||||
};
|
};
|
||||||
|
|
||||||
void bindVBO(KRVBOData *vbo_data, float lodCoverage);
|
void bindVBO(KRVBOData *vbo_data, float lodCoverage);
|
||||||
void bindVBO(KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, float lodCoverage);
|
void bindVBO(KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, float lodCoverage);
|
||||||
void unbindVBO();
|
void unbindVBO();
|
||||||
long getMemUsed();
|
long getMemUsed();
|
||||||
long getMemActive();
|
long getMemActive();
|
||||||
|
|
||||||
static void configureAttribs(__int32_t attributes);
|
static void configureAttribs(__int32_t attributes);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GLfloat x;
|
GLfloat x;
|
||||||
GLfloat y;
|
GLfloat y;
|
||||||
GLfloat z;
|
GLfloat z;
|
||||||
} Vector3D;
|
} Vector3D;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GLfloat u;
|
GLfloat u;
|
||||||
GLfloat v;
|
GLfloat v;
|
||||||
} TexCoord;
|
} TexCoord;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Vector3D vertex;
|
Vector3D vertex;
|
||||||
TexCoord uva;
|
TexCoord uva;
|
||||||
} RandomParticleVertexData;
|
} RandomParticleVertexData;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Vector3D vertex;
|
Vector3D vertex;
|
||||||
} VolumetricLightingVertexData;
|
} VolumetricLightingVertexData;
|
||||||
|
|
||||||
|
|
||||||
KRDataBlock &getRandomParticles();
|
KRDataBlock &getRandomParticles();
|
||||||
KRDataBlock &getVolumetricLightingVertexes();
|
KRDataBlock &getVolumetricLightingVertexes();
|
||||||
|
|
||||||
|
|
||||||
long getMemoryTransferedThisFrame();
|
long getMemoryTransferedThisFrame();
|
||||||
|
|
||||||
int getActiveVBOCount();
|
int getActiveVBOCount();
|
||||||
|
|
||||||
struct draw_call_info {
|
struct draw_call_info {
|
||||||
KRNode::RenderPass pass;
|
KRNode::RenderPass pass;
|
||||||
char object_name[256];
|
char object_name[256];
|
||||||
char material_name[256];
|
char material_name[256];
|
||||||
int vertex_count;
|
int vertex_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
void log_draw_call(KRNode::RenderPass pass, const std::string &object_name, const std::string &material_name, int vertex_count);
|
void log_draw_call(KRNode::RenderPass pass, const std::string &object_name, const std::string &material_name, int vertex_count);
|
||||||
std::vector<draw_call_info> getDrawCalls();
|
std::vector<draw_call_info> getDrawCalls();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
KRVBOData KRENGINE_VBO_DATA_3D_CUBE_VERTICES;
|
KRVBOData KRENGINE_VBO_DATA_3D_CUBE_VERTICES;
|
||||||
KRVBOData KRENGINE_VBO_DATA_2D_SQUARE_VERTICES;
|
KRVBOData KRENGINE_VBO_DATA_2D_SQUARE_VERTICES;
|
||||||
|
|
||||||
void doStreaming(long &memoryRemaining, long &memoryRemainingThisFrame);
|
void doStreaming(long &memoryRemaining, long &memoryRemainingThisFrame);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KRDataBlock KRENGINE_VBO_3D_CUBE_VERTICES, KRENGINE_VBO_3D_CUBE_INDEXES;
|
KRDataBlock KRENGINE_VBO_3D_CUBE_VERTICES, KRENGINE_VBO_3D_CUBE_INDEXES;
|
||||||
__int32_t KRENGINE_VBO_3D_CUBE_ATTRIBS;
|
__int32_t KRENGINE_VBO_3D_CUBE_ATTRIBS;
|
||||||
KRDataBlock KRENGINE_VBO_2D_SQUARE_VERTICES, KRENGINE_VBO_2D_SQUARE_INDEXES;
|
KRDataBlock KRENGINE_VBO_2D_SQUARE_VERTICES, KRENGINE_VBO_2D_SQUARE_INDEXES;
|
||||||
__int32_t KRENGINE_VBO_2D_SQUARE_ATTRIBS;
|
__int32_t KRENGINE_VBO_2D_SQUARE_ATTRIBS;
|
||||||
|
|
||||||
unordered_multimap<std::string, KRMesh *> m_models; // Multiple models with the same name/key may be inserted, representing multiple LOD levels of the model
|
unordered_multimap<std::string, KRMesh *> m_models; // Multiple models with the same name/key may be inserted, representing multiple LOD levels of the model
|
||||||
|
|
||||||
long m_vboMemUsed;
|
long m_vboMemUsed;
|
||||||
KRVBOData *m_currentVBO;
|
KRVBOData *m_currentVBO;
|
||||||
|
|
||||||
unordered_map<KRDataBlock *, KRVBOData *> m_vbosActive;
|
unordered_map<KRDataBlock *, KRVBOData *> m_vbosActive;
|
||||||
std::vector<std::pair<float, KRVBOData *> > m_activeVBOs_streamer;
|
std::vector<std::pair<float, KRVBOData *> > m_activeVBOs_streamer;
|
||||||
std::vector<std::pair<float, KRVBOData *> > m_activeVBOs_streamer_copy;
|
std::vector<std::pair<float, KRVBOData *> > m_activeVBOs_streamer_copy;
|
||||||
|
|
||||||
KRDataBlock m_randomParticleVertexData;
|
KRDataBlock m_randomParticleVertexData;
|
||||||
KRDataBlock m_volumetricLightingVertexData;
|
KRDataBlock m_volumetricLightingVertexData;
|
||||||
|
|
||||||
long m_memoryTransferredThisFrame;
|
long m_memoryTransferredThisFrame;
|
||||||
|
|
||||||
std::vector<draw_call_info> m_draw_calls;
|
std::vector<draw_call_info> m_draw_calls;
|
||||||
bool m_draw_call_logging_enabled;
|
bool m_draw_call_logging_enabled;
|
||||||
bool m_draw_call_log_used;
|
bool m_draw_call_log_used;
|
||||||
|
|
||||||
bool m_first_frame;
|
bool m_first_frame;
|
||||||
|
|
||||||
std::mutex m_streamerFenceMutex;
|
std::mutex m_streamerFenceMutex;
|
||||||
bool m_streamerComplete;
|
bool m_streamerComplete;
|
||||||
|
|
||||||
void balanceVBOMemory(long &memoryRemaining, long &memoryRemainingThisFrame);
|
void balanceVBOMemory(long &memoryRemaining, long &memoryRemainingThisFrame);
|
||||||
|
|
||||||
void primeVBO(KRVBOData *vbo_data);
|
void primeVBO(KRVBOData *vbo_data);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,63 +1,63 @@
|
|||||||
//
|
//
|
||||||
// KRMeshQuad.cpp
|
// KRMeshQuad.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
// permitted provided that the following conditions are met:
|
// permitted provided that the following conditions are met:
|
||||||
//
|
//
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
// conditions and the following disclaimer.
|
// conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
// provided with the distribution.
|
// provided with the distribution.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
// or implied, of Kearwood Gilbert.
|
// or implied, of Kearwood Gilbert.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KRMeshQuad.h"
|
#include "KRMeshQuad.h"
|
||||||
|
|
||||||
|
|
||||||
KRMeshQuad::KRMeshQuad(KRContext &context) : KRMesh(context, "__quad")
|
KRMeshQuad::KRMeshQuad(KRContext &context) : KRMesh(context, "__quad")
|
||||||
{
|
{
|
||||||
m_constant = true;
|
m_constant = true;
|
||||||
|
|
||||||
KRMesh::mesh_info mi;
|
KRMesh::mesh_info mi;
|
||||||
|
|
||||||
mi.vertices.push_back(Vector3(-1.0f, -1.0f, 0.0f));
|
mi.vertices.push_back(Vector3::Create(-1.0f, -1.0f, 0.0f));
|
||||||
mi.vertices.push_back(Vector3(1.0f, -1.0f, 0.0f));
|
mi.vertices.push_back(Vector3::Create(1.0f, -1.0f, 0.0f));
|
||||||
mi.vertices.push_back(Vector3(-1.0f, 1.0f, 0.0f));
|
mi.vertices.push_back(Vector3::Create(-1.0f, 1.0f, 0.0f));
|
||||||
mi.vertices.push_back(Vector3(1.0f, 1.0f, 0.0f));
|
mi.vertices.push_back(Vector3::Create(1.0f, 1.0f, 0.0f));
|
||||||
|
|
||||||
mi.uva.push_back(Vector2(0.0f, 0.0f));
|
mi.uva.push_back(Vector2::Create(0.0f, 0.0f));
|
||||||
mi.uva.push_back(Vector2(1.0f, 0.0f));
|
mi.uva.push_back(Vector2::Create(1.0f, 0.0f));
|
||||||
mi.uva.push_back(Vector2(0.0f, 1.0f));
|
mi.uva.push_back(Vector2::Create(0.0f, 1.0f));
|
||||||
mi.uva.push_back(Vector2(1.0f, 1.0f));
|
mi.uva.push_back(Vector2::Create(1.0f, 1.0f));
|
||||||
|
|
||||||
|
|
||||||
mi.submesh_starts.push_back(0);
|
mi.submesh_starts.push_back(0);
|
||||||
mi.submesh_lengths.push_back(mi.vertices.size());
|
mi.submesh_lengths.push_back(mi.vertices.size());
|
||||||
mi.material_names.push_back("");
|
mi.material_names.push_back("");
|
||||||
mi.format = KRENGINE_MODEL_FORMAT_STRIP;
|
mi.format = KRENGINE_MODEL_FORMAT_STRIP;
|
||||||
|
|
||||||
LoadData(mi, true, true);
|
LoadData(mi, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
KRMeshQuad::~KRMeshQuad()
|
KRMeshQuad::~KRMeshQuad()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,135 +1,135 @@
|
|||||||
//
|
//
|
||||||
// KRMeshSphere.cpp
|
// KRMeshSphere.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
// permitted provided that the following conditions are met:
|
// permitted provided that the following conditions are met:
|
||||||
//
|
//
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
// conditions and the following disclaimer.
|
// conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
// provided with the distribution.
|
// provided with the distribution.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
// or implied, of Kearwood Gilbert.
|
// or implied, of Kearwood Gilbert.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KRMeshSphere.h"
|
#include "KRMeshSphere.h"
|
||||||
|
|
||||||
|
|
||||||
KRMeshSphere::KRMeshSphere(KRContext &context) : KRMesh(context, "__sphere")
|
KRMeshSphere::KRMeshSphere(KRContext &context) : KRMesh(context, "__sphere")
|
||||||
{
|
{
|
||||||
m_constant = true;
|
m_constant = true;
|
||||||
|
|
||||||
KRMesh::mesh_info mi;
|
KRMesh::mesh_info mi;
|
||||||
|
|
||||||
// Create a triangular facet approximation to a sphere
|
// Create a triangular facet approximation to a sphere
|
||||||
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
|
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
|
||||||
|
|
||||||
int iterations = 3;
|
int iterations = 3;
|
||||||
int facet_count = pow(4, iterations) * 8;
|
int facet_count = pow(4, iterations) * 8;
|
||||||
|
|
||||||
class Facet3 {
|
class Facet3 {
|
||||||
public:
|
public:
|
||||||
Facet3() {
|
Facet3() {
|
||||||
|
|
||||||
}
|
}
|
||||||
~Facet3() {
|
~Facet3() {
|
||||||
|
|
||||||
}
|
}
|
||||||
Vector3 p1;
|
Vector3 p1;
|
||||||
Vector3 p2;
|
Vector3 p2;
|
||||||
Vector3 p3;
|
Vector3 p3;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Facet3> f = std::vector<Facet3>(facet_count);
|
std::vector<Facet3> f = std::vector<Facet3>(facet_count);
|
||||||
|
|
||||||
int i,it;
|
int i,it;
|
||||||
float a;
|
float a;
|
||||||
Vector3 p[6] = {
|
Vector3 p[6] = {
|
||||||
Vector3(0,0,1),
|
Vector3::Create(0,0,1),
|
||||||
Vector3(0,0,-1),
|
Vector3::Create(0,0,-1),
|
||||||
Vector3(-1,-1,0),
|
Vector3::Create(-1,-1,0),
|
||||||
Vector3(1,-1,0),
|
Vector3::Create(1,-1,0),
|
||||||
Vector3(1,1,0),
|
Vector3::Create(1,1,0),
|
||||||
Vector3(-1,1,0)
|
Vector3::Create(-1,1,0)
|
||||||
};
|
};
|
||||||
|
|
||||||
Vector3 pa,pb,pc;
|
Vector3 pa,pb,pc;
|
||||||
int nt = 0,ntold;
|
int nt = 0,ntold;
|
||||||
|
|
||||||
/* Create the level 0 object */
|
/* Create the level 0 object */
|
||||||
a = 1 / sqrt(2.0);
|
a = 1 / sqrt(2.0);
|
||||||
for (i=0;i<6;i++) {
|
for (i=0;i<6;i++) {
|
||||||
p[i].x *= a;
|
p[i].x *= a;
|
||||||
p[i].y *= a;
|
p[i].y *= a;
|
||||||
}
|
}
|
||||||
f[0].p1 = p[0]; f[0].p2 = p[3]; f[0].p3 = p[4];
|
f[0].p1 = p[0]; f[0].p2 = p[3]; f[0].p3 = p[4];
|
||||||
f[1].p1 = p[0]; f[1].p2 = p[4]; f[1].p3 = p[5];
|
f[1].p1 = p[0]; f[1].p2 = p[4]; f[1].p3 = p[5];
|
||||||
f[2].p1 = p[0]; f[2].p2 = p[5]; f[2].p3 = p[2];
|
f[2].p1 = p[0]; f[2].p2 = p[5]; f[2].p3 = p[2];
|
||||||
f[3].p1 = p[0]; f[3].p2 = p[2]; f[3].p3 = p[3];
|
f[3].p1 = p[0]; f[3].p2 = p[2]; f[3].p3 = p[3];
|
||||||
f[4].p1 = p[1]; f[4].p2 = p[4]; f[4].p3 = p[3];
|
f[4].p1 = p[1]; f[4].p2 = p[4]; f[4].p3 = p[3];
|
||||||
f[5].p1 = p[1]; f[5].p2 = p[5]; f[5].p3 = p[4];
|
f[5].p1 = p[1]; f[5].p2 = p[5]; f[5].p3 = p[4];
|
||||||
f[6].p1 = p[1]; f[6].p2 = p[2]; f[6].p3 = p[5];
|
f[6].p1 = p[1]; f[6].p2 = p[2]; f[6].p3 = p[5];
|
||||||
f[7].p1 = p[1]; f[7].p2 = p[3]; f[7].p3 = p[2];
|
f[7].p1 = p[1]; f[7].p2 = p[3]; f[7].p3 = p[2];
|
||||||
nt = 8;
|
nt = 8;
|
||||||
|
|
||||||
/* Bisect each edge and move to the surface of a unit sphere */
|
/* Bisect each edge and move to the surface of a unit sphere */
|
||||||
for (it=0;it<iterations;it++) {
|
for (it=0;it<iterations;it++) {
|
||||||
ntold = nt;
|
ntold = nt;
|
||||||
for (i=0;i<ntold;i++) {
|
for (i=0;i<ntold;i++) {
|
||||||
pa.x = (f[i].p1.x + f[i].p2.x) / 2;
|
pa.x = (f[i].p1.x + f[i].p2.x) / 2;
|
||||||
pa.y = (f[i].p1.y + f[i].p2.y) / 2;
|
pa.y = (f[i].p1.y + f[i].p2.y) / 2;
|
||||||
pa.z = (f[i].p1.z + f[i].p2.z) / 2;
|
pa.z = (f[i].p1.z + f[i].p2.z) / 2;
|
||||||
pb.x = (f[i].p2.x + f[i].p3.x) / 2;
|
pb.x = (f[i].p2.x + f[i].p3.x) / 2;
|
||||||
pb.y = (f[i].p2.y + f[i].p3.y) / 2;
|
pb.y = (f[i].p2.y + f[i].p3.y) / 2;
|
||||||
pb.z = (f[i].p2.z + f[i].p3.z) / 2;
|
pb.z = (f[i].p2.z + f[i].p3.z) / 2;
|
||||||
pc.x = (f[i].p3.x + f[i].p1.x) / 2;
|
pc.x = (f[i].p3.x + f[i].p1.x) / 2;
|
||||||
pc.y = (f[i].p3.y + f[i].p1.y) / 2;
|
pc.y = (f[i].p3.y + f[i].p1.y) / 2;
|
||||||
pc.z = (f[i].p3.z + f[i].p1.z) / 2;
|
pc.z = (f[i].p3.z + f[i].p1.z) / 2;
|
||||||
pa.normalize();
|
pa.normalize();
|
||||||
pb.normalize();
|
pb.normalize();
|
||||||
pc.normalize();
|
pc.normalize();
|
||||||
f[nt].p1 = f[i].p1; f[nt].p2 = pa; f[nt].p3 = pc; nt++;
|
f[nt].p1 = f[i].p1; f[nt].p2 = pa; f[nt].p3 = pc; nt++;
|
||||||
f[nt].p1 = pa; f[nt].p2 = f[i].p2; f[nt].p3 = pb; nt++;
|
f[nt].p1 = pa; f[nt].p2 = f[i].p2; f[nt].p3 = pb; nt++;
|
||||||
f[nt].p1 = pb; f[nt].p2 = f[i].p3; f[nt].p3 = pc; nt++;
|
f[nt].p1 = pb; f[nt].p2 = f[i].p3; f[nt].p3 = pc; nt++;
|
||||||
f[i].p1 = pa;
|
f[i].p1 = pa;
|
||||||
f[i].p2 = pb;
|
f[i].p2 = pb;
|
||||||
f[i].p3 = pc;
|
f[i].p3 = pc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int facet_index=0; facet_index < facet_count; facet_index++) {
|
for(int facet_index=0; facet_index < facet_count; facet_index++) {
|
||||||
mi.vertices.push_back(f[facet_index].p1);
|
mi.vertices.push_back(f[facet_index].p1);
|
||||||
mi.vertices.push_back(f[facet_index].p2);
|
mi.vertices.push_back(f[facet_index].p2);
|
||||||
mi.vertices.push_back(f[facet_index].p3);
|
mi.vertices.push_back(f[facet_index].p3);
|
||||||
}
|
}
|
||||||
|
|
||||||
mi.submesh_starts.push_back(0);
|
mi.submesh_starts.push_back(0);
|
||||||
mi.submesh_lengths.push_back(mi.vertices.size());
|
mi.submesh_lengths.push_back(mi.vertices.size());
|
||||||
mi.material_names.push_back("");
|
mi.material_names.push_back("");
|
||||||
|
|
||||||
|
|
||||||
mi.format = KRENGINE_MODEL_FORMAT_TRIANGLES;
|
mi.format = KRENGINE_MODEL_FORMAT_TRIANGLES;
|
||||||
LoadData(mi, true, true);
|
LoadData(mi, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
KRMeshSphere::~KRMeshSphere()
|
KRMeshSphere::~KRMeshSphere()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,263 +1,263 @@
|
|||||||
//
|
//
|
||||||
// KRModel.cpp
|
// KRModel.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
// permitted provided that the following conditions are met:
|
// permitted provided that the following conditions are met:
|
||||||
//
|
//
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
// conditions and the following disclaimer.
|
// conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
// provided with the distribution.
|
// provided with the distribution.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
// or implied, of Kearwood Gilbert.
|
// or implied, of Kearwood Gilbert.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
#include "KRModel.h"
|
#include "KRModel.h"
|
||||||
#include "KRContext.h"
|
#include "KRContext.h"
|
||||||
#include "KRMesh.h"
|
#include "KRMesh.h"
|
||||||
|
|
||||||
KRModel::KRModel(KRScene &scene, std::string instance_name, std::string model_name, std::string light_map, float lod_min_coverage, bool receives_shadow, bool faces_camera, Vector3 rim_color, float rim_power) : KRNode(scene, instance_name) {
|
KRModel::KRModel(KRScene &scene, std::string instance_name, std::string model_name, std::string light_map, float lod_min_coverage, bool receives_shadow, bool faces_camera, Vector3 rim_color, float rim_power) : KRNode(scene, instance_name) {
|
||||||
m_lightMap = light_map;
|
m_lightMap = light_map;
|
||||||
m_pLightMap = NULL;
|
m_pLightMap = NULL;
|
||||||
m_model_name = model_name;
|
m_model_name = model_name;
|
||||||
m_min_lod_coverage = lod_min_coverage;
|
m_min_lod_coverage = lod_min_coverage;
|
||||||
m_receivesShadow = receives_shadow;
|
m_receivesShadow = receives_shadow;
|
||||||
m_faces_camera = faces_camera;
|
m_faces_camera = faces_camera;
|
||||||
m_rim_color = rim_color;
|
m_rim_color = rim_color;
|
||||||
m_rim_power = rim_power;
|
m_rim_power = rim_power;
|
||||||
|
|
||||||
m_boundsCachedMat.c[0] = -1.0f;
|
m_boundsCachedMat.c[0] = -1.0f;
|
||||||
m_boundsCachedMat.c[1] = -1.0f;
|
m_boundsCachedMat.c[1] = -1.0f;
|
||||||
m_boundsCachedMat.c[2] = -1.0f;
|
m_boundsCachedMat.c[2] = -1.0f;
|
||||||
m_boundsCachedMat.c[3] = -1.0f;
|
m_boundsCachedMat.c[3] = -1.0f;
|
||||||
m_boundsCachedMat.c[4] = -1.0f;
|
m_boundsCachedMat.c[4] = -1.0f;
|
||||||
m_boundsCachedMat.c[5] = -1.0f;
|
m_boundsCachedMat.c[5] = -1.0f;
|
||||||
m_boundsCachedMat.c[6] = -1.0f;
|
m_boundsCachedMat.c[6] = -1.0f;
|
||||||
m_boundsCachedMat.c[7] = -1.0f;
|
m_boundsCachedMat.c[7] = -1.0f;
|
||||||
m_boundsCachedMat.c[8] = -1.0f;
|
m_boundsCachedMat.c[8] = -1.0f;
|
||||||
m_boundsCachedMat.c[9] = -1.0f;
|
m_boundsCachedMat.c[9] = -1.0f;
|
||||||
m_boundsCachedMat.c[10] = -1.0f;
|
m_boundsCachedMat.c[10] = -1.0f;
|
||||||
m_boundsCachedMat.c[11] = -1.0f;
|
m_boundsCachedMat.c[11] = -1.0f;
|
||||||
m_boundsCachedMat.c[12] = -1.0f;
|
m_boundsCachedMat.c[12] = -1.0f;
|
||||||
m_boundsCachedMat.c[13] = -1.0f;
|
m_boundsCachedMat.c[13] = -1.0f;
|
||||||
m_boundsCachedMat.c[14] = -1.0f;
|
m_boundsCachedMat.c[14] = -1.0f;
|
||||||
m_boundsCachedMat.c[15] = -1.0f;
|
m_boundsCachedMat.c[15] = -1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRModel::~KRModel() {
|
KRModel::~KRModel() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KRModel::getElementName() {
|
std::string KRModel::getElementName() {
|
||||||
return "model";
|
return "model";
|
||||||
}
|
}
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRModel::saveXML( tinyxml2::XMLNode *parent)
|
tinyxml2::XMLElement *KRModel::saveXML( tinyxml2::XMLNode *parent)
|
||||||
{
|
{
|
||||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||||
e->SetAttribute("mesh", m_model_name.c_str());
|
e->SetAttribute("mesh", m_model_name.c_str());
|
||||||
e->SetAttribute("light_map", m_lightMap.c_str());
|
e->SetAttribute("light_map", m_lightMap.c_str());
|
||||||
e->SetAttribute("lod_min_coverage", m_min_lod_coverage);
|
e->SetAttribute("lod_min_coverage", m_min_lod_coverage);
|
||||||
e->SetAttribute("receives_shadow", m_receivesShadow ? "true" : "false");
|
e->SetAttribute("receives_shadow", m_receivesShadow ? "true" : "false");
|
||||||
e->SetAttribute("faces_camera", m_faces_camera ? "true" : "false");
|
e->SetAttribute("faces_camera", m_faces_camera ? "true" : "false");
|
||||||
kraken::setXMLAttribute("rim_color", e, m_rim_color, Vector3::Zero());
|
kraken::setXMLAttribute("rim_color", e, m_rim_color, Vector3::Zero());
|
||||||
e->SetAttribute("rim_power", m_rim_power);
|
e->SetAttribute("rim_power", m_rim_power);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRModel::setRimColor(const Vector3 &rim_color)
|
void KRModel::setRimColor(const Vector3 &rim_color)
|
||||||
{
|
{
|
||||||
m_rim_color = rim_color;
|
m_rim_color = rim_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRModel::setRimPower(float rim_power)
|
void KRModel::setRimPower(float rim_power)
|
||||||
{
|
{
|
||||||
m_rim_power = rim_power;
|
m_rim_power = rim_power;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 KRModel::getRimColor()
|
Vector3 KRModel::getRimColor()
|
||||||
{
|
{
|
||||||
return m_rim_color;
|
return m_rim_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
float KRModel::getRimPower()
|
float KRModel::getRimPower()
|
||||||
{
|
{
|
||||||
return m_rim_power;
|
return m_rim_power;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRModel::setLightMap(const std::string &name)
|
void KRModel::setLightMap(const std::string &name)
|
||||||
{
|
{
|
||||||
m_lightMap = name;
|
m_lightMap = name;
|
||||||
m_pLightMap = NULL;
|
m_pLightMap = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KRModel::getLightMap()
|
std::string KRModel::getLightMap()
|
||||||
{
|
{
|
||||||
return m_lightMap;
|
return m_lightMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRModel::loadModel() {
|
void KRModel::loadModel() {
|
||||||
if(m_models.size() == 0) {
|
if(m_models.size() == 0) {
|
||||||
std::vector<KRMesh *> models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first
|
std::vector<KRMesh *> models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first
|
||||||
unordered_map<KRMesh *, std::vector<KRBone *> > bones;
|
unordered_map<KRMesh *, std::vector<KRBone *> > bones;
|
||||||
if(models.size() > 0) {
|
if(models.size() > 0) {
|
||||||
bool all_bones_found = true;
|
bool all_bones_found = true;
|
||||||
for(std::vector<KRMesh *>::iterator model_itr = models.begin(); model_itr != models.end(); model_itr++) {
|
for(std::vector<KRMesh *>::iterator model_itr = models.begin(); model_itr != models.end(); model_itr++) {
|
||||||
KRMesh *model = *model_itr;
|
KRMesh *model = *model_itr;
|
||||||
std::vector<KRBone *> model_bones;
|
std::vector<KRBone *> model_bones;
|
||||||
int bone_count = model->getBoneCount();
|
int bone_count = model->getBoneCount();
|
||||||
for(int bone_index=0; bone_index < bone_count; bone_index++) {
|
for(int bone_index=0; bone_index < bone_count; bone_index++) {
|
||||||
KRBone *matching_bone = dynamic_cast<KRBone *>(getScene().getRootNode()->find<KRNode>(model->getBoneName(bone_index)));
|
KRBone *matching_bone = dynamic_cast<KRBone *>(getScene().getRootNode()->find<KRNode>(model->getBoneName(bone_index)));
|
||||||
if(matching_bone) {
|
if(matching_bone) {
|
||||||
model_bones.push_back(matching_bone);
|
model_bones.push_back(matching_bone);
|
||||||
} else {
|
} else {
|
||||||
all_bones_found = false; // Reject when there are any missing bones or multiple matches
|
all_bones_found = false; // Reject when there are any missing bones or multiple matches
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bones[model] = model_bones;
|
bones[model] = model_bones;
|
||||||
}
|
}
|
||||||
if(all_bones_found) {
|
if(all_bones_found) {
|
||||||
m_models = models;
|
m_models = models;
|
||||||
m_bones = bones;
|
m_bones = bones;
|
||||||
getScene().notify_sceneGraphModify(this);
|
getScene().notify_sceneGraphModify(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
invalidateBounds();
|
invalidateBounds();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRModel::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
|
void KRModel::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
|
||||||
|
|
||||||
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) {
|
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) {
|
||||||
preStream(viewport);
|
preStream(viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||||
|
|
||||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||||
|
|
||||||
if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && renderPass != KRNode::RENDER_PASS_PRESTREAM) {
|
if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && renderPass != KRNode::RENDER_PASS_PRESTREAM) {
|
||||||
loadModel();
|
loadModel();
|
||||||
|
|
||||||
if(m_models.size() > 0) {
|
if(m_models.size() > 0) {
|
||||||
// Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied
|
// Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied
|
||||||
|
|
||||||
/*
|
/*
|
||||||
float lod_coverage = 0.0f;
|
float lod_coverage = 0.0f;
|
||||||
if(m_models.size() > 1) {
|
if(m_models.size() > 1) {
|
||||||
lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
|
lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
|
||||||
} else if(viewport.visible(getBounds())) {
|
} else if(viewport.visible(getBounds())) {
|
||||||
lod_coverage = 1.0f;
|
lod_coverage = 1.0f;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
float lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
|
float lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
|
||||||
|
|
||||||
if(lod_coverage > m_min_lod_coverage) {
|
if(lod_coverage > m_min_lod_coverage) {
|
||||||
|
|
||||||
// ---===--- Select the best LOD model based on screen coverage ---===---
|
// ---===--- Select the best LOD model based on screen coverage ---===---
|
||||||
std::vector<KRMesh *>::iterator itr=m_models.begin();
|
std::vector<KRMesh *>::iterator itr=m_models.begin();
|
||||||
KRMesh *pModel = *itr++;
|
KRMesh *pModel = *itr++;
|
||||||
|
|
||||||
while(itr != m_models.end()) {
|
while(itr != m_models.end()) {
|
||||||
KRMesh *pLODModel = *itr++;
|
KRMesh *pLODModel = *itr++;
|
||||||
if((float)pLODModel->getLODCoverage() / 100.0f > lod_coverage && pLODModel->getLODCoverage() < pModel->getLODCoverage()) {
|
if((float)pLODModel->getLODCoverage() / 100.0f > lod_coverage && pLODModel->getLODCoverage() < pModel->getLODCoverage()) {
|
||||||
pModel = pLODModel;
|
pModel = pLODModel;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pLightMap == NULL && m_lightMap.size()) {
|
if(m_pLightMap == NULL && m_lightMap.size()) {
|
||||||
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
|
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pLightMap && pCamera->settings.bEnableLightMap && renderPass != RENDER_PASS_SHADOWMAP && renderPass != RENDER_PASS_GENERATE_SHADOWMAPS) {
|
if(m_pLightMap && pCamera->settings.bEnableLightMap && renderPass != RENDER_PASS_SHADOWMAP && renderPass != RENDER_PASS_GENERATE_SHADOWMAPS) {
|
||||||
m_pContext->getTextureManager()->selectTexture(5, m_pLightMap, lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
|
m_pContext->getTextureManager()->selectTexture(5, m_pLightMap, lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix4 matModel = getModelMatrix();
|
Matrix4 matModel = getModelMatrix();
|
||||||
if(m_faces_camera) {
|
if(m_faces_camera) {
|
||||||
Vector3 model_center = Matrix4::Dot(matModel, Vector3::Zero());
|
Vector3 model_center = Matrix4::Dot(matModel, Vector3::Zero());
|
||||||
Vector3 camera_pos = viewport.getCameraPosition();
|
Vector3 camera_pos = viewport.getCameraPosition();
|
||||||
matModel = Quaternion(Vector3::Forward(), Vector3::Normalize(camera_pos - model_center)).rotationMatrix() * matModel;
|
matModel = Quaternion::Create(Vector3::Forward(), Vector3::Normalize(camera_pos - model_center)).rotationMatrix() * matModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
pModel->render(getName(), pCamera, point_lights, directional_lights, spot_lights, viewport, matModel, m_pLightMap, renderPass, m_bones[pModel], m_rim_color, m_rim_power, lod_coverage);
|
pModel->render(getName(), pCamera, point_lights, directional_lights, spot_lights, viewport, matModel, m_pLightMap, renderPass, m_bones[pModel], m_rim_color, m_rim_power, lod_coverage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRModel::preStream(const KRViewport &viewport)
|
void KRModel::preStream(const KRViewport &viewport)
|
||||||
{
|
{
|
||||||
loadModel();
|
loadModel();
|
||||||
float lod_coverage = viewport.coverage(getBounds());
|
float lod_coverage = viewport.coverage(getBounds());
|
||||||
|
|
||||||
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
|
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
|
||||||
(*itr)->preStream(lod_coverage);
|
(*itr)->preStream(lod_coverage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pLightMap == NULL && m_lightMap.size()) {
|
if(m_pLightMap == NULL && m_lightMap.size()) {
|
||||||
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
|
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pLightMap) {
|
if(m_pLightMap) {
|
||||||
m_pLightMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
|
m_pLightMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
kraken_stream_level KRModel::getStreamLevel(const KRViewport &viewport)
|
kraken_stream_level KRModel::getStreamLevel(const KRViewport &viewport)
|
||||||
{
|
{
|
||||||
kraken_stream_level stream_level = KRNode::getStreamLevel(viewport);
|
kraken_stream_level stream_level = KRNode::getStreamLevel(viewport);
|
||||||
|
|
||||||
loadModel();
|
loadModel();
|
||||||
|
|
||||||
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
|
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
|
||||||
stream_level = KRMIN(stream_level, (*itr)->getStreamLevel());
|
stream_level = KRMIN(stream_level, (*itr)->getStreamLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
return stream_level;
|
return stream_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
AABB KRModel::getBounds() {
|
AABB KRModel::getBounds() {
|
||||||
loadModel();
|
loadModel();
|
||||||
if(m_models.size() > 0) {
|
if(m_models.size() > 0) {
|
||||||
if(m_faces_camera) {
|
if(m_faces_camera) {
|
||||||
AABB normal_bounds = AABB(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
AABB normal_bounds = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||||
float max_dimension = normal_bounds.longest_radius();
|
float max_dimension = normal_bounds.longest_radius();
|
||||||
return AABB(normal_bounds.center()-Vector3(max_dimension), normal_bounds.center() + Vector3(max_dimension));
|
return AABB::Create(normal_bounds.center()-Vector3::Create(max_dimension), normal_bounds.center() + Vector3::Create(max_dimension));
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if(!(m_boundsCachedMat == getModelMatrix())) {
|
if(!(m_boundsCachedMat == getModelMatrix())) {
|
||||||
m_boundsCachedMat = getModelMatrix();
|
m_boundsCachedMat = getModelMatrix();
|
||||||
m_boundsCached = AABB(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
m_boundsCached = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||||
}
|
}
|
||||||
return m_boundsCached;
|
return m_boundsCached;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return AABB::Infinite();
|
return AABB::Infinite();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1926
kraken/KRNode.cpp
1926
kraken/KRNode.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,156 +1,156 @@
|
|||||||
//
|
//
|
||||||
// KROctree.cpp
|
// KROctree.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 2012-08-29.
|
// Created by Kearwood Gilbert on 2012-08-29.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "public/kraken.h"
|
#include "public/kraken.h"
|
||||||
#include "KROctree.h"
|
#include "KROctree.h"
|
||||||
#include "KRNode.h"
|
#include "KRNode.h"
|
||||||
#include "KRCollider.h"
|
#include "KRCollider.h"
|
||||||
|
|
||||||
KROctree::KROctree()
|
KROctree::KROctree()
|
||||||
{
|
{
|
||||||
m_pRootNode = NULL;
|
m_pRootNode = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
KROctree::~KROctree()
|
KROctree::~KROctree()
|
||||||
{
|
{
|
||||||
if(m_pRootNode) {
|
if(m_pRootNode) {
|
||||||
delete m_pRootNode;
|
delete m_pRootNode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KROctree::add(KRNode *pNode)
|
void KROctree::add(KRNode *pNode)
|
||||||
{
|
{
|
||||||
AABB nodeBounds = pNode->getBounds();
|
AABB nodeBounds = pNode->getBounds();
|
||||||
if(nodeBounds == AABB::Zero()) {
|
if(nodeBounds == AABB::Zero()) {
|
||||||
// This item is not visible, don't add it to the octree or outer scene nodes
|
// This item is not visible, don't add it to the octree or outer scene nodes
|
||||||
} else if(nodeBounds == AABB::Infinite()) {
|
} else if(nodeBounds == AABB::Infinite()) {
|
||||||
// This item is infinitely large; we track it separately
|
// This item is infinitely large; we track it separately
|
||||||
m_outerSceneNodes.insert(pNode);
|
m_outerSceneNodes.insert(pNode);
|
||||||
} else {
|
} else {
|
||||||
if(m_pRootNode == NULL) {
|
if(m_pRootNode == NULL) {
|
||||||
// First item inserted, create a node large enough to fit it
|
// First item inserted, create a node large enough to fit it
|
||||||
m_pRootNode = new KROctreeNode(NULL, nodeBounds);
|
m_pRootNode = new KROctreeNode(NULL, nodeBounds);
|
||||||
m_pRootNode->add(pNode);
|
m_pRootNode->add(pNode);
|
||||||
} else {
|
} else {
|
||||||
// Keep encapsulating the root node until the new root contains the inserted node
|
// Keep encapsulating the root node until the new root contains the inserted node
|
||||||
bool bInsideRoot = false;
|
bool bInsideRoot = false;
|
||||||
while(!bInsideRoot) {
|
while(!bInsideRoot) {
|
||||||
AABB rootBounds = m_pRootNode->getBounds();
|
AABB rootBounds = m_pRootNode->getBounds();
|
||||||
Vector3 rootSize = rootBounds.size();
|
Vector3 rootSize = rootBounds.size();
|
||||||
if(nodeBounds.min.x < rootBounds.min.x || nodeBounds.min.y < rootBounds.min.y || nodeBounds.min.z < rootBounds.min.z) {
|
if(nodeBounds.min.x < rootBounds.min.x || nodeBounds.min.y < rootBounds.min.y || nodeBounds.min.z < rootBounds.min.z) {
|
||||||
m_pRootNode = new KROctreeNode(NULL, AABB(rootBounds.min - rootSize, rootBounds.max), 7, m_pRootNode);
|
m_pRootNode = new KROctreeNode(NULL, AABB::Create(rootBounds.min - rootSize, rootBounds.max), 7, m_pRootNode);
|
||||||
} else if(nodeBounds.max.x > rootBounds.max.x || nodeBounds.max.y > rootBounds.max.y || nodeBounds.max.z > rootBounds.max.z) {
|
} else if(nodeBounds.max.x > rootBounds.max.x || nodeBounds.max.y > rootBounds.max.y || nodeBounds.max.z > rootBounds.max.z) {
|
||||||
m_pRootNode = new KROctreeNode(NULL, AABB(rootBounds.min, rootBounds.max + rootSize), 0, m_pRootNode);
|
m_pRootNode = new KROctreeNode(NULL, AABB::Create(rootBounds.min, rootBounds.max + rootSize), 0, m_pRootNode);
|
||||||
} else {
|
} else {
|
||||||
bInsideRoot = true;
|
bInsideRoot = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_pRootNode->add(pNode);
|
m_pRootNode->add(pNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KROctree::remove(KRNode *pNode)
|
void KROctree::remove(KRNode *pNode)
|
||||||
{
|
{
|
||||||
if(!m_outerSceneNodes.erase(pNode)) {
|
if(!m_outerSceneNodes.erase(pNode)) {
|
||||||
if(m_pRootNode) {
|
if(m_pRootNode) {
|
||||||
pNode->removeFromOctreeNodes();
|
pNode->removeFromOctreeNodes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shrink();
|
shrink();
|
||||||
}
|
}
|
||||||
|
|
||||||
void KROctree::update(KRNode *pNode)
|
void KROctree::update(KRNode *pNode)
|
||||||
{
|
{
|
||||||
// TODO: This may be more efficient as an incremental operation rather than removing and re-adding the node
|
// TODO: This may be more efficient as an incremental operation rather than removing and re-adding the node
|
||||||
remove(pNode);
|
remove(pNode);
|
||||||
add(pNode);
|
add(pNode);
|
||||||
shrink();
|
shrink();
|
||||||
}
|
}
|
||||||
|
|
||||||
void KROctree::shrink()
|
void KROctree::shrink()
|
||||||
{
|
{
|
||||||
if(m_pRootNode) {
|
if(m_pRootNode) {
|
||||||
while(m_pRootNode->canShrinkRoot()) {
|
while(m_pRootNode->canShrinkRoot()) {
|
||||||
KROctreeNode *newRoot = m_pRootNode->stripChild();
|
KROctreeNode *newRoot = m_pRootNode->stripChild();
|
||||||
delete m_pRootNode;
|
delete m_pRootNode;
|
||||||
m_pRootNode = newRoot;
|
m_pRootNode = newRoot;
|
||||||
if(m_pRootNode == NULL) return;
|
if(m_pRootNode == NULL) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KROctreeNode *KROctree::getRootNode()
|
KROctreeNode *KROctree::getRootNode()
|
||||||
{
|
{
|
||||||
return m_pRootNode;
|
return m_pRootNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<KRNode *> &KROctree::getOuterSceneNodes()
|
std::set<KRNode *> &KROctree::getOuterSceneNodes()
|
||||||
{
|
{
|
||||||
return m_outerSceneNodes;
|
return m_outerSceneNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool KROctree::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask)
|
bool KROctree::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask)
|
||||||
{
|
{
|
||||||
bool hit_found = false;
|
bool hit_found = false;
|
||||||
std::vector<KRCollider *> outer_colliders;
|
std::vector<KRCollider *> outer_colliders;
|
||||||
|
|
||||||
for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) {
|
for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) {
|
||||||
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
|
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
|
||||||
if(collider) {
|
if(collider) {
|
||||||
outer_colliders.push_back(collider);
|
outer_colliders.push_back(collider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(std::vector<KRCollider *>::iterator itr=outer_colliders.begin(); itr != outer_colliders.end(); itr++) {
|
for(std::vector<KRCollider *>::iterator itr=outer_colliders.begin(); itr != outer_colliders.end(); itr++) {
|
||||||
if((*itr)->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
if((*itr)->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pRootNode) {
|
if(m_pRootNode) {
|
||||||
if(m_pRootNode->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
if(m_pRootNode->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
||||||
}
|
}
|
||||||
return hit_found;
|
return hit_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KROctree::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
|
bool KROctree::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
|
||||||
{
|
{
|
||||||
bool hit_found = false;
|
bool hit_found = false;
|
||||||
for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) {
|
for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) {
|
||||||
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
|
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
|
||||||
if(collider) {
|
if(collider) {
|
||||||
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(m_pRootNode) {
|
if(m_pRootNode) {
|
||||||
if(m_pRootNode->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
if(m_pRootNode->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||||
}
|
}
|
||||||
return hit_found;
|
return hit_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KROctree::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
|
bool KROctree::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
|
||||||
{
|
{
|
||||||
bool hit_found = false;
|
bool hit_found = false;
|
||||||
std::vector<KRCollider *> outer_colliders;
|
std::vector<KRCollider *> outer_colliders;
|
||||||
|
|
||||||
for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) {
|
for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) {
|
||||||
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
|
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
|
||||||
if(collider) {
|
if(collider) {
|
||||||
outer_colliders.push_back(collider);
|
outer_colliders.push_back(collider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(std::vector<KRCollider *>::iterator itr=outer_colliders.begin(); itr != outer_colliders.end(); itr++) {
|
for(std::vector<KRCollider *>::iterator itr=outer_colliders.begin(); itr != outer_colliders.end(); itr++) {
|
||||||
if((*itr)->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
if((*itr)->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pRootNode) {
|
if(m_pRootNode) {
|
||||||
if(m_pRootNode->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
if(m_pRootNode->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
||||||
}
|
}
|
||||||
return hit_found;
|
return hit_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,290 +1,290 @@
|
|||||||
//
|
//
|
||||||
// KROctreeNode.cpp
|
// KROctreeNode.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 2012-08-29.
|
// Created by Kearwood Gilbert on 2012-08-29.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KROctreeNode.h"
|
#include "KROctreeNode.h"
|
||||||
#include "KRNode.h"
|
#include "KRNode.h"
|
||||||
#include "KRCollider.h"
|
#include "KRCollider.h"
|
||||||
|
|
||||||
KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds) : m_bounds(bounds)
|
KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds) : m_bounds(bounds)
|
||||||
{
|
{
|
||||||
m_parent = parent;
|
m_parent = parent;
|
||||||
|
|
||||||
for(int i=0; i<8; i++) m_children[i] = NULL;
|
for(int i=0; i<8; i++) m_children[i] = NULL;
|
||||||
|
|
||||||
m_occlusionQuery = 0;
|
m_occlusionQuery = 0;
|
||||||
m_occlusionTested = false;
|
m_occlusionTested = false;
|
||||||
m_activeQuery = false;
|
m_activeQuery = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds, int iChild, KROctreeNode *pChild) : m_bounds(bounds)
|
KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds, int iChild, KROctreeNode *pChild) : m_bounds(bounds)
|
||||||
{
|
{
|
||||||
// This constructor is used when expanding the octree and replacing the root node with a new root that encapsulates it
|
// This constructor is used when expanding the octree and replacing the root node with a new root that encapsulates it
|
||||||
m_parent = parent;
|
m_parent = parent;
|
||||||
|
|
||||||
for(int i=0; i<8; i++) m_children[i] = NULL;
|
for(int i=0; i<8; i++) m_children[i] = NULL;
|
||||||
m_children[iChild] = pChild;
|
m_children[iChild] = pChild;
|
||||||
pChild->m_parent = this;
|
pChild->m_parent = this;
|
||||||
|
|
||||||
m_occlusionQuery = 0;
|
m_occlusionQuery = 0;
|
||||||
m_occlusionTested = false;
|
m_occlusionTested = false;
|
||||||
m_activeQuery = false;
|
m_activeQuery = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
KROctreeNode::~KROctreeNode()
|
KROctreeNode::~KROctreeNode()
|
||||||
{
|
{
|
||||||
for(int i=0; i<8; i++) {
|
for(int i=0; i<8; i++) {
|
||||||
if(m_children[i] != NULL) {
|
if(m_children[i] != NULL) {
|
||||||
delete m_children[i];
|
delete m_children[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_occlusionTested) {
|
if(m_occlusionTested) {
|
||||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void KROctreeNode::beginOcclusionQuery()
|
void KROctreeNode::beginOcclusionQuery()
|
||||||
{
|
{
|
||||||
if(!m_occlusionTested){
|
if(!m_occlusionTested){
|
||||||
GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery));
|
GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery));
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
|
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
|
||||||
#else
|
#else
|
||||||
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
|
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
|
||||||
#endif
|
#endif
|
||||||
m_occlusionTested = true;
|
m_occlusionTested = true;
|
||||||
m_activeQuery = true;
|
m_activeQuery = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KROctreeNode::endOcclusionQuery()
|
void KROctreeNode::endOcclusionQuery()
|
||||||
{
|
{
|
||||||
if(m_activeQuery) {
|
if(m_activeQuery) {
|
||||||
// Only end a query if we started one
|
// Only end a query if we started one
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
|
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
|
||||||
#else
|
#else
|
||||||
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
|
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AABB KROctreeNode::getBounds()
|
AABB KROctreeNode::getBounds()
|
||||||
{
|
{
|
||||||
return m_bounds;
|
return m_bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KROctreeNode::add(KRNode *pNode)
|
void KROctreeNode::add(KRNode *pNode)
|
||||||
{
|
{
|
||||||
int iChild = getChildIndex(pNode);
|
int iChild = getChildIndex(pNode);
|
||||||
if(iChild == -1) {
|
if(iChild == -1) {
|
||||||
m_sceneNodes.insert(pNode);
|
m_sceneNodes.insert(pNode);
|
||||||
pNode->addToOctreeNode(this);
|
pNode->addToOctreeNode(this);
|
||||||
} else {
|
} else {
|
||||||
if(m_children[iChild] == NULL) {
|
if(m_children[iChild] == NULL) {
|
||||||
m_children[iChild] = new KROctreeNode(this, getChildBounds(iChild));
|
m_children[iChild] = new KROctreeNode(this, getChildBounds(iChild));
|
||||||
}
|
}
|
||||||
m_children[iChild]->add(pNode);
|
m_children[iChild]->add(pNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AABB KROctreeNode::getChildBounds(int iChild)
|
AABB KROctreeNode::getChildBounds(int iChild)
|
||||||
{
|
{
|
||||||
Vector3 center = m_bounds.center();
|
Vector3 center = m_bounds.center();
|
||||||
|
|
||||||
return AABB(
|
return AABB::Create(
|
||||||
Vector3(
|
Vector3::Create(
|
||||||
(iChild & 1) == 0 ? m_bounds.min.x : center.x,
|
(iChild & 1) == 0 ? m_bounds.min.x : center.x,
|
||||||
(iChild & 2) == 0 ? m_bounds.min.y : center.y,
|
(iChild & 2) == 0 ? m_bounds.min.y : center.y,
|
||||||
(iChild & 4) == 0 ? m_bounds.min.z : center.z),
|
(iChild & 4) == 0 ? m_bounds.min.z : center.z),
|
||||||
Vector3(
|
Vector3::Create(
|
||||||
(iChild & 1) == 0 ? center.x : m_bounds.max.x,
|
(iChild & 1) == 0 ? center.x : m_bounds.max.x,
|
||||||
(iChild & 2) == 0 ? center.y : m_bounds.max.y,
|
(iChild & 2) == 0 ? center.y : m_bounds.max.y,
|
||||||
(iChild & 4) == 0 ? center.z : m_bounds.max.z)
|
(iChild & 4) == 0 ? center.z : m_bounds.max.z)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
int KROctreeNode::getChildIndex(KRNode *pNode)
|
int KROctreeNode::getChildIndex(KRNode *pNode)
|
||||||
{
|
{
|
||||||
for(int iChild=0; iChild < 8; iChild++) {
|
for(int iChild=0; iChild < 8; iChild++) {
|
||||||
if(getChildBounds(iChild).contains(pNode->getBounds())) {
|
if(getChildBounds(iChild).contains(pNode->getBounds())) {
|
||||||
return iChild;
|
return iChild;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KROctreeNode::trim()
|
void KROctreeNode::trim()
|
||||||
{
|
{
|
||||||
for(int iChild = 0; iChild < 8; iChild++) {
|
for(int iChild = 0; iChild < 8; iChild++) {
|
||||||
if(m_children[iChild]) {
|
if(m_children[iChild]) {
|
||||||
if(m_children[iChild]->isEmpty()) {
|
if(m_children[iChild]->isEmpty()) {
|
||||||
delete m_children[iChild];
|
delete m_children[iChild];
|
||||||
m_children[iChild] = NULL;
|
m_children[iChild] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KROctreeNode::remove(KRNode *pNode)
|
void KROctreeNode::remove(KRNode *pNode)
|
||||||
{
|
{
|
||||||
m_sceneNodes.erase(pNode);
|
m_sceneNodes.erase(pNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KROctreeNode::update(KRNode *pNode)
|
void KROctreeNode::update(KRNode *pNode)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KROctreeNode::isEmpty() const
|
bool KROctreeNode::isEmpty() const
|
||||||
{
|
{
|
||||||
for(int i=0; i<8; i++) {
|
for(int i=0; i<8; i++) {
|
||||||
if(m_children[i]) {
|
if(m_children[i]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m_sceneNodes.empty();
|
return m_sceneNodes.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KROctreeNode::canShrinkRoot() const
|
bool KROctreeNode::canShrinkRoot() const
|
||||||
{
|
{
|
||||||
int cChildren = 0;
|
int cChildren = 0;
|
||||||
for(int i=0; i<8; i++) {
|
for(int i=0; i<8; i++) {
|
||||||
if(m_children[i]) {
|
if(m_children[i]) {
|
||||||
cChildren++;
|
cChildren++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cChildren <= 1 && m_sceneNodes.empty();
|
return cChildren <= 1 && m_sceneNodes.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
KROctreeNode *KROctreeNode::stripChild()
|
KROctreeNode *KROctreeNode::stripChild()
|
||||||
{
|
{
|
||||||
// Return the first found child and update its reference to NULL so that the destructor will not free it. This is used for shrinking the octree
|
// Return the first found child and update its reference to NULL so that the destructor will not free it. This is used for shrinking the octree
|
||||||
// NOTE: The caller of this function will be responsible for freeing the child object. It is also possible to return a NULL
|
// NOTE: The caller of this function will be responsible for freeing the child object. It is also possible to return a NULL
|
||||||
for(int i=0; i<8; i++) {
|
for(int i=0; i<8; i++) {
|
||||||
if(m_children[i]) {
|
if(m_children[i]) {
|
||||||
KROctreeNode *child = m_children[i];
|
KROctreeNode *child = m_children[i];
|
||||||
child->m_parent = NULL;
|
child->m_parent = NULL;
|
||||||
m_children[i] = NULL;
|
m_children[i] = NULL;
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
KROctreeNode *KROctreeNode::getParent()
|
KROctreeNode *KROctreeNode::getParent()
|
||||||
{
|
{
|
||||||
return m_parent;
|
return m_parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
KROctreeNode **KROctreeNode::getChildren()
|
KROctreeNode **KROctreeNode::getChildren()
|
||||||
{
|
{
|
||||||
return m_children;
|
return m_children;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<KRNode *> &KROctreeNode::getSceneNodes()
|
std::set<KRNode *> &KROctreeNode::getSceneNodes()
|
||||||
{
|
{
|
||||||
return m_sceneNodes;
|
return m_sceneNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool KROctreeNode::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask)
|
bool KROctreeNode::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask)
|
||||||
{
|
{
|
||||||
bool hit_found = false;
|
bool hit_found = false;
|
||||||
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
|
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
|
||||||
// Optimization: If we already have a hit, only search for hits that are closer
|
// Optimization: If we already have a hit, only search for hits that are closer
|
||||||
hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask);
|
hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask);
|
||||||
} else {
|
} else {
|
||||||
if(getBounds().intersectsLine(v0, v1)) {
|
if(getBounds().intersectsLine(v0, v1)) {
|
||||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||||
if(collider) {
|
if(collider) {
|
||||||
if(collider->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
if(collider->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0; i<8; i++) {
|
for(int i=0; i<8; i++) {
|
||||||
if(m_children[i]) {
|
if(m_children[i]) {
|
||||||
if(m_children[i]->lineCast(v0, v1, hitinfo, layer_mask)) {
|
if(m_children[i]->lineCast(v0, v1, hitinfo, layer_mask)) {
|
||||||
hit_found = true;
|
hit_found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return hit_found;
|
return hit_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KROctreeNode::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
|
bool KROctreeNode::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
|
||||||
{
|
{
|
||||||
bool hit_found = false;
|
bool hit_found = false;
|
||||||
if(hitinfo.didHit()) {
|
if(hitinfo.didHit()) {
|
||||||
// Optimization: If we already have a hit, only search for hits that are closer
|
// Optimization: If we already have a hit, only search for hits that are closer
|
||||||
hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask); // Note: This is purposefully lineCast as opposed to RayCast
|
hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask); // Note: This is purposefully lineCast as opposed to RayCast
|
||||||
} else {
|
} else {
|
||||||
if(getBounds().intersectsRay(v0, dir)) {
|
if(getBounds().intersectsRay(v0, dir)) {
|
||||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||||
if(collider) {
|
if(collider) {
|
||||||
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0; i<8; i++) {
|
for(int i=0; i<8; i++) {
|
||||||
if(m_children[i]) {
|
if(m_children[i]) {
|
||||||
if(m_children[i]->rayCast(v0, dir, hitinfo, layer_mask)) {
|
if(m_children[i]->rayCast(v0, dir, hitinfo, layer_mask)) {
|
||||||
hit_found = true;
|
hit_found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return hit_found;
|
return hit_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KROctreeNode::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
|
bool KROctreeNode::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
|
||||||
{
|
{
|
||||||
bool hit_found = false;
|
bool hit_found = false;
|
||||||
/*
|
/*
|
||||||
// FINDME, TODO - Adapt this optimization to work with sphereCasts
|
// FINDME, TODO - Adapt this optimization to work with sphereCasts
|
||||||
|
|
||||||
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
|
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
|
||||||
// Optimization: If we already have a hit, only search for hits that are closer
|
// Optimization: If we already have a hit, only search for hits that are closer
|
||||||
hit_found = sphereCast(v0, hitinfo.getPosition(), radius, hitinfo, layer_mask);
|
hit_found = sphereCast(v0, hitinfo.getPosition(), radius, hitinfo, layer_mask);
|
||||||
} else {
|
} else {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AABB swept_bounds = AABB(Vector3(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius), Vector3(KRMAX(v0.x, v1.x) + radius, KRMAX(v0.y, v1.y) + radius, KRMAX(v0.z, v1.z) + radius));
|
AABB swept_bounds = AABB::Create(Vector3::Create(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius), Vector3::Create(KRMAX(v0.x, v1.x) + radius, KRMAX(v0.y, v1.y) + radius, KRMAX(v0.z, v1.z) + radius));
|
||||||
// FINDME, TODO - Investigate AABB - swept sphere intersections or OBB - AABB intersections: "if(getBounds().intersectsSweptSphere(v0, v1, radius)) {"
|
// FINDME, TODO - Investigate AABB - swept sphere intersections or OBB - AABB intersections: "if(getBounds().intersectsSweptSphere(v0, v1, radius)) {"
|
||||||
if(getBounds().intersects(swept_bounds)) {
|
if(getBounds().intersects(swept_bounds)) {
|
||||||
|
|
||||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||||
if(collider) {
|
if(collider) {
|
||||||
if(collider->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
if(collider->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0; i<8; i++) {
|
for(int i=0; i<8; i++) {
|
||||||
if(m_children[i]) {
|
if(m_children[i]) {
|
||||||
if(m_children[i]->sphereCast(v0, v1, radius, hitinfo, layer_mask)) {
|
if(m_children[i]->sphereCast(v0, v1, radius, hitinfo, layer_mask)) {
|
||||||
hit_found = true;
|
hit_found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return hit_found;
|
return hit_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,65 +1,65 @@
|
|||||||
//
|
//
|
||||||
// KROctreeNode.h
|
// KROctreeNode.h
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 2012-08-29.
|
// Created by Kearwood Gilbert on 2012-08-29.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef KROCTREENODE_H
|
#ifndef KROCTREENODE_H
|
||||||
#define KROCTREENODE_H
|
#define KROCTREENODE_H
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
#include "public/hitinfo.h"
|
#include "hitinfo.h"
|
||||||
|
|
||||||
class KRNode;
|
class KRNode;
|
||||||
|
|
||||||
class KROctreeNode {
|
class KROctreeNode {
|
||||||
public:
|
public:
|
||||||
KROctreeNode(KROctreeNode *parent, const AABB &bounds);
|
KROctreeNode(KROctreeNode *parent, const AABB &bounds);
|
||||||
KROctreeNode(KROctreeNode *parent, const AABB &bounds, int iChild, KROctreeNode *pChild);
|
KROctreeNode(KROctreeNode *parent, const AABB &bounds, int iChild, KROctreeNode *pChild);
|
||||||
~KROctreeNode();
|
~KROctreeNode();
|
||||||
|
|
||||||
KROctreeNode **getChildren();
|
KROctreeNode **getChildren();
|
||||||
std::set<KRNode *> &getSceneNodes();
|
std::set<KRNode *> &getSceneNodes();
|
||||||
|
|
||||||
void add(KRNode *pNode);
|
void add(KRNode *pNode);
|
||||||
void remove(KRNode *pNode);
|
void remove(KRNode *pNode);
|
||||||
void update(KRNode *pNode);
|
void update(KRNode *pNode);
|
||||||
|
|
||||||
AABB getBounds();
|
AABB getBounds();
|
||||||
|
|
||||||
KROctreeNode *getParent();
|
KROctreeNode *getParent();
|
||||||
void setChildNode(int iChild, KROctreeNode *pChild);
|
void setChildNode(int iChild, KROctreeNode *pChild);
|
||||||
int getChildIndex(KRNode *pNode);
|
int getChildIndex(KRNode *pNode);
|
||||||
AABB getChildBounds(int iChild);
|
AABB getChildBounds(int iChild);
|
||||||
void trim();
|
void trim();
|
||||||
bool isEmpty() const;
|
bool isEmpty() const;
|
||||||
|
|
||||||
bool canShrinkRoot() const;
|
bool canShrinkRoot() const;
|
||||||
KROctreeNode *stripChild();
|
KROctreeNode *stripChild();
|
||||||
|
|
||||||
void beginOcclusionQuery();
|
void beginOcclusionQuery();
|
||||||
void endOcclusionQuery();
|
void endOcclusionQuery();
|
||||||
|
|
||||||
|
|
||||||
GLuint m_occlusionQuery;
|
GLuint m_occlusionQuery;
|
||||||
bool m_occlusionTested;
|
bool m_occlusionTested;
|
||||||
bool m_activeQuery;
|
bool m_activeQuery;
|
||||||
|
|
||||||
bool lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask);
|
bool lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask);
|
||||||
bool rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask);
|
bool rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask);
|
||||||
bool sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask);
|
bool sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
AABB m_bounds;
|
AABB m_bounds;
|
||||||
|
|
||||||
KROctreeNode *m_parent;
|
KROctreeNode *m_parent;
|
||||||
KROctreeNode *m_children[8];
|
KROctreeNode *m_children[8];
|
||||||
|
|
||||||
std::set<KRNode *>m_sceneNodes;
|
std::set<KRNode *>m_sceneNodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* defined(KROCTREENODE_H) */
|
#endif /* defined(KROCTREENODE_H) */
|
||||||
|
|||||||
@@ -1,226 +1,226 @@
|
|||||||
//
|
//
|
||||||
// KRPointLight.cpp
|
// KRPointLight.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 12-04-05.
|
// Created by Kearwood Gilbert on 12-04-05.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
#include "KRPointLight.h"
|
#include "KRPointLight.h"
|
||||||
#include "KRCamera.h"
|
#include "KRCamera.h"
|
||||||
#include "KRContext.h"
|
#include "KRContext.h"
|
||||||
#include "KRStockGeometry.h"
|
#include "KRStockGeometry.h"
|
||||||
|
|
||||||
KRPointLight::KRPointLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
KRPointLight::KRPointLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
||||||
{
|
{
|
||||||
m_sphereVertices = NULL;
|
m_sphereVertices = NULL;
|
||||||
m_cVertices = 0;
|
m_cVertices = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRPointLight::~KRPointLight()
|
KRPointLight::~KRPointLight()
|
||||||
{
|
{
|
||||||
if(m_sphereVertices) {
|
if(m_sphereVertices) {
|
||||||
delete m_sphereVertices;
|
delete m_sphereVertices;
|
||||||
m_cVertices = 0;
|
m_cVertices = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KRPointLight::getElementName() {
|
std::string KRPointLight::getElementName() {
|
||||||
return "point_light";
|
return "point_light";
|
||||||
}
|
}
|
||||||
|
|
||||||
AABB KRPointLight::getBounds() {
|
AABB KRPointLight::getBounds() {
|
||||||
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
||||||
if(influence_radius < m_flareOcclusionSize) {
|
if(influence_radius < m_flareOcclusionSize) {
|
||||||
influence_radius = m_flareOcclusionSize;
|
influence_radius = m_flareOcclusionSize;
|
||||||
}
|
}
|
||||||
return AABB(Vector3(-influence_radius), Vector3(influence_radius), getModelMatrix());
|
return AABB::Create(Vector3::Create(-influence_radius), Vector3::Create(influence_radius), getModelMatrix());
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRPointLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
|
void KRPointLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
|
||||||
{
|
{
|
||||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||||
|
|
||||||
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||||
|
|
||||||
bool bVisualize = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.bShowDeferred;
|
bool bVisualize = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.bShowDeferred;
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS || bVisualize) {
|
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS || bVisualize) {
|
||||||
// Lights are rendered on the second pass of the deferred renderer
|
// Lights are rendered on the second pass of the deferred renderer
|
||||||
|
|
||||||
std::vector<KRPointLight *> this_light;
|
std::vector<KRPointLight *> this_light;
|
||||||
this_light.push_back(this);
|
this_light.push_back(this);
|
||||||
|
|
||||||
Vector3 light_position = getLocalTranslation();
|
Vector3 light_position = getLocalTranslation();
|
||||||
|
|
||||||
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
||||||
|
|
||||||
Matrix4 sphereModelMatrix = Matrix4();
|
Matrix4 sphereModelMatrix = Matrix4();
|
||||||
sphereModelMatrix.scale(influence_radius);
|
sphereModelMatrix.scale(influence_radius);
|
||||||
sphereModelMatrix.translate(light_position.x, light_position.y, light_position.z);
|
sphereModelMatrix.translate(light_position.x, light_position.y, light_position.z);
|
||||||
|
|
||||||
if(viewport.visible(getBounds())) { // Cull out any lights not within the view frustrum
|
if(viewport.visible(getBounds())) { // Cull out any lights not within the view frustrum
|
||||||
|
|
||||||
Vector3 view_light_position = Matrix4::Dot(viewport.getViewMatrix(), light_position);
|
Vector3 view_light_position = Matrix4::Dot(viewport.getViewMatrix(), light_position);
|
||||||
|
|
||||||
bool bInsideLight = view_light_position.sqrMagnitude() <= (influence_radius + pCamera->settings.getPerspectiveNearZ()) * (influence_radius + pCamera->settings.getPerspectiveNearZ());
|
bool bInsideLight = view_light_position.sqrMagnitude() <= (influence_radius + pCamera->settings.getPerspectiveNearZ()) * (influence_radius + pCamera->settings.getPerspectiveNearZ());
|
||||||
|
|
||||||
KRShader *pShader = getContext().getShaderManager()->getShader(bVisualize ? "visualize_overlay" : (bInsideLight ? "light_point_inside" : "light_point"), pCamera, this_light, std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
KRShader *pShader = getContext().getShaderManager()->getShader(bVisualize ? "visualize_overlay" : (bInsideLight ? "light_point_inside" : "light_point"), pCamera, this_light, std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, this_light, std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, this_light, std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||||
|
|
||||||
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color);
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f);
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_DECAY_START, getDecayStart());
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_DECAY_START, getDecayStart());
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_CUTOFF, KRLIGHT_MIN_INFLUENCE);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_CUTOFF, KRLIGHT_MIN_INFLUENCE);
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_POSITION, light_position);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_POSITION, light_position);
|
||||||
|
|
||||||
|
|
||||||
if(bVisualize) {
|
if(bVisualize) {
|
||||||
// Enable additive blending
|
// Enable additive blending
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
GLDEBUG(glEnable(GL_BLEND));
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable z-buffer write
|
// Disable z-buffer write
|
||||||
GLDEBUG(glDepthMask(GL_FALSE));
|
GLDEBUG(glDepthMask(GL_FALSE));
|
||||||
|
|
||||||
|
|
||||||
if(bInsideLight) {
|
if(bInsideLight) {
|
||||||
|
|
||||||
// Disable z-buffer test
|
// Disable z-buffer test
|
||||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||||
|
|
||||||
// Render a full screen quad
|
// Render a full screen quad
|
||||||
m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
||||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||||
} else {
|
} else {
|
||||||
#if GL_OES_vertex_array_object
|
#if GL_OES_vertex_array_object
|
||||||
GLDEBUG(glBindVertexArrayOES(0));
|
GLDEBUG(glBindVertexArrayOES(0));
|
||||||
#endif
|
#endif
|
||||||
m_pContext->getMeshManager()->configureAttribs(1 << KRMesh::KRENGINE_ATTRIB_VERTEX);
|
m_pContext->getMeshManager()->configureAttribs(1 << KRMesh::KRENGINE_ATTRIB_VERTEX);
|
||||||
// Render sphere of light's influence
|
// Render sphere of light's influence
|
||||||
generateMesh();
|
generateMesh();
|
||||||
|
|
||||||
// Enable z-buffer test
|
// Enable z-buffer test
|
||||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||||
|
|
||||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_VERTEX, 3, GL_FLOAT, 0, 0, m_sphereVertices));
|
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_VERTEX, 3, GL_FLOAT, 0, 0, m_sphereVertices));
|
||||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, m_cVertices));
|
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, m_cVertices));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(bVisualize) {
|
if(bVisualize) {
|
||||||
// Enable alpha blending
|
// Enable alpha blending
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
GLDEBUG(glEnable(GL_BLEND));
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRPointLight::generateMesh() {
|
void KRPointLight::generateMesh() {
|
||||||
// Create a triangular facet approximation to a sphere
|
// Create a triangular facet approximation to a sphere
|
||||||
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
|
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
|
||||||
|
|
||||||
int iterations = 3;
|
int iterations = 3;
|
||||||
int facet_count = pow(4, iterations) * 8;
|
int facet_count = pow(4, iterations) * 8;
|
||||||
|
|
||||||
if(m_cVertices != facet_count * 3) {
|
if(m_cVertices != facet_count * 3) {
|
||||||
if(m_sphereVertices) {
|
if(m_sphereVertices) {
|
||||||
free(m_sphereVertices);
|
free(m_sphereVertices);
|
||||||
m_sphereVertices = NULL;
|
m_sphereVertices = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cVertices = facet_count * 3;
|
m_cVertices = facet_count * 3;
|
||||||
|
|
||||||
|
|
||||||
class Facet3 {
|
class Facet3 {
|
||||||
public:
|
public:
|
||||||
Facet3() {
|
Facet3() {
|
||||||
|
|
||||||
}
|
}
|
||||||
~Facet3() {
|
~Facet3() {
|
||||||
|
|
||||||
}
|
}
|
||||||
Vector3 p1;
|
Vector3 p1;
|
||||||
Vector3 p2;
|
Vector3 p2;
|
||||||
Vector3 p3;
|
Vector3 p3;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Facet3> f = std::vector<Facet3>(facet_count);
|
std::vector<Facet3> f = std::vector<Facet3>(facet_count);
|
||||||
|
|
||||||
int i,it;
|
int i,it;
|
||||||
float a;
|
float a;
|
||||||
Vector3 p[6] = {
|
Vector3 p[6] = {
|
||||||
Vector3(0,0,1),
|
Vector3::Create(0,0,1),
|
||||||
Vector3(0,0,-1),
|
Vector3::Create(0,0,-1),
|
||||||
Vector3(-1,-1,0),
|
Vector3::Create(-1,-1,0),
|
||||||
Vector3(1,-1,0),
|
Vector3::Create(1,-1,0),
|
||||||
Vector3(1,1,0),
|
Vector3::Create(1,1,0),
|
||||||
Vector3(-1,1,0)
|
Vector3::Create(-1,1,0)
|
||||||
};
|
};
|
||||||
|
|
||||||
Vector3 pa,pb,pc;
|
Vector3 pa,pb,pc;
|
||||||
int nt = 0,ntold;
|
int nt = 0,ntold;
|
||||||
|
|
||||||
/* Create the level 0 object */
|
/* Create the level 0 object */
|
||||||
a = 1 / sqrt(2.0);
|
a = 1.0f / sqrtf(2.0f);
|
||||||
for (i=0;i<6;i++) {
|
for (i=0;i<6;i++) {
|
||||||
p[i].x *= a;
|
p[i].x *= a;
|
||||||
p[i].y *= a;
|
p[i].y *= a;
|
||||||
}
|
}
|
||||||
f[0].p1 = p[0]; f[0].p2 = p[3]; f[0].p3 = p[4];
|
f[0].p1 = p[0]; f[0].p2 = p[3]; f[0].p3 = p[4];
|
||||||
f[1].p1 = p[0]; f[1].p2 = p[4]; f[1].p3 = p[5];
|
f[1].p1 = p[0]; f[1].p2 = p[4]; f[1].p3 = p[5];
|
||||||
f[2].p1 = p[0]; f[2].p2 = p[5]; f[2].p3 = p[2];
|
f[2].p1 = p[0]; f[2].p2 = p[5]; f[2].p3 = p[2];
|
||||||
f[3].p1 = p[0]; f[3].p2 = p[2]; f[3].p3 = p[3];
|
f[3].p1 = p[0]; f[3].p2 = p[2]; f[3].p3 = p[3];
|
||||||
f[4].p1 = p[1]; f[4].p2 = p[4]; f[4].p3 = p[3];
|
f[4].p1 = p[1]; f[4].p2 = p[4]; f[4].p3 = p[3];
|
||||||
f[5].p1 = p[1]; f[5].p2 = p[5]; f[5].p3 = p[4];
|
f[5].p1 = p[1]; f[5].p2 = p[5]; f[5].p3 = p[4];
|
||||||
f[6].p1 = p[1]; f[6].p2 = p[2]; f[6].p3 = p[5];
|
f[6].p1 = p[1]; f[6].p2 = p[2]; f[6].p3 = p[5];
|
||||||
f[7].p1 = p[1]; f[7].p2 = p[3]; f[7].p3 = p[2];
|
f[7].p1 = p[1]; f[7].p2 = p[3]; f[7].p3 = p[2];
|
||||||
nt = 8;
|
nt = 8;
|
||||||
|
|
||||||
/* Bisect each edge and move to the surface of a unit sphere */
|
/* Bisect each edge and move to the surface of a unit sphere */
|
||||||
for (it=0;it<iterations;it++) {
|
for (it=0;it<iterations;it++) {
|
||||||
ntold = nt;
|
ntold = nt;
|
||||||
for (i=0;i<ntold;i++) {
|
for (i=0;i<ntold;i++) {
|
||||||
pa.x = (f[i].p1.x + f[i].p2.x) / 2;
|
pa.x = (f[i].p1.x + f[i].p2.x) / 2;
|
||||||
pa.y = (f[i].p1.y + f[i].p2.y) / 2;
|
pa.y = (f[i].p1.y + f[i].p2.y) / 2;
|
||||||
pa.z = (f[i].p1.z + f[i].p2.z) / 2;
|
pa.z = (f[i].p1.z + f[i].p2.z) / 2;
|
||||||
pb.x = (f[i].p2.x + f[i].p3.x) / 2;
|
pb.x = (f[i].p2.x + f[i].p3.x) / 2;
|
||||||
pb.y = (f[i].p2.y + f[i].p3.y) / 2;
|
pb.y = (f[i].p2.y + f[i].p3.y) / 2;
|
||||||
pb.z = (f[i].p2.z + f[i].p3.z) / 2;
|
pb.z = (f[i].p2.z + f[i].p3.z) / 2;
|
||||||
pc.x = (f[i].p3.x + f[i].p1.x) / 2;
|
pc.x = (f[i].p3.x + f[i].p1.x) / 2;
|
||||||
pc.y = (f[i].p3.y + f[i].p1.y) / 2;
|
pc.y = (f[i].p3.y + f[i].p1.y) / 2;
|
||||||
pc.z = (f[i].p3.z + f[i].p1.z) / 2;
|
pc.z = (f[i].p3.z + f[i].p1.z) / 2;
|
||||||
pa.normalize();
|
pa.normalize();
|
||||||
pb.normalize();
|
pb.normalize();
|
||||||
pc.normalize();
|
pc.normalize();
|
||||||
f[nt].p1 = f[i].p1; f[nt].p2 = pa; f[nt].p3 = pc; nt++;
|
f[nt].p1 = f[i].p1; f[nt].p2 = pa; f[nt].p3 = pc; nt++;
|
||||||
f[nt].p1 = pa; f[nt].p2 = f[i].p2; f[nt].p3 = pb; nt++;
|
f[nt].p1 = pa; f[nt].p2 = f[i].p2; f[nt].p3 = pb; nt++;
|
||||||
f[nt].p1 = pb; f[nt].p2 = f[i].p3; f[nt].p3 = pc; nt++;
|
f[nt].p1 = pb; f[nt].p2 = f[i].p3; f[nt].p3 = pc; nt++;
|
||||||
f[i].p1 = pa;
|
f[i].p1 = pa;
|
||||||
f[i].p2 = pb;
|
f[i].p2 = pb;
|
||||||
f[i].p3 = pc;
|
f[i].p3 = pc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_sphereVertices = (GLfloat *)malloc(sizeof(GLfloat) * m_cVertices * 3);
|
m_sphereVertices = (GLfloat *)malloc(sizeof(GLfloat) * m_cVertices * 3);
|
||||||
assert(m_sphereVertices != NULL);
|
assert(m_sphereVertices != NULL);
|
||||||
GLfloat *pDest = m_sphereVertices;
|
GLfloat *pDest = m_sphereVertices;
|
||||||
for(int facet_index=0; facet_index < facet_count; facet_index++) {
|
for(int facet_index=0; facet_index < facet_count; facet_index++) {
|
||||||
*pDest++ = f[facet_index].p1.x;
|
*pDest++ = f[facet_index].p1.x;
|
||||||
*pDest++ = f[facet_index].p1.y;
|
*pDest++ = f[facet_index].p1.y;
|
||||||
*pDest++ = f[facet_index].p1.z;
|
*pDest++ = f[facet_index].p1.z;
|
||||||
*pDest++ = f[facet_index].p2.x;
|
*pDest++ = f[facet_index].p2.x;
|
||||||
*pDest++ = f[facet_index].p2.y;
|
*pDest++ = f[facet_index].p2.y;
|
||||||
*pDest++ = f[facet_index].p2.z;
|
*pDest++ = f[facet_index].p2.z;
|
||||||
*pDest++ = f[facet_index].p3.x;
|
*pDest++ = f[facet_index].p3.x;
|
||||||
*pDest++ = f[facet_index].p3.y;
|
*pDest++ = f[facet_index].p3.y;
|
||||||
*pDest++ = f[facet_index].p3.z;
|
*pDest++ = f[facet_index].p3.z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,204 +1,204 @@
|
|||||||
//
|
//
|
||||||
// KRRenderSettings.cpp
|
// KRRenderSettings.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 2012-12-20.
|
// Created by Kearwood Gilbert on 2012-12-20.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KRRenderSettings.h"
|
#include "KRRenderSettings.h"
|
||||||
|
|
||||||
KRRenderSettings::KRRenderSettings()
|
KRRenderSettings::KRRenderSettings()
|
||||||
{
|
{
|
||||||
siren_enable = true;
|
siren_enable = true;
|
||||||
siren_enable_reverb = true;
|
siren_enable_reverb = true;
|
||||||
siren_enable_hrtf = true;
|
siren_enable_hrtf = true;
|
||||||
siren_reverb_max_length = 2.0f;
|
siren_reverb_max_length = 2.0f;
|
||||||
|
|
||||||
m_enable_realtime_occlusion = false;
|
m_enable_realtime_occlusion = false;
|
||||||
bShowShadowBuffer = false;
|
bShowShadowBuffer = false;
|
||||||
bShowOctree = false;
|
bShowOctree = false;
|
||||||
bShowDeferred = false;
|
bShowDeferred = false;
|
||||||
bEnablePerPixel = true;
|
bEnablePerPixel = true;
|
||||||
bEnableDiffuseMap = true;
|
bEnableDiffuseMap = true;
|
||||||
bEnableNormalMap = true;
|
bEnableNormalMap = true;
|
||||||
bEnableSpecMap = true;
|
bEnableSpecMap = true;
|
||||||
bEnableReflectionMap = true;
|
bEnableReflectionMap = true;
|
||||||
bEnableReflection = true;
|
bEnableReflection = true;
|
||||||
bDebugPSSM = false;
|
bDebugPSSM = false;
|
||||||
bEnableAmbient = true;
|
bEnableAmbient = true;
|
||||||
bEnableDiffuse = true;
|
bEnableDiffuse = true;
|
||||||
bEnableSpecular = true;
|
bEnableSpecular = true;
|
||||||
bEnableLightMap = true;
|
bEnableLightMap = true;
|
||||||
bEnableDeferredLighting = false;
|
bEnableDeferredLighting = false;
|
||||||
max_anisotropy = 4.0f;
|
max_anisotropy = 4.0f;
|
||||||
|
|
||||||
ambient_intensity = Vector3::Zero();
|
ambient_intensity = Vector3::Zero();
|
||||||
light_intensity = Vector3::One();
|
light_intensity = Vector3::One();
|
||||||
|
|
||||||
perspective_fov = 45.0 * D2R;
|
perspective_fov = 45.0f * D2R;
|
||||||
perspective_nearz = 0.3f; // was 0.05f
|
perspective_nearz = 0.3f; // was 0.05f
|
||||||
perspective_farz = 1000.0f;
|
perspective_farz = 1000.0f;
|
||||||
|
|
||||||
dof_quality = 0;
|
dof_quality = 0;
|
||||||
dof_depth = 0.05f;
|
dof_depth = 0.05f;
|
||||||
dof_falloff = 0.05f;
|
dof_falloff = 0.05f;
|
||||||
|
|
||||||
bEnableFlash = false;
|
bEnableFlash = false;
|
||||||
flash_intensity = 1.0f;
|
flash_intensity = 1.0f;
|
||||||
flash_depth = 0.7f;
|
flash_depth = 0.7f;
|
||||||
flash_falloff = 0.5f;
|
flash_falloff = 0.5f;
|
||||||
|
|
||||||
|
|
||||||
bEnableVignette = false;
|
bEnableVignette = false;
|
||||||
vignette_radius = 0.4f;
|
vignette_radius = 0.4f;
|
||||||
vignette_falloff = 1.0f;
|
vignette_falloff = 1.0f;
|
||||||
|
|
||||||
|
|
||||||
m_cShadowBuffers = 0;
|
m_cShadowBuffers = 0;
|
||||||
|
|
||||||
volumetric_environment_enable = false;
|
volumetric_environment_enable = false;
|
||||||
volumetric_environment_downsample = 2;
|
volumetric_environment_downsample = 2;
|
||||||
volumetric_environment_max_distance = 100.0f;
|
volumetric_environment_max_distance = 100.0f;
|
||||||
volumetric_environment_quality = (50 - 5.0) / 495.0f;
|
volumetric_environment_quality = (50.0f - 5.0f) / 495.0f;
|
||||||
volumetric_environment_intensity = 0.9f;
|
volumetric_environment_intensity = 0.9f;
|
||||||
|
|
||||||
|
|
||||||
fog_near = 50.0f;
|
fog_near = 50.0f;
|
||||||
fog_far = 500.0f;
|
fog_far = 500.0f;
|
||||||
fog_density = 0.0005f;
|
fog_density = 0.0005f;
|
||||||
fog_color = Vector3(0.45, 0.45, 0.5);
|
fog_color = Vector3::Create(0.45f, 0.45f, 0.5f);
|
||||||
fog_type = 0;
|
fog_type = 0;
|
||||||
|
|
||||||
dust_particle_intensity = 0.25f;
|
dust_particle_intensity = 0.25f;
|
||||||
dust_particle_enable = false;
|
dust_particle_enable = false;
|
||||||
|
|
||||||
m_lodBias = 0.0f;
|
m_lodBias = 0.0f;
|
||||||
|
|
||||||
debug_display = KRENGINE_DEBUG_DISPLAY_NONE;
|
debug_display = KRENGINE_DEBUG_DISPLAY_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRRenderSettings::~KRRenderSettings()
|
KRRenderSettings::~KRRenderSettings()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KRRenderSettings& KRRenderSettings::operator=(const KRRenderSettings &s)
|
KRRenderSettings& KRRenderSettings::operator=(const KRRenderSettings &s)
|
||||||
{
|
{
|
||||||
siren_enable = s.siren_enable;
|
siren_enable = s.siren_enable;
|
||||||
siren_enable_reverb = s.siren_enable_reverb;
|
siren_enable_reverb = s.siren_enable_reverb;
|
||||||
siren_enable_hrtf = s.siren_enable_hrtf;
|
siren_enable_hrtf = s.siren_enable_hrtf;
|
||||||
siren_reverb_max_length = s.siren_reverb_max_length;
|
siren_reverb_max_length = s.siren_reverb_max_length;
|
||||||
|
|
||||||
bEnablePerPixel = s.bEnablePerPixel;
|
bEnablePerPixel = s.bEnablePerPixel;
|
||||||
bEnableDiffuseMap = s.bEnableDiffuseMap;
|
bEnableDiffuseMap = s.bEnableDiffuseMap;
|
||||||
bEnableNormalMap = s.bEnableNormalMap;
|
bEnableNormalMap = s.bEnableNormalMap;
|
||||||
bEnableSpecMap = s.bEnableSpecMap;
|
bEnableSpecMap = s.bEnableSpecMap;
|
||||||
bEnableReflectionMap = s.bEnableReflectionMap;
|
bEnableReflectionMap = s.bEnableReflectionMap;
|
||||||
bEnableReflection=s.bEnableReflection;
|
bEnableReflection=s.bEnableReflection;
|
||||||
bEnableLightMap=s.bEnableLightMap;
|
bEnableLightMap=s.bEnableLightMap;
|
||||||
bDebugPSSM=s.bDebugPSSM;
|
bDebugPSSM=s.bDebugPSSM;
|
||||||
bShowShadowBuffer=s.bShowShadowBuffer;
|
bShowShadowBuffer=s.bShowShadowBuffer;
|
||||||
bShowOctree=s.bShowOctree;
|
bShowOctree=s.bShowOctree;
|
||||||
bShowDeferred=s.bShowDeferred;
|
bShowDeferred=s.bShowDeferred;
|
||||||
bEnableAmbient=s.bEnableAmbient;
|
bEnableAmbient=s.bEnableAmbient;
|
||||||
bEnableDiffuse=s.bEnableDiffuse;
|
bEnableDiffuse=s.bEnableDiffuse;
|
||||||
bEnableSpecular=s.bEnableSpecular;
|
bEnableSpecular=s.bEnableSpecular;
|
||||||
bEnableDeferredLighting=s.bEnableDeferredLighting;
|
bEnableDeferredLighting=s.bEnableDeferredLighting;
|
||||||
light_intensity=s.light_intensity;
|
light_intensity=s.light_intensity;
|
||||||
ambient_intensity=s.ambient_intensity;
|
ambient_intensity=s.ambient_intensity;
|
||||||
perspective_fov=s.perspective_fov;
|
perspective_fov=s.perspective_fov;
|
||||||
|
|
||||||
dof_quality=s.dof_quality;
|
dof_quality=s.dof_quality;
|
||||||
dof_depth=s.dof_depth;
|
dof_depth=s.dof_depth;
|
||||||
dof_falloff=s.dof_falloff;
|
dof_falloff=s.dof_falloff;
|
||||||
bEnableFlash=s.bEnableFlash;
|
bEnableFlash=s.bEnableFlash;
|
||||||
flash_intensity=s.flash_intensity;
|
flash_intensity=s.flash_intensity;
|
||||||
flash_depth=s.flash_depth;
|
flash_depth=s.flash_depth;
|
||||||
flash_falloff=s.flash_falloff;
|
flash_falloff=s.flash_falloff;
|
||||||
|
|
||||||
bEnableVignette=s.bEnableVignette;
|
bEnableVignette=s.bEnableVignette;
|
||||||
vignette_radius=s.vignette_radius;
|
vignette_radius=s.vignette_radius;
|
||||||
vignette_falloff=s.vignette_falloff;
|
vignette_falloff=s.vignette_falloff;
|
||||||
|
|
||||||
m_viewportSize=s.m_viewportSize;
|
m_viewportSize=s.m_viewportSize;
|
||||||
|
|
||||||
m_cShadowBuffers=s.m_cShadowBuffers;
|
m_cShadowBuffers=s.m_cShadowBuffers;
|
||||||
|
|
||||||
m_debug_text=s.m_debug_text;
|
m_debug_text=s.m_debug_text;
|
||||||
|
|
||||||
volumetric_environment_enable=s.volumetric_environment_enable;
|
volumetric_environment_enable=s.volumetric_environment_enable;
|
||||||
volumetric_environment_downsample=s.volumetric_environment_downsample;
|
volumetric_environment_downsample=s.volumetric_environment_downsample;
|
||||||
volumetric_environment_max_distance=s.volumetric_environment_max_distance;
|
volumetric_environment_max_distance=s.volumetric_environment_max_distance;
|
||||||
volumetric_environment_quality=s.volumetric_environment_quality;
|
volumetric_environment_quality=s.volumetric_environment_quality;
|
||||||
volumetric_environment_intensity=s.volumetric_environment_intensity;
|
volumetric_environment_intensity=s.volumetric_environment_intensity;
|
||||||
|
|
||||||
fog_near=s.fog_near;
|
fog_near=s.fog_near;
|
||||||
fog_far=s.fog_far;
|
fog_far=s.fog_far;
|
||||||
fog_density=s.fog_density;
|
fog_density=s.fog_density;
|
||||||
fog_color=s.fog_color;
|
fog_color=s.fog_color;
|
||||||
fog_type=s.fog_type;
|
fog_type=s.fog_type;
|
||||||
|
|
||||||
dust_particle_intensity=s.dust_particle_intensity;
|
dust_particle_intensity=s.dust_particle_intensity;
|
||||||
dust_particle_enable=s.dust_particle_enable;
|
dust_particle_enable=s.dust_particle_enable;
|
||||||
perspective_nearz=s.perspective_nearz;
|
perspective_nearz=s.perspective_nearz;
|
||||||
perspective_farz=s.perspective_farz;
|
perspective_farz=s.perspective_farz;
|
||||||
debug_display = s.debug_display;
|
debug_display = s.debug_display;
|
||||||
|
|
||||||
m_lodBias = s.m_lodBias;
|
m_lodBias = s.m_lodBias;
|
||||||
m_enable_realtime_occlusion = s.m_enable_realtime_occlusion;
|
m_enable_realtime_occlusion = s.m_enable_realtime_occlusion;
|
||||||
|
|
||||||
max_anisotropy = s.max_anisotropy;
|
max_anisotropy = s.max_anisotropy;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vector2 &KRRenderSettings::getViewportSize() {
|
const Vector2 &KRRenderSettings::getViewportSize() {
|
||||||
return m_viewportSize;
|
return m_viewportSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRRenderSettings::setViewportSize(const Vector2 &size) {
|
void KRRenderSettings::setViewportSize(const Vector2 &size) {
|
||||||
m_viewportSize = size;
|
m_viewportSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
float KRRenderSettings::getPerspectiveNearZ()
|
float KRRenderSettings::getPerspectiveNearZ()
|
||||||
{
|
{
|
||||||
return perspective_nearz;
|
return perspective_nearz;
|
||||||
}
|
}
|
||||||
float KRRenderSettings::getPerspectiveFarZ()
|
float KRRenderSettings::getPerspectiveFarZ()
|
||||||
{
|
{
|
||||||
return perspective_farz;
|
return perspective_farz;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRRenderSettings::setPerspectiveNear(float v)
|
void KRRenderSettings::setPerspectiveNear(float v)
|
||||||
{
|
{
|
||||||
if(perspective_nearz != v) {
|
if(perspective_nearz != v) {
|
||||||
perspective_nearz = v;
|
perspective_nearz = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void KRRenderSettings::setPerpsectiveFarZ(float v)
|
void KRRenderSettings::setPerpsectiveFarZ(float v)
|
||||||
{
|
{
|
||||||
if(perspective_farz != v) {
|
if(perspective_farz != v) {
|
||||||
perspective_farz = v;
|
perspective_farz = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float KRRenderSettings::getLODBias()
|
float KRRenderSettings::getLODBias()
|
||||||
{
|
{
|
||||||
return m_lodBias;
|
return m_lodBias;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRRenderSettings::setLODBias(float v)
|
void KRRenderSettings::setLODBias(float v)
|
||||||
{
|
{
|
||||||
m_lodBias = v;
|
m_lodBias = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KRRenderSettings::getEnableRealtimeOcclusion()
|
bool KRRenderSettings::getEnableRealtimeOcclusion()
|
||||||
{
|
{
|
||||||
return m_enable_realtime_occlusion;
|
return m_enable_realtime_occlusion;
|
||||||
}
|
}
|
||||||
void KRRenderSettings::setEnableRealtimeOcclusion(bool enable)
|
void KRRenderSettings::setEnableRealtimeOcclusion(bool enable)
|
||||||
{
|
{
|
||||||
m_enable_realtime_occlusion = enable;
|
m_enable_realtime_occlusion = enable;
|
||||||
}
|
}
|
||||||
@@ -1,341 +1,341 @@
|
|||||||
//
|
//
|
||||||
// KRResource_obj.cpp
|
// KRResource_obj.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 12-03-22.
|
// Created by Kearwood Gilbert on 12-03-22.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
#include "KRResource.h"
|
#include "KRResource.h"
|
||||||
#include "KRMesh.h"
|
#include "KRMesh.h"
|
||||||
|
|
||||||
std::vector<KRResource *> KRResource::LoadObj(KRContext &context, const std::string& path)
|
std::vector<KRResource *> KRResource::LoadObj(KRContext &context, const std::string& path)
|
||||||
{
|
{
|
||||||
std::vector<KRResource *> resources;
|
std::vector<KRResource *> resources;
|
||||||
|
|
||||||
KRMesh *new_mesh = new KRMesh(context, KRResource::GetFileBase(path));
|
KRMesh *new_mesh = new KRMesh(context, KRResource::GetFileBase(path));
|
||||||
resources.push_back(new_mesh);
|
resources.push_back(new_mesh);
|
||||||
|
|
||||||
KRMesh::mesh_info mi;
|
KRMesh::mesh_info mi;
|
||||||
|
|
||||||
std::vector<std::string> material_names_t;
|
std::vector<std::string> material_names_t;
|
||||||
|
|
||||||
KRDataBlock data;
|
KRDataBlock data;
|
||||||
|
|
||||||
char szSymbol[500][256];
|
char szSymbol[500][256];
|
||||||
|
|
||||||
int *pFaces = NULL;
|
int *pFaces = NULL;
|
||||||
|
|
||||||
vector<KRMesh::pack_material *> m_materials;
|
vector<KRMesh::pack_material *> m_materials;
|
||||||
|
|
||||||
if(data.load(path)) {
|
if(data.load(path)) {
|
||||||
// -----=====----- Get counts -----=====-----
|
// -----=====----- Get counts -----=====-----
|
||||||
|
|
||||||
int cVertexData = 0;
|
int cVertexData = 0;
|
||||||
|
|
||||||
|
|
||||||
int cFaces = 1;
|
int cFaces = 1;
|
||||||
int cMaterialFaceStart = 1;
|
int cMaterialFaceStart = 1;
|
||||||
|
|
||||||
char *pScan = (char *)data.getStart();
|
char *pScan = (char *)data.getStart();
|
||||||
char *pEnd = (char *)data.getEnd();
|
char *pEnd = (char *)data.getEnd();
|
||||||
while(pScan < pEnd) {
|
while(pScan < pEnd) {
|
||||||
|
|
||||||
// Scan through whitespace
|
// Scan through whitespace
|
||||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||||
pScan++;
|
pScan++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(*pScan == '#') {
|
if(*pScan == '#') {
|
||||||
// Line is a comment line
|
// Line is a comment line
|
||||||
|
|
||||||
// Scan to the end of the line
|
// Scan to the end of the line
|
||||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||||
pScan++;
|
pScan++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int cSymbols = 0;
|
int cSymbols = 0;
|
||||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||||
|
|
||||||
char *pDest = szSymbol[cSymbols++];
|
char *pDest = szSymbol[cSymbols++];
|
||||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||||
*pDest++ = *pScan++;
|
*pDest++ = *pScan++;
|
||||||
}
|
}
|
||||||
*pDest = '\0';
|
*pDest = '\0';
|
||||||
|
|
||||||
// Scan through whitespace, but don't advance to next line
|
// Scan through whitespace, but don't advance to next line
|
||||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
||||||
pScan++;
|
pScan++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strcmp(szSymbol[0], "v") == 0) {
|
if(strcmp(szSymbol[0], "v") == 0) {
|
||||||
// Vertex (v)
|
// Vertex (v)
|
||||||
} else if(strcmp(szSymbol[0], "vt") == 0) {
|
} else if(strcmp(szSymbol[0], "vt") == 0) {
|
||||||
// Vertex Texture UV Coordinate (vt)
|
// Vertex Texture UV Coordinate (vt)
|
||||||
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
||||||
// Vertex Normal (vn)
|
// Vertex Normal (vn)
|
||||||
} else if(strcmp(szSymbol[0], "f") == 0) {
|
} else if(strcmp(szSymbol[0], "f") == 0) {
|
||||||
// Face (f)
|
// Face (f)
|
||||||
int cFaceVertexes = (cSymbols - 3) * 3; // 3 vertexes per triangle. Triangles have 4 symbols. Quads have 5 symbols and generate two triangles.
|
int cFaceVertexes = (cSymbols - 3) * 3; // 3 vertexes per triangle. Triangles have 4 symbols. Quads have 5 symbols and generate two triangles.
|
||||||
cVertexData += cFaceVertexes;
|
cVertexData += cFaceVertexes;
|
||||||
cFaces += cFaceVertexes * 3 + 1; // Allocate space for count of vertices, Vertex Index, Texture Coordinate Index, and Normal Index
|
cFaces += cFaceVertexes * 3 + 1; // Allocate space for count of vertices, Vertex Index, Texture Coordinate Index, and Normal Index
|
||||||
|
|
||||||
} else if(strcmp(szSymbol[0], "usemtl") == 0) {
|
} else if(strcmp(szSymbol[0], "usemtl") == 0) {
|
||||||
// Use Material (usemtl)
|
// Use Material (usemtl)
|
||||||
if(cMaterialFaceStart - cFaces > 0) {
|
if(cMaterialFaceStart - cFaces > 0) {
|
||||||
cFaces++;
|
cFaces++;
|
||||||
|
|
||||||
}
|
}
|
||||||
material_names_t.push_back(std::string(szSymbol[1]));
|
material_names_t.push_back(std::string(szSymbol[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// -----=====----- Populate vertexes and faces -----=====-----
|
// -----=====----- Populate vertexes and faces -----=====-----
|
||||||
|
|
||||||
int *pFaces = (int *)malloc(sizeof(int) * (cFaces + 1));
|
int *pFaces = (int *)malloc(sizeof(int) * (cFaces + 1));
|
||||||
assert(pFaces != NULL);
|
assert(pFaces != NULL);
|
||||||
|
|
||||||
std::vector<Vector3> indexed_vertices;
|
std::vector<Vector3> indexed_vertices;
|
||||||
std::vector<Vector2> indexed_uva;
|
std::vector<Vector2> indexed_uva;
|
||||||
std::vector<Vector3> indexed_normals;
|
std::vector<Vector3> indexed_normals;
|
||||||
|
|
||||||
int *pFace = pFaces;
|
int *pFace = pFaces;
|
||||||
int *pMaterialFaces = pFace++;
|
int *pMaterialFaces = pFace++;
|
||||||
*pMaterialFaces = 0;
|
*pMaterialFaces = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// --------
|
// --------
|
||||||
|
|
||||||
pScan = (char *)data.getStart();
|
pScan = (char *)data.getStart();
|
||||||
while(pScan < pEnd) {
|
while(pScan < pEnd) {
|
||||||
|
|
||||||
// Scan through whitespace
|
// Scan through whitespace
|
||||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||||
pScan++;
|
pScan++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(*pScan == '#') {
|
if(*pScan == '#') {
|
||||||
// Line is a comment line
|
// Line is a comment line
|
||||||
|
|
||||||
// Scan to the end of the line
|
// Scan to the end of the line
|
||||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||||
pScan++;
|
pScan++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int cSymbols = 0;
|
int cSymbols = 0;
|
||||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||||
|
|
||||||
char *pDest = szSymbol[cSymbols++];
|
char *pDest = szSymbol[cSymbols++];
|
||||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||||
*pDest++ = *pScan++;
|
*pDest++ = *pScan++;
|
||||||
}
|
}
|
||||||
*pDest = '\0';
|
*pDest = '\0';
|
||||||
|
|
||||||
// Scan through whitespace, but don't advance to next line
|
// Scan through whitespace, but don't advance to next line
|
||||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
||||||
pScan++;
|
pScan++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strcmp(szSymbol[0], "v") == 0) {
|
if(strcmp(szSymbol[0], "v") == 0) {
|
||||||
// Vertex (v)
|
// Vertex (v)
|
||||||
float x, y, z;
|
float x, y, z;
|
||||||
char *pChar = szSymbol[1];
|
char *pChar = szSymbol[1];
|
||||||
x = strtof(pChar, &pChar);
|
x = strtof(pChar, &pChar);
|
||||||
pChar = szSymbol[2];
|
pChar = szSymbol[2];
|
||||||
y = strtof(pChar, &pChar);
|
y = strtof(pChar, &pChar);
|
||||||
pChar = szSymbol[3];
|
pChar = szSymbol[3];
|
||||||
z = strtof(pChar, &pChar);
|
z = strtof(pChar, &pChar);
|
||||||
indexed_vertices.push_back(Vector3(x,y,z));
|
indexed_vertices.push_back(Vector3::Create(x,y,z));
|
||||||
} else if(strcmp(szSymbol[0], "vt") == 0) {
|
} else if(strcmp(szSymbol[0], "vt") == 0) {
|
||||||
// Vertex Texture UV Coordinate (vt)
|
// Vertex Texture UV Coordinate (vt)
|
||||||
char *pChar = szSymbol[1];
|
char *pChar = szSymbol[1];
|
||||||
float u,v;
|
float u,v;
|
||||||
|
|
||||||
u = strtof(pChar, &pChar);
|
u = strtof(pChar, &pChar);
|
||||||
pChar = szSymbol[2];
|
pChar = szSymbol[2];
|
||||||
v = strtof(pChar, &pChar);
|
v = strtof(pChar, &pChar);
|
||||||
indexed_uva.push_back(Vector2(u,v));
|
indexed_uva.push_back(Vector2::Create(u,v));
|
||||||
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
||||||
// Vertex Normal (vn)
|
// Vertex Normal (vn)
|
||||||
float x,y,z;
|
float x,y,z;
|
||||||
char *pChar = szSymbol[1];
|
char *pChar = szSymbol[1];
|
||||||
x = strtof(pChar, &pChar);
|
x = strtof(pChar, &pChar);
|
||||||
pChar = szSymbol[2];
|
pChar = szSymbol[2];
|
||||||
y = strtof(pChar, &pChar);
|
y = strtof(pChar, &pChar);
|
||||||
pChar = szSymbol[3];
|
pChar = szSymbol[3];
|
||||||
z = strtof(pChar, &pChar);
|
z = strtof(pChar, &pChar);
|
||||||
indexed_normals.push_back(Vector3(x,y,z));
|
indexed_normals.push_back(Vector3::Create(x,y,z));
|
||||||
} else if(strcmp(szSymbol[0], "f") == 0) {
|
} else if(strcmp(szSymbol[0], "f") == 0) {
|
||||||
// Face (f)
|
// Face (f)
|
||||||
int cFaceVertices = cSymbols - 1;
|
int cFaceVertices = cSymbols - 1;
|
||||||
|
|
||||||
*pFace++ = cFaceVertices;
|
*pFace++ = cFaceVertices;
|
||||||
for(int iSymbol=1; iSymbol < cSymbols; iSymbol++) {
|
for(int iSymbol=1; iSymbol < cSymbols; iSymbol++) {
|
||||||
char *pChar = szSymbol[iSymbol];
|
char *pChar = szSymbol[iSymbol];
|
||||||
if(*pChar == '.' || (*pChar >= '0' && *pChar <= '9')) {
|
if(*pChar == '.' || (*pChar >= '0' && *pChar <= '9')) {
|
||||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Vertex Index
|
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Vertex Index
|
||||||
|
|
||||||
if(*pChar == '/') {
|
if(*pChar == '/') {
|
||||||
pChar++;
|
pChar++;
|
||||||
if(*pChar == '/') {
|
if(*pChar == '/') {
|
||||||
*pFace++ = -1;
|
*pFace++ = -1;
|
||||||
} else {
|
} else {
|
||||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Texture Coordinate Index
|
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Texture Coordinate Index
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*pFace++ = -1;
|
*pFace++ = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(*pChar == '/') {
|
if(*pChar == '/') {
|
||||||
pChar++;
|
pChar++;
|
||||||
if(*pChar == '/') {
|
if(*pChar == '/') {
|
||||||
*pFace++ = -1;
|
*pFace++ = -1;
|
||||||
} else {
|
} else {
|
||||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Normal Index
|
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Normal Index
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*pFace++ = -1;
|
*pFace++ = -1;
|
||||||
}
|
}
|
||||||
while(*pChar == '/') {
|
while(*pChar == '/') {
|
||||||
pChar++;
|
pChar++;
|
||||||
strtol(pChar, &pChar, 10);
|
strtol(pChar, &pChar, 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} else if(strcmp(szSymbol[0], "usemtl") == 0) {
|
} else if(strcmp(szSymbol[0], "usemtl") == 0) {
|
||||||
// Use Material (usemtl)
|
// Use Material (usemtl)
|
||||||
if(pFace - pMaterialFaces > 1) {
|
if(pFace - pMaterialFaces > 1) {
|
||||||
*pMaterialFaces = pFace - pMaterialFaces - 1;
|
*pMaterialFaces = pFace - pMaterialFaces - 1;
|
||||||
pMaterialFaces = pFace++;
|
pMaterialFaces = pFace++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
*pMaterialFaces = pFace - pMaterialFaces - 1;
|
*pMaterialFaces = pFace - pMaterialFaces - 1;
|
||||||
*pFace++ = 0;
|
*pFace++ = 0;
|
||||||
|
|
||||||
|
|
||||||
int iVertex = 0;
|
int iVertex = 0;
|
||||||
|
|
||||||
|
|
||||||
std::vector<std::string>::iterator material_itr = material_names_t.begin();
|
std::vector<std::string>::iterator material_itr = material_names_t.begin();
|
||||||
KRMesh::pack_material *pMaterial = new KRMesh::pack_material();
|
KRMesh::pack_material *pMaterial = new KRMesh::pack_material();
|
||||||
pMaterial->start_vertex = iVertex;
|
pMaterial->start_vertex = iVertex;
|
||||||
pMaterial->vertex_count = 0;
|
pMaterial->vertex_count = 0;
|
||||||
memset(pMaterial->szName, 256, 0);
|
memset(pMaterial->szName, 256, 0);
|
||||||
if(material_itr < material_names_t.end()) {
|
if(material_itr < material_names_t.end()) {
|
||||||
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
|
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
|
||||||
}
|
}
|
||||||
m_materials.push_back(pMaterial);
|
m_materials.push_back(pMaterial);
|
||||||
|
|
||||||
|
|
||||||
pFace = pFaces;
|
pFace = pFaces;
|
||||||
while(*pFace != 0 && iVertex < cVertexData) {
|
while(*pFace != 0 && iVertex < cVertexData) {
|
||||||
pMaterial->start_vertex = iVertex;
|
pMaterial->start_vertex = iVertex;
|
||||||
|
|
||||||
int *pMaterialEndFace = pFace + *pFace;
|
int *pMaterialEndFace = pFace + *pFace;
|
||||||
++pFace;
|
++pFace;
|
||||||
while(pFace < pMaterialEndFace && iVertex < cVertexData) {
|
while(pFace < pMaterialEndFace && iVertex < cVertexData) {
|
||||||
int cFaceVertexes = *pFace;
|
int cFaceVertexes = *pFace;
|
||||||
Vector3 firstFaceVertex;
|
Vector3 firstFaceVertex;
|
||||||
Vector3 prevFaceVertex;
|
Vector3 prevFaceVertex;
|
||||||
Vector3 firstFaceNormal;
|
Vector3 firstFaceNormal;
|
||||||
Vector3 prevFaceNormal;
|
Vector3 prevFaceNormal;
|
||||||
Vector2 firstFaceUva;
|
Vector2 firstFaceUva;
|
||||||
Vector2 prevFaceUva;
|
Vector2 prevFaceUva;
|
||||||
for(int iFaceVertex=0; iFaceVertex < cFaceVertexes; iFaceVertex++) {
|
for(int iFaceVertex=0; iFaceVertex < cFaceVertexes; iFaceVertex++) {
|
||||||
if(iFaceVertex > 2) {
|
if(iFaceVertex > 2) {
|
||||||
// There have already been 3 vertices. Now we need to split the quad into a second triangle composed of the 1st, 3rd, and 4th vertices
|
// There have already been 3 vertices. Now we need to split the quad into a second triangle composed of the 1st, 3rd, and 4th vertices
|
||||||
iVertex+=2;
|
iVertex+=2;
|
||||||
|
|
||||||
mi.vertices.push_back(firstFaceVertex);
|
mi.vertices.push_back(firstFaceVertex);
|
||||||
mi.uva.push_back(firstFaceUva);
|
mi.uva.push_back(firstFaceUva);
|
||||||
mi.normals.push_back(firstFaceNormal);
|
mi.normals.push_back(firstFaceNormal);
|
||||||
|
|
||||||
mi.vertices.push_back(prevFaceVertex);
|
mi.vertices.push_back(prevFaceVertex);
|
||||||
mi.uva.push_back(prevFaceUva);
|
mi.uva.push_back(prevFaceUva);
|
||||||
mi.normals.push_back(prevFaceNormal);
|
mi.normals.push_back(prevFaceNormal);
|
||||||
}
|
}
|
||||||
Vector3 vertex = indexed_vertices[pFace[iFaceVertex*3+1]];
|
Vector3 vertex = indexed_vertices[pFace[iFaceVertex*3+1]];
|
||||||
Vector2 new_uva;
|
Vector2 new_uva;
|
||||||
if(pFace[iFaceVertex*3+2] >= 0) {
|
if(pFace[iFaceVertex*3+2] >= 0) {
|
||||||
new_uva = indexed_uva[pFace[iFaceVertex*3+2]];
|
new_uva = indexed_uva[pFace[iFaceVertex*3+2]];
|
||||||
}
|
}
|
||||||
Vector3 normal;
|
Vector3 normal;
|
||||||
if(pFace[iFaceVertex*3+3] >= 0){
|
if(pFace[iFaceVertex*3+3] >= 0){
|
||||||
Vector3 normal = indexed_normals[pFace[iFaceVertex*3+3]];
|
Vector3 normal = indexed_normals[pFace[iFaceVertex*3+3]];
|
||||||
}
|
}
|
||||||
|
|
||||||
mi.vertices.push_back(vertex);
|
mi.vertices.push_back(vertex);
|
||||||
mi.uva.push_back(new_uva);
|
mi.uva.push_back(new_uva);
|
||||||
mi.normals.push_back(normal);
|
mi.normals.push_back(normal);
|
||||||
|
|
||||||
if(iFaceVertex==0) {
|
if(iFaceVertex==0) {
|
||||||
firstFaceVertex = vertex;
|
firstFaceVertex = vertex;
|
||||||
firstFaceUva = new_uva;
|
firstFaceUva = new_uva;
|
||||||
firstFaceNormal = normal;
|
firstFaceNormal = normal;
|
||||||
}
|
}
|
||||||
prevFaceVertex = vertex;
|
prevFaceVertex = vertex;
|
||||||
prevFaceUva = new_uva;
|
prevFaceUva = new_uva;
|
||||||
prevFaceNormal = normal;
|
prevFaceNormal = normal;
|
||||||
|
|
||||||
iVertex++;
|
iVertex++;
|
||||||
}
|
}
|
||||||
pFace += cFaceVertexes * 3 + 1;
|
pFace += cFaceVertexes * 3 + 1;
|
||||||
}
|
}
|
||||||
pMaterial->vertex_count = iVertex - pMaterial->start_vertex;
|
pMaterial->vertex_count = iVertex - pMaterial->start_vertex;
|
||||||
if(*pFace != 0) {
|
if(*pFace != 0) {
|
||||||
pMaterial = new KRMesh::pack_material();
|
pMaterial = new KRMesh::pack_material();
|
||||||
pMaterial->start_vertex = iVertex;
|
pMaterial->start_vertex = iVertex;
|
||||||
pMaterial->vertex_count = 0;
|
pMaterial->vertex_count = 0;
|
||||||
memset(pMaterial->szName, 256, 0);
|
memset(pMaterial->szName, 256, 0);
|
||||||
|
|
||||||
if(material_itr < material_names_t.end()) {
|
if(material_itr < material_names_t.end()) {
|
||||||
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
|
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
|
||||||
}
|
}
|
||||||
m_materials.push_back(pMaterial);
|
m_materials.push_back(pMaterial);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int iMaterial=0; iMaterial < m_materials.size(); iMaterial++) {
|
for(int iMaterial=0; iMaterial < m_materials.size(); iMaterial++) {
|
||||||
KRMesh::pack_material *pNewMaterial = m_materials[iMaterial];
|
KRMesh::pack_material *pNewMaterial = m_materials[iMaterial];
|
||||||
if(pNewMaterial->vertex_count > 0) {
|
if(pNewMaterial->vertex_count > 0) {
|
||||||
mi.material_names.push_back(std::string(pNewMaterial->szName));
|
mi.material_names.push_back(std::string(pNewMaterial->szName));
|
||||||
mi.submesh_starts.push_back(pNewMaterial->start_vertex);
|
mi.submesh_starts.push_back(pNewMaterial->start_vertex);
|
||||||
mi.submesh_lengths.push_back(pNewMaterial->vertex_count);
|
mi.submesh_lengths.push_back(pNewMaterial->vertex_count);
|
||||||
}
|
}
|
||||||
delete pNewMaterial;
|
delete pNewMaterial;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Bones not yet supported for OBJ
|
// TODO: Bones not yet supported for OBJ
|
||||||
// std::vector<std::string> bone_names;
|
// std::vector<std::string> bone_names;
|
||||||
// std::vector<Matrix4> bone_bind_poses;
|
// std::vector<Matrix4> bone_bind_poses;
|
||||||
// std::vector<std::vector<int> > bone_indexes;
|
// std::vector<std::vector<int> > bone_indexes;
|
||||||
// std::vector<std::vector<float> > bone_weights;
|
// std::vector<std::vector<float> > bone_weights;
|
||||||
//
|
//
|
||||||
// std::vector<__uint16_t> vertex_indexes;
|
// std::vector<__uint16_t> vertex_indexes;
|
||||||
// std::vector<std::pair<int, int> > vertex_index_bases;
|
// std::vector<std::pair<int, int> > vertex_index_bases;
|
||||||
|
|
||||||
mi.format = KRMesh::KRENGINE_MODEL_FORMAT_TRIANGLES;
|
mi.format = KRMesh::KRENGINE_MODEL_FORMAT_TRIANGLES;
|
||||||
new_mesh->LoadData(mi, true, false);
|
new_mesh->LoadData(mi, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pFaces) {
|
if(pFaces) {
|
||||||
free(pFaces);
|
free(pFaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
return resources;
|
return resources;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,166 +1,166 @@
|
|||||||
//
|
//
|
||||||
// KRReverbZone.cpp
|
// KRReverbZone.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 2012-12-06.
|
// Created by Kearwood Gilbert on 2012-12-06.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KRReverbZone.h"
|
#include "KRReverbZone.h"
|
||||||
#include "KRContext.h"
|
#include "KRContext.h"
|
||||||
|
|
||||||
KRReverbZone::KRReverbZone(KRScene &scene, std::string name) : KRNode(scene, name)
|
KRReverbZone::KRReverbZone(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||||
{
|
{
|
||||||
m_reverb = "";
|
m_reverb = "";
|
||||||
m_reverb_gain = 1.0f;
|
m_reverb_gain = 1.0f;
|
||||||
m_gradient_distance = 0.25f;
|
m_gradient_distance = 0.25f;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KRReverbZone::~KRReverbZone()
|
KRReverbZone::~KRReverbZone()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KRReverbZone::getElementName() {
|
std::string KRReverbZone::getElementName() {
|
||||||
return "reverb_zone";
|
return "reverb_zone";
|
||||||
}
|
}
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRReverbZone::saveXML( tinyxml2::XMLNode *parent)
|
tinyxml2::XMLElement *KRReverbZone::saveXML( tinyxml2::XMLNode *parent)
|
||||||
{
|
{
|
||||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||||
e->SetAttribute("zone", m_zone.c_str());
|
e->SetAttribute("zone", m_zone.c_str());
|
||||||
e->SetAttribute("sample", m_reverb.c_str());
|
e->SetAttribute("sample", m_reverb.c_str());
|
||||||
e->SetAttribute("gain", m_reverb_gain);
|
e->SetAttribute("gain", m_reverb_gain);
|
||||||
e->SetAttribute("gradient", m_gradient_distance);
|
e->SetAttribute("gradient", m_gradient_distance);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRReverbZone::loadXML(tinyxml2::XMLElement *e)
|
void KRReverbZone::loadXML(tinyxml2::XMLElement *e)
|
||||||
{
|
{
|
||||||
KRNode::loadXML(e);
|
KRNode::loadXML(e);
|
||||||
|
|
||||||
m_zone = e->Attribute("zone");
|
m_zone = e->Attribute("zone");
|
||||||
|
|
||||||
m_gradient_distance = 0.25f;
|
m_gradient_distance = 0.25f;
|
||||||
if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
|
||||||
m_gradient_distance = 0.25f;
|
m_gradient_distance = 0.25f;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_reverb = e->Attribute("sample");
|
m_reverb = e->Attribute("sample");
|
||||||
|
|
||||||
m_reverb_gain = 1.0f;
|
m_reverb_gain = 1.0f;
|
||||||
if(e->QueryFloatAttribute("gain", &m_reverb_gain) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("gain", &m_reverb_gain) != tinyxml2::XML_SUCCESS) {
|
||||||
m_reverb_gain = 1.0f;
|
m_reverb_gain = 1.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KRReverbZone::getReverb()
|
std::string KRReverbZone::getReverb()
|
||||||
{
|
{
|
||||||
return m_reverb;
|
return m_reverb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRReverbZone::setReverb(const std::string &reverb)
|
void KRReverbZone::setReverb(const std::string &reverb)
|
||||||
{
|
{
|
||||||
m_reverb = reverb;
|
m_reverb = reverb;
|
||||||
}
|
}
|
||||||
|
|
||||||
float KRReverbZone::getReverbGain()
|
float KRReverbZone::getReverbGain()
|
||||||
{
|
{
|
||||||
return m_reverb_gain;
|
return m_reverb_gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRReverbZone::setReverbGain(float reverb_gain)
|
void KRReverbZone::setReverbGain(float reverb_gain)
|
||||||
{
|
{
|
||||||
m_reverb_gain = reverb_gain;
|
m_reverb_gain = reverb_gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KRReverbZone::getZone()
|
std::string KRReverbZone::getZone()
|
||||||
{
|
{
|
||||||
return m_zone;
|
return m_zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRReverbZone::setZone(const std::string &zone)
|
void KRReverbZone::setZone(const std::string &zone)
|
||||||
{
|
{
|
||||||
m_zone = zone;
|
m_zone = zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRReverbZone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
|
void KRReverbZone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
|
||||||
{
|
{
|
||||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||||
|
|
||||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||||
|
|
||||||
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_REVERB_ZONES;
|
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_REVERB_ZONES;
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
||||||
Matrix4 sphereModelMatrix = getModelMatrix();
|
Matrix4 sphereModelMatrix = getModelMatrix();
|
||||||
|
|
||||||
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
||||||
|
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||||
|
|
||||||
// Enable additive blending
|
// Enable additive blending
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
GLDEBUG(glEnable(GL_BLEND));
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||||
|
|
||||||
|
|
||||||
// Disable z-buffer write
|
// Disable z-buffer write
|
||||||
GLDEBUG(glDepthMask(GL_FALSE));
|
GLDEBUG(glDepthMask(GL_FALSE));
|
||||||
|
|
||||||
// Enable z-buffer test
|
// Enable z-buffer test
|
||||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
||||||
if(sphereModels.size()) {
|
if(sphereModels.size()) {
|
||||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable alpha blending
|
// Enable alpha blending
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
GLDEBUG(glEnable(GL_BLEND));
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float KRReverbZone::getGradientDistance()
|
float KRReverbZone::getGradientDistance()
|
||||||
{
|
{
|
||||||
return m_gradient_distance;
|
return m_gradient_distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRReverbZone::setGradientDistance(float gradient_distance)
|
void KRReverbZone::setGradientDistance(float gradient_distance)
|
||||||
{
|
{
|
||||||
m_gradient_distance = gradient_distance;
|
m_gradient_distance = gradient_distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
AABB KRReverbZone::getBounds() {
|
AABB KRReverbZone::getBounds() {
|
||||||
// Reverb zones always have a -1, -1, -1 to 1, 1, 1 bounding box
|
// Reverb zones always have a -1, -1, -1 to 1, 1, 1 bounding box
|
||||||
return AABB(-Vector3::One(), Vector3::One(), getModelMatrix());
|
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
|
||||||
}
|
}
|
||||||
|
|
||||||
float KRReverbZone::getContainment(const Vector3 &pos)
|
float KRReverbZone::getContainment(const Vector3 &pos)
|
||||||
{
|
{
|
||||||
AABB bounds = getBounds();
|
AABB bounds = getBounds();
|
||||||
if(bounds.contains(pos)) {
|
if(bounds.contains(pos)) {
|
||||||
Vector3 size = bounds.size();
|
Vector3 size = bounds.size();
|
||||||
Vector3 diff = pos - bounds.center();
|
Vector3 diff = pos - bounds.center();
|
||||||
diff = diff * 2.0f;
|
diff = diff * 2.0f;
|
||||||
diff = Vector3(diff.x / size.x, diff.y / size.y, diff.z / size.z);
|
diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z);
|
||||||
float d = diff.magnitude();
|
float d = diff.magnitude();
|
||||||
|
|
||||||
if(m_gradient_distance <= 0.0f) {
|
if(m_gradient_distance <= 0.0f) {
|
||||||
// Avoid division by zero
|
// Avoid division by zero
|
||||||
d = d > 1.0f ? 0.0f : 1.0f;
|
d = d > 1.0f ? 0.0f : 1.0f;
|
||||||
} else {
|
} else {
|
||||||
d = (1.0f - d) / m_gradient_distance;
|
d = (1.0f - d) / m_gradient_distance;
|
||||||
d = KRCLAMP(d, 0.0f, 1.0f);
|
d = KRCLAMP(d, 0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
return d;
|
return d;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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
|
// KRSpotLight.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 12-04-05.
|
// Created by Kearwood Gilbert on 12-04-05.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
#include "KRSpotLight.h"
|
#include "KRSpotLight.h"
|
||||||
|
|
||||||
KRSpotLight::KRSpotLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
KRSpotLight::KRSpotLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
KRSpotLight::~KRSpotLight()
|
KRSpotLight::~KRSpotLight()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KRSpotLight::getElementName() {
|
std::string KRSpotLight::getElementName() {
|
||||||
return "spot_light";
|
return "spot_light";
|
||||||
}
|
}
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRSpotLight::saveXML( tinyxml2::XMLNode *parent)
|
tinyxml2::XMLElement *KRSpotLight::saveXML( tinyxml2::XMLNode *parent)
|
||||||
{
|
{
|
||||||
tinyxml2::XMLElement *e = KRLight::saveXML(parent);
|
tinyxml2::XMLElement *e = KRLight::saveXML(parent);
|
||||||
e->SetAttribute("inner_angle", m_innerAngle);
|
e->SetAttribute("inner_angle", m_innerAngle);
|
||||||
e->SetAttribute("outer_angle", m_outerAngle);
|
e->SetAttribute("outer_angle", m_outerAngle);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRSpotLight::loadXML(tinyxml2::XMLElement *e) {
|
void KRSpotLight::loadXML(tinyxml2::XMLElement *e) {
|
||||||
KRLight::loadXML(e);
|
KRLight::loadXML(e);
|
||||||
|
|
||||||
e->QueryFloatAttribute("inner_angle", &m_innerAngle);
|
e->QueryFloatAttribute("inner_angle", &m_innerAngle);
|
||||||
e->QueryFloatAttribute("outer_angle", &m_outerAngle);
|
e->QueryFloatAttribute("outer_angle", &m_outerAngle);
|
||||||
}
|
}
|
||||||
|
|
||||||
float KRSpotLight::getInnerAngle() {
|
float KRSpotLight::getInnerAngle() {
|
||||||
return m_innerAngle;
|
return m_innerAngle;
|
||||||
}
|
}
|
||||||
float KRSpotLight::getOuterAngle() {
|
float KRSpotLight::getOuterAngle() {
|
||||||
return m_outerAngle;
|
return m_outerAngle;
|
||||||
}
|
}
|
||||||
void KRSpotLight::setInnerAngle(float innerAngle) {
|
void KRSpotLight::setInnerAngle(float innerAngle) {
|
||||||
m_innerAngle = innerAngle;
|
m_innerAngle = innerAngle;
|
||||||
}
|
}
|
||||||
void KRSpotLight::setOuterAngle(float outerAngle) {
|
void KRSpotLight::setOuterAngle(float outerAngle) {
|
||||||
m_outerAngle = outerAngle;
|
m_outerAngle = outerAngle;
|
||||||
}
|
}
|
||||||
|
|
||||||
AABB KRSpotLight::getBounds() {
|
AABB KRSpotLight::getBounds() {
|
||||||
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
||||||
if(influence_radius < m_flareOcclusionSize) {
|
if(influence_radius < m_flareOcclusionSize) {
|
||||||
influence_radius = m_flareOcclusionSize;
|
influence_radius = m_flareOcclusionSize;
|
||||||
}
|
}
|
||||||
return AABB(Vector3(-influence_radius), Vector3(influence_radius), getModelMatrix());
|
return AABB::Create(Vector3::Create(-influence_radius), Vector3::Create(influence_radius), getModelMatrix());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,141 +1,141 @@
|
|||||||
//
|
//
|
||||||
// KRSprite.cpp
|
// KRSprite.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 12-04-05.
|
// Created by Kearwood Gilbert on 12-04-05.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
#include "KRSprite.h"
|
#include "KRSprite.h"
|
||||||
|
|
||||||
#include "KRNode.h"
|
#include "KRNode.h"
|
||||||
#include "KRCamera.h"
|
#include "KRCamera.h"
|
||||||
#include "KRContext.h"
|
#include "KRContext.h"
|
||||||
|
|
||||||
#include "KRShaderManager.h"
|
#include "KRShaderManager.h"
|
||||||
#include "KRShader.h"
|
#include "KRShader.h"
|
||||||
#include "KRStockGeometry.h"
|
#include "KRStockGeometry.h"
|
||||||
#include "KRDirectionalLight.h"
|
#include "KRDirectionalLight.h"
|
||||||
#include "KRSpotLight.h"
|
#include "KRSpotLight.h"
|
||||||
#include "KRPointLight.h"
|
#include "KRPointLight.h"
|
||||||
|
|
||||||
|
|
||||||
KRSprite::KRSprite(KRScene &scene, std::string name) : KRNode(scene, name)
|
KRSprite::KRSprite(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||||
{
|
{
|
||||||
m_spriteTexture = "";
|
m_spriteTexture = "";
|
||||||
m_pSpriteTexture = NULL;
|
m_pSpriteTexture = NULL;
|
||||||
m_spriteAlpha = 1.0f;
|
m_spriteAlpha = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRSprite::~KRSprite()
|
KRSprite::~KRSprite()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KRSprite::getElementName() {
|
std::string KRSprite::getElementName() {
|
||||||
return "sprite";
|
return "sprite";
|
||||||
}
|
}
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRSprite::saveXML( tinyxml2::XMLNode *parent)
|
tinyxml2::XMLElement *KRSprite::saveXML( tinyxml2::XMLNode *parent)
|
||||||
{
|
{
|
||||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||||
e->SetAttribute("sprite_texture", m_spriteTexture.c_str());
|
e->SetAttribute("sprite_texture", m_spriteTexture.c_str());
|
||||||
e->SetAttribute("sprite_alpha", m_spriteAlpha);
|
e->SetAttribute("sprite_alpha", m_spriteAlpha);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRSprite::loadXML(tinyxml2::XMLElement *e) {
|
void KRSprite::loadXML(tinyxml2::XMLElement *e) {
|
||||||
KRNode::loadXML(e);
|
KRNode::loadXML(e);
|
||||||
|
|
||||||
if(e->QueryFloatAttribute("sprite_alpha", &m_spriteAlpha) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("sprite_alpha", &m_spriteAlpha) != tinyxml2::XML_SUCCESS) {
|
||||||
m_spriteAlpha = 1.0f;
|
m_spriteAlpha = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *szSpriteTexture = e->Attribute("sprite_texture");
|
const char *szSpriteTexture = e->Attribute("sprite_texture");
|
||||||
if(szSpriteTexture) {
|
if(szSpriteTexture) {
|
||||||
m_spriteTexture = szSpriteTexture;
|
m_spriteTexture = szSpriteTexture;
|
||||||
} else {
|
} else {
|
||||||
m_spriteTexture = "";
|
m_spriteTexture = "";
|
||||||
}
|
}
|
||||||
m_pSpriteTexture = NULL;
|
m_pSpriteTexture = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRSprite::setSpriteTexture(std::string sprite_texture) {
|
void KRSprite::setSpriteTexture(std::string sprite_texture) {
|
||||||
m_spriteTexture = sprite_texture;
|
m_spriteTexture = sprite_texture;
|
||||||
m_pSpriteTexture = NULL;
|
m_pSpriteTexture = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRSprite::setSpriteAlpha(float alpha)
|
void KRSprite::setSpriteAlpha(float alpha)
|
||||||
{
|
{
|
||||||
m_spriteAlpha = alpha;
|
m_spriteAlpha = alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
float KRSprite::getSpriteAlpha() const
|
float KRSprite::getSpriteAlpha() const
|
||||||
{
|
{
|
||||||
return m_spriteAlpha;
|
return m_spriteAlpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
AABB KRSprite::getBounds() {
|
AABB KRSprite::getBounds() {
|
||||||
return AABB(-Vector3::One() * 0.5f, Vector3::One() * 0.5f, getModelMatrix());
|
return AABB::Create(-Vector3::One() * 0.5f, Vector3::One() * 0.5f, getModelMatrix());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void KRSprite::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
|
void KRSprite::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
|
||||||
|
|
||||||
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) {
|
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) {
|
||||||
// Pre-stream sprites, even if the alpha is zero
|
// Pre-stream sprites, even if the alpha is zero
|
||||||
if(m_spriteTexture.size() && m_pSpriteTexture == NULL) {
|
if(m_spriteTexture.size() && m_pSpriteTexture == NULL) {
|
||||||
if(!m_pSpriteTexture && m_spriteTexture.size()) {
|
if(!m_pSpriteTexture && m_spriteTexture.size()) {
|
||||||
m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture);
|
m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pSpriteTexture) {
|
if(m_pSpriteTexture) {
|
||||||
m_pSpriteTexture->resetPoolExpiry(0.0f, KRTexture::TEXTURE_USAGE_SPRITE);
|
m_pSpriteTexture->resetPoolExpiry(0.0f, KRTexture::TEXTURE_USAGE_SPRITE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||||
|
|
||||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||||
|
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
|
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
|
||||||
if(m_spriteTexture.size() && m_spriteAlpha > 0.0f) {
|
if(m_spriteTexture.size() && m_spriteAlpha > 0.0f) {
|
||||||
|
|
||||||
|
|
||||||
if(!m_pSpriteTexture && m_spriteTexture.size()) {
|
if(!m_pSpriteTexture && m_spriteTexture.size()) {
|
||||||
m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture);
|
m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pSpriteTexture) {
|
if(m_pSpriteTexture) {
|
||||||
/*
|
/*
|
||||||
// Enable additive blending
|
// Enable additive blending
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
GLDEBUG(glEnable(GL_BLEND));
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||||
|
|
||||||
// Disable z-buffer write
|
// Disable z-buffer write
|
||||||
GLDEBUG(glDepthMask(GL_FALSE));
|
GLDEBUG(glDepthMask(GL_FALSE));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO - Sprites are currently additive only. Need to expose this and allow for multiple blending modes
|
// TODO - Sprites are currently additive only. Need to expose this and allow for multiple blending modes
|
||||||
|
|
||||||
// Enable z-buffer test
|
// Enable z-buffer test
|
||||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||||
|
|
||||||
// Render light sprite on transparency pass
|
// Render light sprite on transparency pass
|
||||||
KRShader *pShader = getContext().getShaderManager()->getShader("sprite", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
KRShader *pShader = getContext().getShaderManager()->getShader("sprite", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_spriteAlpha);
|
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_spriteAlpha);
|
||||||
m_pContext->getTextureManager()->selectTexture(0, m_pSpriteTexture, 0.0f, KRTexture::TEXTURE_USAGE_SPRITE);
|
m_pContext->getTextureManager()->selectTexture(0, m_pSpriteTexture, 0.0f, KRTexture::TEXTURE_USAGE_SPRITE);
|
||||||
m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
||||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,385 +1,385 @@
|
|||||||
//
|
//
|
||||||
// KRTextureTGA.cpp
|
// KRTextureTGA.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 2012-10-23.
|
// Created by Kearwood Gilbert on 2012-10-23.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KRTextureTGA.h"
|
#include "KRTextureTGA.h"
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
#include "KRContext.h"
|
#include "KRContext.h"
|
||||||
#include "KRTextureKTX.h"
|
#include "KRTextureKTX.h"
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char idlength;
|
char idlength;
|
||||||
char colourmaptype;
|
char colourmaptype;
|
||||||
char imagetype;
|
char imagetype;
|
||||||
short int colourmaporigin;
|
short int colourmaporigin;
|
||||||
short int colourmaplength;
|
short int colourmaplength;
|
||||||
char colourmapdepth;
|
char colourmapdepth;
|
||||||
short int x_origin;
|
short int x_origin;
|
||||||
short int y_origin;
|
short int y_origin;
|
||||||
short width;
|
short width;
|
||||||
short height;
|
short height;
|
||||||
char bitsperpixel;
|
char bitsperpixel;
|
||||||
char imagedescriptor;
|
char imagedescriptor;
|
||||||
} TGA_HEADER;
|
} TGA_HEADER;
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
#else
|
#else
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char idlength;
|
char idlength;
|
||||||
char colourmaptype;
|
char colourmaptype;
|
||||||
char imagetype;
|
char imagetype;
|
||||||
short int colourmaporigin;
|
short int colourmaporigin;
|
||||||
short int colourmaplength;
|
short int colourmaplength;
|
||||||
char colourmapdepth;
|
char colourmapdepth;
|
||||||
short int x_origin;
|
short int x_origin;
|
||||||
short int y_origin;
|
short int y_origin;
|
||||||
short width;
|
short width;
|
||||||
short height;
|
short height;
|
||||||
char bitsperpixel;
|
char bitsperpixel;
|
||||||
char imagedescriptor;
|
char imagedescriptor;
|
||||||
} __attribute__((packed)) TGA_HEADER;
|
} __attribute__((packed)) TGA_HEADER;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
KRTextureTGA::KRTextureTGA(KRContext &context, KRDataBlock *data, std::string name) : KRTexture2D(context, data, name)
|
KRTextureTGA::KRTextureTGA(KRContext &context, KRDataBlock *data, std::string name) : KRTexture2D(context, data, name)
|
||||||
{
|
{
|
||||||
data->lock();
|
data->lock();
|
||||||
TGA_HEADER *pHeader = (TGA_HEADER *)data->getStart();
|
TGA_HEADER *pHeader = (TGA_HEADER *)data->getStart();
|
||||||
|
|
||||||
m_max_lod_max_dim = pHeader->width > pHeader->height ? pHeader->width : pHeader->height;
|
m_max_lod_max_dim = pHeader->width > pHeader->height ? pHeader->width : pHeader->height;
|
||||||
m_min_lod_max_dim = m_max_lod_max_dim; // Mipmaps not yet supported for TGA images
|
m_min_lod_max_dim = m_max_lod_max_dim; // Mipmaps not yet supported for TGA images
|
||||||
switch(pHeader->imagetype) {
|
switch(pHeader->imagetype) {
|
||||||
case 2: // rgb
|
case 2: // rgb
|
||||||
case 10: // rgb + rle
|
case 10: // rgb + rle
|
||||||
switch(pHeader->bitsperpixel) {
|
switch(pHeader->bitsperpixel) {
|
||||||
case 24:
|
case 24:
|
||||||
{
|
{
|
||||||
m_imageSize = pHeader->width * pHeader->height * 4;
|
m_imageSize = pHeader->width * pHeader->height * 4;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
{
|
{
|
||||||
m_imageSize = pHeader->width * pHeader->height * 4;
|
m_imageSize = pHeader->width * pHeader->height * 4;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
assert(false);
|
assert(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data->unlock();
|
data->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
KRTextureTGA::~KRTextureTGA()
|
KRTextureTGA::~KRTextureTGA()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, bool compress, bool premultiply_alpha)
|
bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, bool compress, bool premultiply_alpha)
|
||||||
{
|
{
|
||||||
m_pData->lock();
|
m_pData->lock();
|
||||||
TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart();
|
TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart();
|
||||||
unsigned char *pData = (unsigned char *)pHeader + (long)pHeader->idlength + (long)pHeader->colourmaplength * (long)pHeader->colourmaptype + sizeof(TGA_HEADER);
|
unsigned char *pData = (unsigned char *)pHeader + (long)pHeader->idlength + (long)pHeader->colourmaplength * (long)pHeader->colourmaptype + sizeof(TGA_HEADER);
|
||||||
|
|
||||||
GLenum internal_format = GL_RGBA;
|
GLenum internal_format = GL_RGBA;
|
||||||
|
|
||||||
#if !TARGET_OS_IPHONE
|
#if !TARGET_OS_IPHONE
|
||||||
if(compress) {
|
if(compress) {
|
||||||
internal_format = pHeader->bitsperpixel == 24 ? GL_COMPRESSED_RGB_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
internal_format = pHeader->bitsperpixel == 24 ? GL_COMPRESSED_RGB_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(pHeader->colourmaptype != 0) {
|
if(pHeader->colourmaptype != 0) {
|
||||||
m_pData->unlock();
|
m_pData->unlock();
|
||||||
return false; // Mapped colors not supported
|
return false; // Mapped colors not supported
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(pHeader->imagetype) {
|
switch(pHeader->imagetype) {
|
||||||
case 2: // rgb
|
case 2: // rgb
|
||||||
switch(pHeader->bitsperpixel) {
|
switch(pHeader->bitsperpixel) {
|
||||||
case 24:
|
case 24:
|
||||||
{
|
{
|
||||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||||
//#ifdef __APPLE__
|
//#ifdef __APPLE__
|
||||||
// vImage_Buffer source_image = { pData, pHeader->height, pHeader->width, pHeader->width*3 };
|
// vImage_Buffer source_image = { pData, pHeader->height, pHeader->width, pHeader->width*3 };
|
||||||
// vImage_Buffer dest_image = { converted_image, pHeader->height, pHeader->width, pHeader->width*4 };
|
// vImage_Buffer dest_image = { converted_image, pHeader->height, pHeader->width, pHeader->width*4 };
|
||||||
// vImageConvert_RGB888toRGBA8888(&source_image, NULL, 0xff, &dest_image, false, kvImageDoNotTile);
|
// vImageConvert_RGB888toRGBA8888(&source_image, NULL, 0xff, &dest_image, false, kvImageDoNotTile);
|
||||||
//#else
|
//#else
|
||||||
unsigned char *pSource = pData;
|
unsigned char *pSource = pData;
|
||||||
unsigned char *pDest = converted_image;
|
unsigned char *pDest = converted_image;
|
||||||
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
|
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
|
||||||
while(pSource < pEnd) {
|
while(pSource < pEnd) {
|
||||||
*pDest++ = pSource[0];
|
*pDest++ = pSource[0];
|
||||||
*pDest++ = pSource[1];
|
*pDest++ = pSource[1];
|
||||||
*pDest++ = pSource[2];
|
*pDest++ = pSource[2];
|
||||||
*pDest++ = 0xff;
|
*pDest++ = 0xff;
|
||||||
pSource += 3;
|
pSource += 3;
|
||||||
}
|
}
|
||||||
assert(pSource <= m_pData->getEnd());
|
assert(pSource <= m_pData->getEnd());
|
||||||
//#endif
|
//#endif
|
||||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
||||||
GLDEBUG(glFinish());
|
GLDEBUG(glFinish());
|
||||||
free(converted_image);
|
free(converted_image);
|
||||||
|
|
||||||
current_lod_max_dim = m_max_lod_max_dim;
|
current_lod_max_dim = m_max_lod_max_dim;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
{
|
{
|
||||||
if(premultiply_alpha) {
|
if(premultiply_alpha) {
|
||||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||||
|
|
||||||
unsigned char *pSource = pData;
|
unsigned char *pSource = pData;
|
||||||
unsigned char *pDest = converted_image;
|
unsigned char *pDest = converted_image;
|
||||||
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
|
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
|
||||||
while(pSource < pEnd) {
|
while(pSource < pEnd) {
|
||||||
*pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff;
|
*pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff;
|
||||||
*pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff;
|
*pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff;
|
||||||
*pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff;
|
*pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff;
|
||||||
*pDest++ = pSource[3];
|
*pDest++ = pSource[3];
|
||||||
pSource += 4;
|
pSource += 4;
|
||||||
}
|
}
|
||||||
assert(pSource <= m_pData->getEnd());
|
assert(pSource <= m_pData->getEnd());
|
||||||
|
|
||||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
||||||
GLDEBUG(glFinish());
|
GLDEBUG(glFinish());
|
||||||
free(converted_image);
|
free(converted_image);
|
||||||
} else {
|
} else {
|
||||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)pData));
|
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)pData));
|
||||||
GLDEBUG(glFinish());
|
GLDEBUG(glFinish());
|
||||||
}
|
}
|
||||||
|
|
||||||
current_lod_max_dim = m_max_lod_max_dim;
|
current_lod_max_dim = m_max_lod_max_dim;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
m_pData->unlock();
|
m_pData->unlock();
|
||||||
return false; // 16-bit images not yet supported
|
return false; // 16-bit images not yet supported
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 10: // rgb + rle
|
case 10: // rgb + rle
|
||||||
switch(pHeader->bitsperpixel) {
|
switch(pHeader->bitsperpixel) {
|
||||||
case 32:
|
case 32:
|
||||||
{
|
{
|
||||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||||
unsigned char *pSource = pData;
|
unsigned char *pSource = pData;
|
||||||
unsigned char *pDest = converted_image;
|
unsigned char *pDest = converted_image;
|
||||||
unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4;
|
unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4;
|
||||||
if(premultiply_alpha) {
|
if(premultiply_alpha) {
|
||||||
while(pDest < pEnd) {
|
while(pDest < pEnd) {
|
||||||
int count = (*pSource & 0x7f) + 1;
|
int count = (*pSource & 0x7f) + 1;
|
||||||
if(*pSource & 0x80) {
|
if(*pSource & 0x80) {
|
||||||
// RLE Packet
|
// RLE Packet
|
||||||
pSource++;
|
pSource++;
|
||||||
while(count--) {
|
while(count--) {
|
||||||
*pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff;
|
*pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff;
|
||||||
*pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff;
|
*pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff;
|
||||||
*pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff;
|
*pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff;
|
||||||
*pDest++ = pSource[3];
|
*pDest++ = pSource[3];
|
||||||
}
|
}
|
||||||
pSource += 4;
|
pSource += 4;
|
||||||
} else {
|
} else {
|
||||||
// RAW Packet
|
// RAW Packet
|
||||||
pSource++;
|
pSource++;
|
||||||
while(count--) {
|
while(count--) {
|
||||||
*pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff;
|
*pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff;
|
||||||
*pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff;
|
*pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff;
|
||||||
*pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff;
|
*pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff;
|
||||||
*pDest++ = pSource[3];
|
*pDest++ = pSource[3];
|
||||||
pSource += 4;
|
pSource += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(pSource <= m_pData->getEnd());
|
assert(pSource <= m_pData->getEnd());
|
||||||
assert(pDest == pEnd);
|
assert(pDest == pEnd);
|
||||||
} else {
|
} else {
|
||||||
while(pDest < pEnd) {
|
while(pDest < pEnd) {
|
||||||
int count = (*pSource & 0x7f) + 1;
|
int count = (*pSource & 0x7f) + 1;
|
||||||
if(*pSource & 0x80) {
|
if(*pSource & 0x80) {
|
||||||
// RLE Packet
|
// RLE Packet
|
||||||
pSource++;
|
pSource++;
|
||||||
while(count--) {
|
while(count--) {
|
||||||
*pDest++ = pSource[0];
|
*pDest++ = pSource[0];
|
||||||
*pDest++ = pSource[1];
|
*pDest++ = pSource[1];
|
||||||
*pDest++ = pSource[2];
|
*pDest++ = pSource[2];
|
||||||
*pDest++ = pSource[3];
|
*pDest++ = pSource[3];
|
||||||
}
|
}
|
||||||
pSource += 4;
|
pSource += 4;
|
||||||
} else {
|
} else {
|
||||||
// RAW Packet
|
// RAW Packet
|
||||||
pSource++;
|
pSource++;
|
||||||
while(count--) {
|
while(count--) {
|
||||||
*pDest++ = pSource[0];
|
*pDest++ = pSource[0];
|
||||||
*pDest++ = pSource[1];
|
*pDest++ = pSource[1];
|
||||||
*pDest++ = pSource[2];
|
*pDest++ = pSource[2];
|
||||||
*pDest++ = pSource[3];
|
*pDest++ = pSource[3];
|
||||||
pSource += 4;
|
pSource += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(pSource <= m_pData->getEnd());
|
assert(pSource <= m_pData->getEnd());
|
||||||
assert(pDest == pEnd);
|
assert(pDest == pEnd);
|
||||||
}
|
}
|
||||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
||||||
GLDEBUG(glFinish());
|
GLDEBUG(glFinish());
|
||||||
free(converted_image);
|
free(converted_image);
|
||||||
current_lod_max_dim = m_max_lod_max_dim;
|
current_lod_max_dim = m_max_lod_max_dim;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 24:
|
case 24:
|
||||||
{
|
{
|
||||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||||
unsigned char *pSource = pData;
|
unsigned char *pSource = pData;
|
||||||
unsigned char *pDest = converted_image;
|
unsigned char *pDest = converted_image;
|
||||||
unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4;
|
unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4;
|
||||||
while(pDest < pEnd) {
|
while(pDest < pEnd) {
|
||||||
int count = (*pSource & 0x7f) + 1;
|
int count = (*pSource & 0x7f) + 1;
|
||||||
if(*pSource & 0x80) {
|
if(*pSource & 0x80) {
|
||||||
// RLE Packet
|
// RLE Packet
|
||||||
pSource++;
|
pSource++;
|
||||||
while(count--) {
|
while(count--) {
|
||||||
*pDest++ = pSource[0];
|
*pDest++ = pSource[0];
|
||||||
*pDest++ = pSource[1];
|
*pDest++ = pSource[1];
|
||||||
*pDest++ = pSource[2];
|
*pDest++ = pSource[2];
|
||||||
*pDest++ = 0xff;
|
*pDest++ = 0xff;
|
||||||
}
|
}
|
||||||
pSource += 3;
|
pSource += 3;
|
||||||
} else {
|
} else {
|
||||||
// RAW Packet
|
// RAW Packet
|
||||||
pSource++;
|
pSource++;
|
||||||
while(count--) {
|
while(count--) {
|
||||||
*pDest++ = pSource[0];
|
*pDest++ = pSource[0];
|
||||||
*pDest++ = pSource[1];
|
*pDest++ = pSource[1];
|
||||||
*pDest++ = pSource[2];
|
*pDest++ = pSource[2];
|
||||||
*pDest++ = 0xff;
|
*pDest++ = 0xff;
|
||||||
pSource += 3;
|
pSource += 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(pSource <= m_pData->getEnd());
|
assert(pSource <= m_pData->getEnd());
|
||||||
assert(pDest == pEnd);
|
assert(pDest == pEnd);
|
||||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
||||||
GLDEBUG(glFinish());
|
GLDEBUG(glFinish());
|
||||||
free(converted_image);
|
free(converted_image);
|
||||||
current_lod_max_dim = m_max_lod_max_dim;
|
current_lod_max_dim = m_max_lod_max_dim;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
m_pData->unlock();
|
m_pData->unlock();
|
||||||
return false; // 16-bit images not yet supported
|
return false; // 16-bit images not yet supported
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
m_pData->unlock();
|
m_pData->unlock();
|
||||||
return false; // Image type not yet supported
|
return false; // Image type not yet supported
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pData->unlock();
|
m_pData->unlock();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !TARGET_OS_IPHONE
|
#if !TARGET_OS_IPHONE
|
||||||
|
|
||||||
KRTexture *KRTextureTGA::compress(bool premultiply_alpha)
|
KRTexture *KRTextureTGA::compress(bool premultiply_alpha)
|
||||||
{
|
{
|
||||||
m_pData->lock();
|
m_pData->lock();
|
||||||
|
|
||||||
std::list<KRDataBlock *> blocks;
|
std::list<KRDataBlock *> blocks;
|
||||||
|
|
||||||
getContext().getTextureManager()->_setActiveTexture(0);
|
getContext().getTextureManager()->_setActiveTexture(0);
|
||||||
|
|
||||||
GLuint compressed_handle = 0;
|
GLuint compressed_handle = 0;
|
||||||
GLDEBUG(glGenTextures(1, &compressed_handle));
|
GLDEBUG(glGenTextures(1, &compressed_handle));
|
||||||
|
|
||||||
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compressed_handle));
|
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compressed_handle));
|
||||||
|
|
||||||
int current_max_dim = 0;
|
int current_max_dim = 0;
|
||||||
if(!uploadTexture(GL_TEXTURE_2D, m_max_lod_max_dim, current_max_dim, true, premultiply_alpha)) {
|
if(!uploadTexture(GL_TEXTURE_2D, m_max_lod_max_dim, current_max_dim, true, premultiply_alpha)) {
|
||||||
assert(false); // Failed to upload the texture
|
assert(false); // Failed to upload the texture
|
||||||
}
|
}
|
||||||
GLDEBUG(glGenerateMipmap(GL_TEXTURE_2D));
|
GLDEBUG(glGenerateMipmap(GL_TEXTURE_2D));
|
||||||
|
|
||||||
GLint width = 0, height = 0, internal_format, base_internal_format;
|
GLint width = 0, height = 0, internal_format, base_internal_format;
|
||||||
|
|
||||||
|
|
||||||
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width));
|
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width));
|
||||||
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height));
|
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height));
|
||||||
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format));
|
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
int texture_base_level = 0;
|
int texture_base_level = 0;
|
||||||
int texture_max_level = 0;
|
int texture_max_level = 0;
|
||||||
GLDEBUG(glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, &texture_base_level));
|
GLDEBUG(glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, &texture_base_level));
|
||||||
GLDEBUG(glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, &texture_max_level));
|
GLDEBUG(glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, &texture_max_level));
|
||||||
*/
|
*/
|
||||||
switch(internal_format)
|
switch(internal_format)
|
||||||
{
|
{
|
||||||
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||||
base_internal_format = GL_BGRA;
|
base_internal_format = GL_BGRA;
|
||||||
break;
|
break;
|
||||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||||
base_internal_format = GL_BGRA;
|
base_internal_format = GL_BGRA;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false); // Not yet supported
|
assert(false); // Not yet supported
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint lod_level = 0;
|
GLuint lod_level = 0;
|
||||||
GLint compressed_size = 0;
|
GLint compressed_size = 0;
|
||||||
int lod_width = width;
|
int lod_width = width;
|
||||||
while(lod_width > 1) {
|
while(lod_width > 1) {
|
||||||
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, lod_level, GL_TEXTURE_WIDTH, &lod_width));
|
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, lod_level, GL_TEXTURE_WIDTH, &lod_width));
|
||||||
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, lod_level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compressed_size));
|
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, lod_level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compressed_size));
|
||||||
KRDataBlock *new_block = new KRDataBlock();
|
KRDataBlock *new_block = new KRDataBlock();
|
||||||
new_block->expand(compressed_size);
|
new_block->expand(compressed_size);
|
||||||
new_block->lock();
|
new_block->lock();
|
||||||
GLDEBUG(glGetCompressedTexImage(GL_TEXTURE_2D, lod_level, new_block->getStart()));
|
GLDEBUG(glGetCompressedTexImage(GL_TEXTURE_2D, lod_level, new_block->getStart()));
|
||||||
new_block->unlock();
|
new_block->unlock();
|
||||||
blocks.push_back(new_block);
|
blocks.push_back(new_block);
|
||||||
|
|
||||||
lod_level++;
|
lod_level++;
|
||||||
}
|
}
|
||||||
assert(lod_width == 1);
|
assert(lod_width == 1);
|
||||||
|
|
||||||
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
|
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
|
||||||
getContext().getTextureManager()->selectTexture(0, NULL, 0.0f, KRTexture::TEXTURE_USAGE_NONE);
|
getContext().getTextureManager()->selectTexture(0, NULL, 0.0f, KRTexture::TEXTURE_USAGE_NONE);
|
||||||
GLDEBUG(glDeleteTextures(1, &compressed_handle));
|
GLDEBUG(glDeleteTextures(1, &compressed_handle));
|
||||||
|
|
||||||
KRTextureKTX *new_texture = new KRTextureKTX(getContext(), getName(), internal_format, base_internal_format, width, height, blocks);
|
KRTextureKTX *new_texture = new KRTextureKTX(getContext(), getName(), internal_format, base_internal_format, width, height, blocks);
|
||||||
|
|
||||||
m_pData->unlock();
|
m_pData->unlock();
|
||||||
|
|
||||||
for(auto block_itr = blocks.begin(); block_itr != blocks.end(); block_itr++) {
|
for(auto block_itr = blocks.begin(); block_itr != blocks.end(); block_itr++) {
|
||||||
KRDataBlock *block = *block_itr;
|
KRDataBlock *block = *block_itr;
|
||||||
delete block;
|
delete block;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new_texture;
|
return new_texture;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
long KRTextureTGA::getMemRequiredForSize(int max_dim)
|
long KRTextureTGA::getMemRequiredForSize(int max_dim)
|
||||||
{
|
{
|
||||||
return m_imageSize;
|
return m_imageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KRTextureTGA::getExtension()
|
std::string KRTextureTGA::getExtension()
|
||||||
{
|
{
|
||||||
return "tga";
|
return "tga";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,264 +1,264 @@
|
|||||||
//
|
//
|
||||||
// KRViewport.cpp
|
// KRViewport.cpp
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 2012-10-25.
|
// Created by Kearwood Gilbert on 2012-10-25.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#define KRENGINE_SWAP_INT(x,y) {int t;t=x;x=y;y=t;}
|
#define KRENGINE_SWAP_INT(x,y) {int t;t=x;x=y;y=t;}
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
#include "KRViewport.h"
|
#include "KRViewport.h"
|
||||||
|
|
||||||
KRViewport::KRViewport()
|
KRViewport::KRViewport()
|
||||||
{
|
{
|
||||||
m_size = Vector2::One();
|
m_size = Vector2::One();
|
||||||
m_matProjection = Matrix4();
|
m_matProjection = Matrix4();
|
||||||
m_matView = Matrix4();
|
m_matView = Matrix4();
|
||||||
m_lodBias = 0.0f;
|
m_lodBias = 0.0f;
|
||||||
calculateDerivedValues();
|
calculateDerivedValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
KRViewport::KRViewport(const Vector2 &size, const Matrix4 &matView, const Matrix4 &matProjection)
|
KRViewport::KRViewport(const Vector2 &size, const Matrix4 &matView, const Matrix4 &matProjection)
|
||||||
{
|
{
|
||||||
m_size = size;
|
m_size = size;
|
||||||
m_matView = matView;
|
m_matView = matView;
|
||||||
m_matProjection = matProjection;
|
m_matProjection = matProjection;
|
||||||
calculateDerivedValues();
|
calculateDerivedValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
KRViewport& KRViewport::operator=(const KRViewport &v) {
|
KRViewport& KRViewport::operator=(const KRViewport &v) {
|
||||||
if(this != &v) { // Prevent self-assignment.
|
if(this != &v) { // Prevent self-assignment.
|
||||||
m_size = v.m_size;
|
m_size = v.m_size;
|
||||||
m_matProjection = v.m_matProjection;
|
m_matProjection = v.m_matProjection;
|
||||||
m_matView = v.m_matView;
|
m_matView = v.m_matView;
|
||||||
m_lodBias = v.m_lodBias;
|
m_lodBias = v.m_lodBias;
|
||||||
|
|
||||||
calculateDerivedValues();
|
calculateDerivedValues();
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
KRViewport::~KRViewport()
|
KRViewport::~KRViewport()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vector2 &KRViewport::getSize() const
|
const Vector2 &KRViewport::getSize() const
|
||||||
{
|
{
|
||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Matrix4 &KRViewport::getViewMatrix() const
|
const Matrix4 &KRViewport::getViewMatrix() const
|
||||||
{
|
{
|
||||||
return m_matView;
|
return m_matView;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Matrix4 &KRViewport::getProjectionMatrix() const
|
const Matrix4 &KRViewport::getProjectionMatrix() const
|
||||||
{
|
{
|
||||||
return m_matProjection;
|
return m_matProjection;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRViewport::setSize(const Vector2 &size)
|
void KRViewport::setSize(const Vector2 &size)
|
||||||
{
|
{
|
||||||
m_size = size;
|
m_size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRViewport::setViewMatrix(const Matrix4 &matView)
|
void KRViewport::setViewMatrix(const Matrix4 &matView)
|
||||||
{
|
{
|
||||||
m_matView = matView;
|
m_matView = matView;
|
||||||
calculateDerivedValues();
|
calculateDerivedValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRViewport::setProjectionMatrix(const Matrix4 &matProjection)
|
void KRViewport::setProjectionMatrix(const Matrix4 &matProjection)
|
||||||
{
|
{
|
||||||
m_matProjection = matProjection;
|
m_matProjection = matProjection;
|
||||||
calculateDerivedValues();
|
calculateDerivedValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Matrix4 &KRViewport::KRViewport::getViewProjectionMatrix() const
|
const Matrix4 &KRViewport::KRViewport::getViewProjectionMatrix() const
|
||||||
{
|
{
|
||||||
return m_matViewProjection;
|
return m_matViewProjection;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Matrix4 &KRViewport::getInverseViewMatrix() const
|
const Matrix4 &KRViewport::getInverseViewMatrix() const
|
||||||
{
|
{
|
||||||
return m_matInverseView;
|
return m_matInverseView;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Matrix4 &KRViewport::getInverseProjectionMatrix() const
|
const Matrix4 &KRViewport::getInverseProjectionMatrix() const
|
||||||
{
|
{
|
||||||
return m_matInverseProjection;
|
return m_matInverseProjection;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vector3 &KRViewport::getCameraDirection() const
|
const Vector3 &KRViewport::getCameraDirection() const
|
||||||
{
|
{
|
||||||
return m_cameraDirection;
|
return m_cameraDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vector3 &KRViewport::getCameraPosition() const
|
const Vector3 &KRViewport::getCameraPosition() const
|
||||||
{
|
{
|
||||||
return m_cameraPosition;
|
return m_cameraPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int *KRViewport::getFrontToBackOrder() const
|
const int *KRViewport::getFrontToBackOrder() const
|
||||||
{
|
{
|
||||||
return &m_frontToBackOrder[0];
|
return &m_frontToBackOrder[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
const int *KRViewport::getBackToFrontOrder() const
|
const int *KRViewport::getBackToFrontOrder() const
|
||||||
{
|
{
|
||||||
return &m_backToFrontOrder[0];
|
return &m_backToFrontOrder[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRViewport::calculateDerivedValues()
|
void KRViewport::calculateDerivedValues()
|
||||||
{
|
{
|
||||||
m_matViewProjection = m_matView * m_matProjection;
|
m_matViewProjection = m_matView * m_matProjection;
|
||||||
m_matInverseView = Matrix4::Invert(m_matView);
|
m_matInverseView = Matrix4::Invert(m_matView);
|
||||||
m_matInverseProjection = Matrix4::Invert(m_matProjection);
|
m_matInverseProjection = Matrix4::Invert(m_matProjection);
|
||||||
m_cameraPosition = Matrix4::Dot(m_matInverseView, Vector3::Zero());
|
m_cameraPosition = Matrix4::Dot(m_matInverseView, Vector3::Zero());
|
||||||
m_cameraDirection = Matrix4::Dot(m_matInverseView, Vector3(0.0, 0.0, 1.0)) - Matrix4::Dot(m_matInverseView, Vector3(0.0, 0.0, 0.0));
|
m_cameraDirection = Matrix4::Dot(m_matInverseView, Vector3::Create(0.0, 0.0, 1.0)) - Matrix4::Dot(m_matInverseView, Vector3::Create(0.0, 0.0, 0.0));
|
||||||
|
|
||||||
for(int i=0; i<8; i++) {
|
for(int i=0; i<8; i++) {
|
||||||
m_frontToBackOrder[i] = i;
|
m_frontToBackOrder[i] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_cameraDirection.x > 0.0) {
|
if(m_cameraDirection.x > 0.0) {
|
||||||
KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[1]);
|
KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[1]);
|
||||||
KRENGINE_SWAP_INT(m_frontToBackOrder[2], m_frontToBackOrder[3]);
|
KRENGINE_SWAP_INT(m_frontToBackOrder[2], m_frontToBackOrder[3]);
|
||||||
KRENGINE_SWAP_INT(m_frontToBackOrder[4], m_frontToBackOrder[5]);
|
KRENGINE_SWAP_INT(m_frontToBackOrder[4], m_frontToBackOrder[5]);
|
||||||
KRENGINE_SWAP_INT(m_frontToBackOrder[6], m_frontToBackOrder[7]);
|
KRENGINE_SWAP_INT(m_frontToBackOrder[6], m_frontToBackOrder[7]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_cameraDirection.y > 0.0) {
|
if(m_cameraDirection.y > 0.0) {
|
||||||
KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[2]);
|
KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[2]);
|
||||||
KRENGINE_SWAP_INT(m_frontToBackOrder[1], m_frontToBackOrder[3]);
|
KRENGINE_SWAP_INT(m_frontToBackOrder[1], m_frontToBackOrder[3]);
|
||||||
KRENGINE_SWAP_INT(m_frontToBackOrder[4], m_frontToBackOrder[6]);
|
KRENGINE_SWAP_INT(m_frontToBackOrder[4], m_frontToBackOrder[6]);
|
||||||
KRENGINE_SWAP_INT(m_frontToBackOrder[5], m_frontToBackOrder[7]);
|
KRENGINE_SWAP_INT(m_frontToBackOrder[5], m_frontToBackOrder[7]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_cameraDirection.z > 0.0) {
|
if(m_cameraDirection.z > 0.0) {
|
||||||
KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[4]);
|
KRENGINE_SWAP_INT(m_frontToBackOrder[0], m_frontToBackOrder[4]);
|
||||||
KRENGINE_SWAP_INT(m_frontToBackOrder[1], m_frontToBackOrder[5]);
|
KRENGINE_SWAP_INT(m_frontToBackOrder[1], m_frontToBackOrder[5]);
|
||||||
KRENGINE_SWAP_INT(m_frontToBackOrder[2], m_frontToBackOrder[6]);
|
KRENGINE_SWAP_INT(m_frontToBackOrder[2], m_frontToBackOrder[6]);
|
||||||
KRENGINE_SWAP_INT(m_frontToBackOrder[3], m_frontToBackOrder[7]);
|
KRENGINE_SWAP_INT(m_frontToBackOrder[3], m_frontToBackOrder[7]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0; i<8; i++) {
|
for(int i=0; i<8; i++) {
|
||||||
m_backToFrontOrder[i] = m_frontToBackOrder[7-i];
|
m_backToFrontOrder[i] = m_frontToBackOrder[7-i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unordered_map<AABB, int> &KRViewport::getVisibleBounds()
|
unordered_map<AABB, int> &KRViewport::getVisibleBounds()
|
||||||
{
|
{
|
||||||
return m_visibleBounds;
|
return m_visibleBounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
float KRViewport::getLODBias() const
|
float KRViewport::getLODBias() const
|
||||||
{
|
{
|
||||||
return m_lodBias;
|
return m_lodBias;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRViewport::setLODBias(float lod_bias)
|
void KRViewport::setLODBias(float lod_bias)
|
||||||
{
|
{
|
||||||
m_lodBias = lod_bias;
|
m_lodBias = lod_bias;
|
||||||
}
|
}
|
||||||
|
|
||||||
float KRViewport::coverage(const AABB &b) const
|
float KRViewport::coverage(const AABB &b) const
|
||||||
{
|
{
|
||||||
if(!visible(b)) {
|
if(!visible(b)) {
|
||||||
return 0.0f; // Culled out by view frustrum
|
return 0.0f; // Culled out by view frustrum
|
||||||
} else {
|
} else {
|
||||||
Vector3 nearest_point = b.nearestPoint(getCameraPosition());
|
Vector3 nearest_point = b.nearestPoint(getCameraPosition());
|
||||||
float distance = (nearest_point - getCameraPosition()).magnitude();
|
float distance = (nearest_point - getCameraPosition()).magnitude();
|
||||||
|
|
||||||
Vector3 v = Matrix4::DotWDiv(m_matProjection, getCameraPosition() + getCameraDirection() * distance);
|
Vector3 v = Matrix4::DotWDiv(m_matProjection, getCameraPosition() + getCameraDirection() * distance);
|
||||||
|
|
||||||
float screen_depth = distance / 1000.0f;
|
float screen_depth = distance / 1000.0f;
|
||||||
|
|
||||||
return KRCLAMP(1.0f - screen_depth, 0.01f, 1.0f);
|
return KRCLAMP(1.0f - screen_depth, 0.01f, 1.0f);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Vector2 screen_min;
|
Vector2 screen_min;
|
||||||
Vector2 screen_max;
|
Vector2 screen_max;
|
||||||
// Loop through all corners and transform them to screen space
|
// Loop through all corners and transform them to screen space
|
||||||
for(int i=0; i<8; i++) {
|
for(int i=0; i<8; i++) {
|
||||||
Vector3 screen_pos = Matrix4::DotWDiv(m_matViewProjection, Vector3(i & 1 ? b.min.x : b.max.x, i & 2 ? b.min.y : b.max.y, i & 4 ? b.min.z : b.max.z));
|
Vector3 screen_pos = Matrix4::DotWDiv(m_matViewProjection, Vector3(i & 1 ? b.min.x : b.max.x, i & 2 ? b.min.y : b.max.y, i & 4 ? b.min.z : b.max.z));
|
||||||
if(i==0) {
|
if(i==0) {
|
||||||
screen_min = screen_pos.xy();
|
screen_min = screen_pos.xy();
|
||||||
screen_max = screen_pos.xy();
|
screen_max = screen_pos.xy();
|
||||||
} else {
|
} else {
|
||||||
if(screen_pos.x < screen_min.x) screen_min.x = screen_pos.x;
|
if(screen_pos.x < screen_min.x) screen_min.x = screen_pos.x;
|
||||||
if(screen_pos.y < screen_min.y) screen_min.y = screen_pos.y;
|
if(screen_pos.y < screen_min.y) screen_min.y = screen_pos.y;
|
||||||
if(screen_pos.x > screen_max.x) screen_max.x = screen_pos.x;
|
if(screen_pos.x > screen_max.x) screen_max.x = screen_pos.x;
|
||||||
if(screen_pos.y > screen_max.y) screen_max.y = screen_pos.y;
|
if(screen_pos.y > screen_max.y) screen_max.y = screen_pos.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
screen_min.x = KRCLAMP(screen_min.x, 0.0f, 1.0f);
|
screen_min.x = KRCLAMP(screen_min.x, 0.0f, 1.0f);
|
||||||
screen_min.y = KRCLAMP(screen_min.y, 0.0f, 1.0f);
|
screen_min.y = KRCLAMP(screen_min.y, 0.0f, 1.0f);
|
||||||
screen_max.x = KRCLAMP(screen_max.x, 0.0f, 1.0f);
|
screen_max.x = KRCLAMP(screen_max.x, 0.0f, 1.0f);
|
||||||
screen_max.y = KRCLAMP(screen_max.y, 0.0f, 1.0f);
|
screen_max.y = KRCLAMP(screen_max.y, 0.0f, 1.0f);
|
||||||
|
|
||||||
float c = (screen_max.x - screen_min.x) * (screen_max.y - screen_min.y);
|
float c = (screen_max.x - screen_min.x) * (screen_max.y - screen_min.y);
|
||||||
return KRCLAMP(c, 0.01f, 1.0f);
|
return KRCLAMP(c, 0.01f, 1.0f);
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool KRViewport::visible(const AABB &b) const
|
bool KRViewport::visible(const AABB &b) const
|
||||||
{
|
{
|
||||||
// test if bounding box would be within the visible range of the clip space transformed by matViewProjection
|
// test if bounding box would be within the visible range of the clip space transformed by matViewProjection
|
||||||
// This is used for view frustrum culling
|
// This is used for view frustrum culling
|
||||||
|
|
||||||
int outside_count[6] = {0, 0, 0, 0, 0, 0};
|
int outside_count[6] = {0, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
for(int iCorner=0; iCorner<8; iCorner++) {
|
for(int iCorner=0; iCorner<8; iCorner++) {
|
||||||
Vector4 sourceCornerVertex = Vector4(
|
Vector4 sourceCornerVertex = Vector4::Create(
|
||||||
(iCorner & 1) == 0 ? b.min.x : b.max.x,
|
(iCorner & 1) == 0 ? b.min.x : b.max.x,
|
||||||
(iCorner & 2) == 0 ? b.min.y : b.max.y,
|
(iCorner & 2) == 0 ? b.min.y : b.max.y,
|
||||||
(iCorner & 4) == 0 ? b.min.z : b.max.z, 1.0f);
|
(iCorner & 4) == 0 ? b.min.z : b.max.z, 1.0f);
|
||||||
|
|
||||||
Vector4 cornerVertex = Matrix4::Dot4(m_matViewProjection, sourceCornerVertex);
|
Vector4 cornerVertex = Matrix4::Dot4(m_matViewProjection, sourceCornerVertex);
|
||||||
|
|
||||||
if(cornerVertex.x < -cornerVertex.w) {
|
if(cornerVertex.x < -cornerVertex.w) {
|
||||||
outside_count[0]++;
|
outside_count[0]++;
|
||||||
}
|
}
|
||||||
if(cornerVertex.y < -cornerVertex.w) {
|
if(cornerVertex.y < -cornerVertex.w) {
|
||||||
outside_count[1]++;
|
outside_count[1]++;
|
||||||
}
|
}
|
||||||
if(cornerVertex.z < -cornerVertex.w) {
|
if(cornerVertex.z < -cornerVertex.w) {
|
||||||
outside_count[2]++;
|
outside_count[2]++;
|
||||||
}
|
}
|
||||||
if(cornerVertex.x > cornerVertex.w) {
|
if(cornerVertex.x > cornerVertex.w) {
|
||||||
outside_count[3]++;
|
outside_count[3]++;
|
||||||
}
|
}
|
||||||
if(cornerVertex.y > cornerVertex.w) {
|
if(cornerVertex.y > cornerVertex.w) {
|
||||||
outside_count[4]++;
|
outside_count[4]++;
|
||||||
}
|
}
|
||||||
if(cornerVertex.z > cornerVertex.w) {
|
if(cornerVertex.z > cornerVertex.w) {
|
||||||
outside_count[5]++;
|
outside_count[5]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_visible = true;
|
bool is_visible = true;
|
||||||
for(int iFace=0; iFace < 6; iFace++) {
|
for(int iFace=0; iFace < 6; iFace++) {
|
||||||
if(outside_count[iFace] == 8) {
|
if(outside_count[iFace] == 8) {
|
||||||
is_visible = false;
|
is_visible = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return is_visible;
|
return is_visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,73 +1,75 @@
|
|||||||
//
|
//
|
||||||
// KRViewport.h
|
// KRViewport.h
|
||||||
// KREngine
|
// KREngine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 2012-10-25.
|
// Created by Kearwood Gilbert on 2012-10-25.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef KRENGINE_KRVIEWPORT_H
|
#ifndef KRENGINE_KRVIEWPORT_H
|
||||||
#define KRENGINE_KRVIEWPORT_H
|
#define KRENGINE_KRVIEWPORT_H
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
class KRLight;
|
#include "aabb.h"
|
||||||
|
|
||||||
class KRViewport {
|
class KRLight;
|
||||||
public:
|
|
||||||
KRViewport();
|
class KRViewport {
|
||||||
KRViewport(const Vector2 &size, const Matrix4 &matView, const Matrix4 &matProjection);
|
public:
|
||||||
~KRViewport();
|
KRViewport();
|
||||||
|
KRViewport(const Vector2 &size, const Matrix4 &matView, const Matrix4 &matProjection);
|
||||||
const Vector2 &getSize() const;
|
~KRViewport();
|
||||||
const Matrix4 &getViewMatrix() const;
|
|
||||||
const Matrix4 &getProjectionMatrix() const;
|
const Vector2 &getSize() const;
|
||||||
const Matrix4 &getViewProjectionMatrix() const;
|
const Matrix4 &getViewMatrix() const;
|
||||||
const Matrix4 &getInverseViewMatrix() const;
|
const Matrix4 &getProjectionMatrix() const;
|
||||||
const Matrix4 &getInverseProjectionMatrix() const;
|
const Matrix4 &getViewProjectionMatrix() const;
|
||||||
const Vector3 &getCameraDirection() const;
|
const Matrix4 &getInverseViewMatrix() const;
|
||||||
const Vector3 &getCameraPosition() const;
|
const Matrix4 &getInverseProjectionMatrix() const;
|
||||||
const int *getFrontToBackOrder() const;
|
const Vector3 &getCameraDirection() const;
|
||||||
const int *getBackToFrontOrder() const;
|
const Vector3 &getCameraPosition() const;
|
||||||
void setSize(const Vector2 &size);
|
const int *getFrontToBackOrder() const;
|
||||||
void setViewMatrix(const Matrix4 &matView);
|
const int *getBackToFrontOrder() const;
|
||||||
void setProjectionMatrix(const Matrix4 &matProjection);
|
void setSize(const Vector2 &size);
|
||||||
float getLODBias() const;
|
void setViewMatrix(const Matrix4 &matView);
|
||||||
void setLODBias(float lod_bias);
|
void setProjectionMatrix(const Matrix4 &matProjection);
|
||||||
|
float getLODBias() const;
|
||||||
// Overload assignment operator
|
void setLODBias(float lod_bias);
|
||||||
KRViewport& operator=(const KRViewport &v);
|
|
||||||
|
// Overload assignment operator
|
||||||
unordered_map<AABB, int> &getVisibleBounds();
|
KRViewport& operator=(const KRViewport &v);
|
||||||
|
|
||||||
const std::set<KRLight *> &getVisibleLights();
|
unordered_map<AABB, int> &getVisibleBounds();
|
||||||
void setVisibleLights(const std::set<KRLight *> visibleLights);
|
|
||||||
|
const std::set<KRLight *> &getVisibleLights();
|
||||||
bool visible(const AABB &b) const;
|
void setVisibleLights(const std::set<KRLight *> visibleLights);
|
||||||
float coverage(const AABB &b) const;
|
|
||||||
|
bool visible(const AABB &b) const;
|
||||||
private:
|
float coverage(const AABB &b) const;
|
||||||
Vector2 m_size;
|
|
||||||
Matrix4 m_matView;
|
private:
|
||||||
Matrix4 m_matProjection;
|
Vector2 m_size;
|
||||||
|
Matrix4 m_matView;
|
||||||
float m_lodBias;
|
Matrix4 m_matProjection;
|
||||||
|
|
||||||
// Derived values
|
float m_lodBias;
|
||||||
Matrix4 m_matViewProjection;
|
|
||||||
Matrix4 m_matInverseView;
|
// Derived values
|
||||||
Matrix4 m_matInverseProjection;
|
Matrix4 m_matViewProjection;
|
||||||
Vector3 m_cameraDirection;
|
Matrix4 m_matInverseView;
|
||||||
Vector3 m_cameraPosition;
|
Matrix4 m_matInverseProjection;
|
||||||
|
Vector3 m_cameraDirection;
|
||||||
int m_frontToBackOrder[8];
|
Vector3 m_cameraPosition;
|
||||||
int m_backToFrontOrder[8];
|
|
||||||
|
int m_frontToBackOrder[8];
|
||||||
void calculateDerivedValues();
|
int m_backToFrontOrder[8];
|
||||||
|
|
||||||
unordered_map<AABB, int> m_visibleBounds; // AABB's that output fragments in the last frame
|
void calculateDerivedValues();
|
||||||
|
|
||||||
|
unordered_map<AABB, int> m_visibleBounds; // AABB's that output fragments in the last frame
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
339
kraken/aabb.cpp
339
kraken/aabb.cpp
@@ -1,339 +0,0 @@
|
|||||||
//
|
|
||||||
// KRAABB.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 2012-08-30.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "public/kraken.h"
|
|
||||||
#include "assert.h"
|
|
||||||
#include "KRHelpers.h"
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
AABB::AABB()
|
|
||||||
{
|
|
||||||
min = Vector3::Min();
|
|
||||||
max = Vector3::Max();
|
|
||||||
}
|
|
||||||
|
|
||||||
AABB::AABB(const Vector3 &minPoint, const Vector3 &maxPoint)
|
|
||||||
{
|
|
||||||
min = minPoint;
|
|
||||||
max = maxPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
AABB::AABB(const Vector3 &corner1, const Vector3 &corner2, const Matrix4 &modelMatrix)
|
|
||||||
{
|
|
||||||
for(int iCorner=0; iCorner<8; iCorner++) {
|
|
||||||
Vector3 sourceCornerVertex = Matrix4::DotWDiv(modelMatrix, Vector3(
|
|
||||||
(iCorner & 1) == 0 ? corner1.x : corner2.x,
|
|
||||||
(iCorner & 2) == 0 ? corner1.y : corner2.y,
|
|
||||||
(iCorner & 4) == 0 ? corner1.z : corner2.z));
|
|
||||||
|
|
||||||
|
|
||||||
if(iCorner == 0) {
|
|
||||||
min = sourceCornerVertex;
|
|
||||||
max = sourceCornerVertex;
|
|
||||||
} else {
|
|
||||||
if(sourceCornerVertex.x < min.x) min.x = sourceCornerVertex.x;
|
|
||||||
if(sourceCornerVertex.y < min.y) min.y = sourceCornerVertex.y;
|
|
||||||
if(sourceCornerVertex.z < min.z) min.z = sourceCornerVertex.z;
|
|
||||||
if(sourceCornerVertex.x > max.x) max.x = sourceCornerVertex.x;
|
|
||||||
if(sourceCornerVertex.y > max.y) max.y = sourceCornerVertex.y;
|
|
||||||
if(sourceCornerVertex.z > max.z) max.z = sourceCornerVertex.z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AABB::~AABB()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
AABB& AABB::operator =(const AABB& b)
|
|
||||||
{
|
|
||||||
min = b.min;
|
|
||||||
max = b.max;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AABB::operator ==(const AABB& b) const
|
|
||||||
{
|
|
||||||
return min == b.min && max == b.max;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AABB::operator !=(const AABB& b) const
|
|
||||||
{
|
|
||||||
return min != b.min || max != b.max;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 AABB::center() const
|
|
||||||
{
|
|
||||||
return (min + max) * 0.5f;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 AABB::size() const
|
|
||||||
{
|
|
||||||
return max - min;
|
|
||||||
}
|
|
||||||
|
|
||||||
float AABB::volume() const
|
|
||||||
{
|
|
||||||
Vector3 s = size();
|
|
||||||
return s.x * s.y * s.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AABB::scale(const Vector3 &s)
|
|
||||||
{
|
|
||||||
Vector3 prev_center = center();
|
|
||||||
Vector3 prev_size = size();
|
|
||||||
Vector3 new_scale = Vector3(prev_size.x * s.x, prev_size.y * s.y, prev_size.z * s.z) * 0.5f;
|
|
||||||
min = prev_center - new_scale;
|
|
||||||
max = prev_center + new_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AABB::scale(float s)
|
|
||||||
{
|
|
||||||
scale(Vector3(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AABB::operator >(const AABB& b) const
|
|
||||||
{
|
|
||||||
// Comparison operators are implemented to allow insertion into sorted containers such as std::set
|
|
||||||
if(min > b.min) {
|
|
||||||
return true;
|
|
||||||
} else if(min < b.min) {
|
|
||||||
return false;
|
|
||||||
} else if(max > b.max) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
bool AABB::operator <(const AABB& b) const
|
|
||||||
{
|
|
||||||
// Comparison operators are implemented to allow insertion into sorted containers such as std::set
|
|
||||||
|
|
||||||
if(min < b.min) {
|
|
||||||
return true;
|
|
||||||
} else if(min > b.min) {
|
|
||||||
return false;
|
|
||||||
} else if(max < b.max) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AABB::intersects(const AABB& b) const
|
|
||||||
{
|
|
||||||
// Return true if the two volumes intersect
|
|
||||||
return min.x <= b.max.x && min.y <= b.max.y && min.z <= b.max.z && max.x >= b.min.x && max.y >= b.min.y && max.z >= b.min.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AABB::contains(const AABB &b) const
|
|
||||||
{
|
|
||||||
// Return true if the passed KRAABB is entirely contained within this KRAABB
|
|
||||||
return b.min.x >= min.x && b.min.y >= min.y && b.min.z >= min.z && b.max.x <= max.x && b.max.y <= max.y && b.max.z <= max.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AABB::contains(const Vector3 &v) const
|
|
||||||
{
|
|
||||||
return v.x >= min.x && v.x <= max.x && v.y >= min.y && v.y <= max.y && v.z >= min.z && v.z <= max.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
AABB AABB::Infinite()
|
|
||||||
{
|
|
||||||
return AABB(Vector3::Min(), Vector3::Max());
|
|
||||||
}
|
|
||||||
|
|
||||||
AABB AABB::Zero()
|
|
||||||
{
|
|
||||||
return AABB(Vector3::Zero(), Vector3::Zero());
|
|
||||||
}
|
|
||||||
|
|
||||||
float AABB::longest_radius() const
|
|
||||||
{
|
|
||||||
float radius1 = (center() - min).magnitude();
|
|
||||||
float radius2 = (max - center()).magnitude();
|
|
||||||
return radius1 > radius2 ? radius1 : radius2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool AABB::intersectsLine(const Vector3 &v1, const Vector3 &v2) const
|
|
||||||
{
|
|
||||||
Vector3 dir = Vector3::Normalize(v2 - v1);
|
|
||||||
float length = (v2 - v1).magnitude();
|
|
||||||
|
|
||||||
// EZ cases: if the ray starts inside the box, or ends inside
|
|
||||||
// the box, then it definitely hits the box.
|
|
||||||
// I'm using this code for ray tracing with an octree,
|
|
||||||
// so I needed rays that start and end within an
|
|
||||||
// octree node to COUNT as hits.
|
|
||||||
// You could modify this test to (ray starts inside and ends outside)
|
|
||||||
// to qualify as a hit if you wanted to NOT count totally internal rays
|
|
||||||
if( contains( v1 ) || contains( v2 ) )
|
|
||||||
return true ;
|
|
||||||
|
|
||||||
// the algorithm says, find 3 t's,
|
|
||||||
Vector3 t ;
|
|
||||||
|
|
||||||
// LARGEST t is the only one we need to test if it's on the face.
|
|
||||||
for(int i = 0 ; i < 3 ; i++) {
|
|
||||||
if( dir[i] > 0 ) { // CULL BACK FACE
|
|
||||||
t[i] = ( min[i] - v1[i] ) / dir[i];
|
|
||||||
} else {
|
|
||||||
t[i] = ( max[i] - v1[i] ) / dir[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int mi = 0;
|
|
||||||
if(t[1] > t[mi]) mi = 1;
|
|
||||||
if(t[2] > t[mi]) mi = 2;
|
|
||||||
if(t[mi] >= 0 && t[mi] <= length) {
|
|
||||||
Vector3 pt = v1 + dir * t[mi];
|
|
||||||
|
|
||||||
// check it's in the box in other 2 dimensions
|
|
||||||
int o1 = ( mi + 1 ) % 3 ; // i=0: o1=1, o2=2, i=1: o1=2,o2=0 etc.
|
|
||||||
int o2 = ( mi + 2 ) % 3 ;
|
|
||||||
|
|
||||||
return pt[o1] >= min[o1] && pt[o1] <= max[o1] && pt[o2] >= min[o2] && pt[o2] <= max[o2];
|
|
||||||
}
|
|
||||||
|
|
||||||
return false ; // the ray did not hit the box.
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AABB::intersectsRay(const Vector3 &v1, const Vector3 &dir) const
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Fast Ray-Box Intersection
|
|
||||||
by Andrew Woo
|
|
||||||
from "Graphics Gems", Academic Press, 1990
|
|
||||||
*/
|
|
||||||
|
|
||||||
// FINDME, TODO - Perhaps there is a more efficient algorithm, as we don't actually need the exact coordinate of the intersection
|
|
||||||
|
|
||||||
enum {
|
|
||||||
RIGHT = 0,
|
|
||||||
LEFT = 1,
|
|
||||||
MIDDLE = 2
|
|
||||||
} quadrant[3];
|
|
||||||
|
|
||||||
bool inside = true;
|
|
||||||
Vector3 maxT;
|
|
||||||
Vector3 coord;
|
|
||||||
double candidatePlane[3];
|
|
||||||
|
|
||||||
// Find candidate planes; this loop can be avoided if rays cast all from the eye(assume perpsective view)
|
|
||||||
for (int i=0; i<3; i++)
|
|
||||||
if(v1.c[i] < min.c[i]) {
|
|
||||||
quadrant[i] = LEFT;
|
|
||||||
candidatePlane[i] = min.c[i];
|
|
||||||
inside = false;
|
|
||||||
} else if(v1.c[i] > max.c[i]) {
|
|
||||||
quadrant[i] = RIGHT;
|
|
||||||
candidatePlane[i] = max.c[i];
|
|
||||||
inside = false;
|
|
||||||
} else {
|
|
||||||
quadrant[i] = MIDDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ray v1 inside bounding box */
|
|
||||||
if (inside) {
|
|
||||||
coord = v1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate T distances to candidate planes */
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
if (quadrant[i] != MIDDLE && dir[i] != 0.0f) {
|
|
||||||
maxT.c[i] = (candidatePlane[i]-v1.c[i]) / dir[i];
|
|
||||||
} else {
|
|
||||||
maxT.c[i] = -1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get largest of the maxT's for final choice of intersection */
|
|
||||||
int whichPlane = 0;
|
|
||||||
for (int i = 1; i < 3; i++) {
|
|
||||||
if (maxT.c[whichPlane] < maxT.c[i]) {
|
|
||||||
whichPlane = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check final candidate actually inside box */
|
|
||||||
if (maxT.c[whichPlane] < 0.0f) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
if (whichPlane != i) {
|
|
||||||
coord[i] = v1.c[i] + maxT.c[whichPlane] *dir[i];
|
|
||||||
if (coord[i] < min.c[i] || coord[i] > max.c[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
assert(quadrant[i] != MIDDLE); // This should not be possible
|
|
||||||
coord[i] = candidatePlane[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true; /* ray hits box */
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AABB::intersectsSphere(const Vector3 ¢er, float radius) const
|
|
||||||
{
|
|
||||||
// Arvo's Algorithm
|
|
||||||
|
|
||||||
float squaredDistance = 0;
|
|
||||||
|
|
||||||
// process X
|
|
||||||
if (center.x < min.x) {
|
|
||||||
float diff = center.x - min.x;
|
|
||||||
squaredDistance += diff * diff;
|
|
||||||
} else if (center.x > max.x) {
|
|
||||||
float diff = center.x - max.x;
|
|
||||||
squaredDistance += diff * diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
// process Y
|
|
||||||
if (center.y < min.y) {
|
|
||||||
float diff = center.y - min.y;
|
|
||||||
squaredDistance += diff * diff;
|
|
||||||
} else if (center.y > max.y) {
|
|
||||||
float diff = center.y - max.y;
|
|
||||||
squaredDistance += diff * diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
// process Z
|
|
||||||
if (center.z < min.z) {
|
|
||||||
float diff = center.z - min.z;
|
|
||||||
squaredDistance += diff * diff;
|
|
||||||
} else if (center.z > max.z) {
|
|
||||||
float diff = center.z - max.z;
|
|
||||||
squaredDistance += diff * diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
return squaredDistance <= radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AABB::encapsulate(const AABB & b)
|
|
||||||
{
|
|
||||||
if(b.min.x < min.x) min.x = b.min.x;
|
|
||||||
if(b.min.y < min.y) min.y = b.min.y;
|
|
||||||
if(b.min.z < min.z) min.z = b.min.z;
|
|
||||||
|
|
||||||
if(b.max.x > max.x) max.x = b.max.x;
|
|
||||||
if(b.max.y > max.y) max.y = b.max.y;
|
|
||||||
if(b.max.z > max.z) max.z = b.max.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 AABB::nearestPoint(const Vector3 & v) const
|
|
||||||
{
|
|
||||||
return Vector3(KRCLAMP(v.x, min.x, max.x), KRCLAMP(v.y, min.y, max.y), KRCLAMP(v.z, min.z, max.z));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace kraken
|
|
||||||
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
//
|
|
||||||
// HitInfo.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 "public/kraken.h"
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
HitInfo::HitInfo()
|
|
||||||
{
|
|
||||||
m_position = Vector3::Zero();
|
|
||||||
m_normal = Vector3::Zero();
|
|
||||||
m_distance = 0.0f;
|
|
||||||
m_node = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HitInfo::HitInfo(const Vector3 &position, const Vector3 &normal, const float distance, KRNode *node)
|
|
||||||
{
|
|
||||||
m_position = position;
|
|
||||||
m_normal = normal;
|
|
||||||
m_distance = distance;
|
|
||||||
m_node = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
HitInfo::HitInfo(const Vector3 &position, const Vector3 &normal, const float distance)
|
|
||||||
{
|
|
||||||
m_position = position;
|
|
||||||
m_normal = normal;
|
|
||||||
m_distance = distance;
|
|
||||||
m_node = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HitInfo::~HitInfo()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HitInfo::didHit() const
|
|
||||||
{
|
|
||||||
return m_normal != Vector3::Zero();
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 HitInfo::getPosition() const
|
|
||||||
{
|
|
||||||
return m_position;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 HitInfo::getNormal() const
|
|
||||||
{
|
|
||||||
return m_normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
float HitInfo::getDistance() const
|
|
||||||
{
|
|
||||||
return m_distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRNode *HitInfo::getNode() const
|
|
||||||
{
|
|
||||||
return m_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
HitInfo& HitInfo::operator =(const HitInfo& b)
|
|
||||||
{
|
|
||||||
m_position = b.m_position;
|
|
||||||
m_normal = b.m_normal;
|
|
||||||
m_distance = b.m_distance;
|
|
||||||
m_node = b.m_node;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace kraken
|
|
||||||
|
|
||||||
@@ -1,448 +0,0 @@
|
|||||||
//
|
|
||||||
// Matrix4.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 "public/kraken.h"
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
Matrix4::Matrix4() {
|
|
||||||
// Default constructor - Initialize with an identity matrix
|
|
||||||
static const float IDENTITY_MATRIX[] = {
|
|
||||||
1.0, 0.0, 0.0, 0.0,
|
|
||||||
0.0, 1.0, 0.0, 0.0,
|
|
||||||
0.0, 0.0, 1.0, 0.0,
|
|
||||||
0.0, 0.0, 0.0, 1.0
|
|
||||||
};
|
|
||||||
memcpy(c, IDENTITY_MATRIX, sizeof(float) * 16);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix4::Matrix4(float *pMat) {
|
|
||||||
memcpy(c, pMat, sizeof(float) * 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix4::Matrix4(const Vector3 &new_axis_x, const Vector3 &new_axis_y, const Vector3 &new_axis_z, const Vector3 &new_transform)
|
|
||||||
{
|
|
||||||
c[0] = new_axis_x.x; c[1] = new_axis_x.y; c[2] = new_axis_x.z; c[3] = 0.0f;
|
|
||||||
c[4] = new_axis_y.x; c[5] = new_axis_y.y; c[6] = new_axis_y.z; c[7] = 0.0f;
|
|
||||||
c[8] = new_axis_z.x; c[9] = new_axis_z.y; c[10] = new_axis_z.z; c[11] = 0.0f;
|
|
||||||
c[12] = new_transform.x; c[13] = new_transform.y; c[14] = new_transform.z; c[15] = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix4::~Matrix4() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
float *Matrix4::getPointer() {
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy constructor
|
|
||||||
Matrix4::Matrix4(const Matrix4 &m) {
|
|
||||||
memcpy(c, m.c, sizeof(float) * 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix4& Matrix4::operator=(const Matrix4 &m) {
|
|
||||||
if(this != &m) { // Prevent self-assignment.
|
|
||||||
memcpy(c, m.c, sizeof(float) * 16);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
float& Matrix4::operator[](unsigned i) {
|
|
||||||
return c[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
float Matrix4::operator[](unsigned i) const {
|
|
||||||
return c[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overload comparison operator
|
|
||||||
bool Matrix4::operator==(const Matrix4 &m) const {
|
|
||||||
return memcmp(c, m.c, sizeof(float) * 16) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overload compound multiply operator
|
|
||||||
Matrix4& Matrix4::operator*=(const Matrix4 &m) {
|
|
||||||
float temp[16];
|
|
||||||
|
|
||||||
int x,y;
|
|
||||||
|
|
||||||
for (x=0; x < 4; x++)
|
|
||||||
{
|
|
||||||
for(y=0; y < 4; y++)
|
|
||||||
{
|
|
||||||
temp[y + (x*4)] = (c[x*4] * m.c[y]) +
|
|
||||||
(c[(x*4)+1] * m.c[y+4]) +
|
|
||||||
(c[(x*4)+2] * m.c[y+8]) +
|
|
||||||
(c[(x*4)+3] * m.c[y+12]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(c, temp, sizeof(float) << 4);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overload multiply operator
|
|
||||||
Matrix4 Matrix4::operator*(const Matrix4 &m) const {
|
|
||||||
Matrix4 ret = *this;
|
|
||||||
ret *= m;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Generate a perspective view matrix using a field of view angle fov,
|
|
||||||
* window aspect ratio, near and far clipping planes */
|
|
||||||
void Matrix4::perspective(float fov, float aspect, float nearz, float farz) {
|
|
||||||
|
|
||||||
memset(c, 0, sizeof(float) * 16);
|
|
||||||
|
|
||||||
float range= tan(fov * 0.5) * nearz;
|
|
||||||
c[0] = (2 * nearz) / ((range * aspect) - (-range * aspect));
|
|
||||||
c[5] = (2 * nearz) / (2 * range);
|
|
||||||
c[10] = -(farz + nearz) / (farz - nearz);
|
|
||||||
c[11] = -1;
|
|
||||||
c[14] = -(2 * farz * nearz) / (farz - nearz);
|
|
||||||
/*
|
|
||||||
float range= atan(fov / 20.0f) * nearz;
|
|
||||||
float r = range * aspect;
|
|
||||||
float t = range * 1.0;
|
|
||||||
|
|
||||||
c[0] = nearz / r;
|
|
||||||
c[5] = nearz / t;
|
|
||||||
c[10] = -(farz + nearz) / (farz - nearz);
|
|
||||||
c[11] = -(2.0 * farz * nearz) / (farz - nearz);
|
|
||||||
c[14] = -1.0;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Perform translation operations on a matrix */
|
|
||||||
void Matrix4::translate(float x, float y, float z) {
|
|
||||||
Matrix4 newMatrix; // Create new identity matrix
|
|
||||||
|
|
||||||
newMatrix.c[12] = x;
|
|
||||||
newMatrix.c[13] = y;
|
|
||||||
newMatrix.c[14] = z;
|
|
||||||
|
|
||||||
*this *= newMatrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Matrix4::translate(const Vector3 &v)
|
|
||||||
{
|
|
||||||
translate(v.x, v.y, v.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Rotate a matrix by an angle on a X, Y, or Z axis */
|
|
||||||
void Matrix4::rotate(float angle, AXIS axis) {
|
|
||||||
const int cos1[3] = { 5, 0, 0 }; // cos(angle)
|
|
||||||
const int cos2[3] = { 10, 10, 5 }; // cos(angle)
|
|
||||||
const int sin1[3] = { 9, 2, 4 }; // -sin(angle)
|
|
||||||
const int sin2[3] = { 6, 8, 1 }; // sin(angle)
|
|
||||||
|
|
||||||
/*
|
|
||||||
X_AXIS:
|
|
||||||
|
|
||||||
1, 0, 0, 0
|
|
||||||
0, cos(angle), -sin(angle), 0
|
|
||||||
0, sin(angle), cos(angle), 0
|
|
||||||
0, 0, 0, 1
|
|
||||||
|
|
||||||
Y_AXIS:
|
|
||||||
|
|
||||||
cos(angle), 0, -sin(angle), 0
|
|
||||||
0, 1, 0, 0
|
|
||||||
sin(angle), 0, cos(angle), 0
|
|
||||||
0, 0, 0, 1
|
|
||||||
|
|
||||||
Z_AXIS:
|
|
||||||
|
|
||||||
cos(angle), -sin(angle), 0, 0
|
|
||||||
sin(angle), cos(angle), 0, 0
|
|
||||||
0, 0, 1, 0
|
|
||||||
0, 0, 0, 1
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
Matrix4 newMatrix; // Create new identity matrix
|
|
||||||
|
|
||||||
newMatrix.c[cos1[axis]] = cos(angle);
|
|
||||||
newMatrix.c[sin1[axis]] = -sin(angle);
|
|
||||||
newMatrix.c[sin2[axis]] = -newMatrix.c[sin1[axis]];
|
|
||||||
newMatrix.c[cos2[axis]] = newMatrix.c[cos1[axis]];
|
|
||||||
|
|
||||||
*this *= newMatrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Matrix4::rotate(const Quaternion &q)
|
|
||||||
{
|
|
||||||
*this *= q.rotationMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Scale matrix by separate x, y, and z amounts */
|
|
||||||
void Matrix4::scale(float x, float y, float z) {
|
|
||||||
Matrix4 newMatrix; // Create new identity matrix
|
|
||||||
|
|
||||||
newMatrix.c[0] = x;
|
|
||||||
newMatrix.c[5] = y;
|
|
||||||
newMatrix.c[10] = z;
|
|
||||||
|
|
||||||
*this *= newMatrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Matrix4::scale(const Vector3 &v) {
|
|
||||||
scale(v.x, v.y, v.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Scale all dimensions equally */
|
|
||||||
void Matrix4::scale(float s) {
|
|
||||||
scale(s,s,s);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize with a bias matrix
|
|
||||||
void Matrix4::bias() {
|
|
||||||
static const float BIAS_MATRIX[] = {
|
|
||||||
0.5, 0.0, 0.0, 0.0,
|
|
||||||
0.0, 0.5, 0.0, 0.0,
|
|
||||||
0.0, 0.0, 0.5, 0.0,
|
|
||||||
0.5, 0.5, 0.5, 1.0
|
|
||||||
};
|
|
||||||
memcpy(c, BIAS_MATRIX, sizeof(float) * 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Generate an orthographic view matrix */
|
|
||||||
void Matrix4::ortho(float left, float right, float top, float bottom, float nearz, float farz) {
|
|
||||||
memset(c, 0, sizeof(float) * 16);
|
|
||||||
c[0] = 2.0f / (right - left);
|
|
||||||
c[5] = 2.0f / (bottom - top);
|
|
||||||
c[10] = -1.0f / (farz - nearz);
|
|
||||||
c[11] = -nearz / (farz - nearz);
|
|
||||||
c[15] = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Replace matrix with its inverse */
|
|
||||||
bool Matrix4::invert() {
|
|
||||||
// Based on gluInvertMatrix implementation
|
|
||||||
|
|
||||||
float inv[16], det;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
inv[0] = c[5]*c[10]*c[15] - c[5]*c[11]*c[14] - c[9]*c[6]*c[15]
|
|
||||||
+ c[9]*c[7]*c[14] + c[13]*c[6]*c[11] - c[13]*c[7]*c[10];
|
|
||||||
inv[4] = -c[4]*c[10]*c[15] + c[4]*c[11]*c[14] + c[8]*c[6]*c[15]
|
|
||||||
- c[8]*c[7]*c[14] - c[12]*c[6]*c[11] + c[12]*c[7]*c[10];
|
|
||||||
inv[8] = c[4]*c[9]*c[15] - c[4]*c[11]*c[13] - c[8]*c[5]*c[15]
|
|
||||||
+ c[8]*c[7]*c[13] + c[12]*c[5]*c[11] - c[12]*c[7]*c[9];
|
|
||||||
inv[12] = -c[4]*c[9]*c[14] + c[4]*c[10]*c[13] + c[8]*c[5]*c[14]
|
|
||||||
- c[8]*c[6]*c[13] - c[12]*c[5]*c[10] + c[12]*c[6]*c[9];
|
|
||||||
inv[1] = -c[1]*c[10]*c[15] + c[1]*c[11]*c[14] + c[9]*c[2]*c[15]
|
|
||||||
- c[9]*c[3]*c[14] - c[13]*c[2]*c[11] + c[13]*c[3]*c[10];
|
|
||||||
inv[5] = c[0]*c[10]*c[15] - c[0]*c[11]*c[14] - c[8]*c[2]*c[15]
|
|
||||||
+ c[8]*c[3]*c[14] + c[12]*c[2]*c[11] - c[12]*c[3]*c[10];
|
|
||||||
inv[9] = -c[0]*c[9]*c[15] + c[0]*c[11]*c[13] + c[8]*c[1]*c[15]
|
|
||||||
- c[8]*c[3]*c[13] - c[12]*c[1]*c[11] + c[12]*c[3]*c[9];
|
|
||||||
inv[13] = c[0]*c[9]*c[14] - c[0]*c[10]*c[13] - c[8]*c[1]*c[14]
|
|
||||||
+ c[8]*c[2]*c[13] + c[12]*c[1]*c[10] - c[12]*c[2]*c[9];
|
|
||||||
inv[2] = c[1]*c[6]*c[15] - c[1]*c[7]*c[14] - c[5]*c[2]*c[15]
|
|
||||||
+ c[5]*c[3]*c[14] + c[13]*c[2]*c[7] - c[13]*c[3]*c[6];
|
|
||||||
inv[6] = -c[0]*c[6]*c[15] + c[0]*c[7]*c[14] + c[4]*c[2]*c[15]
|
|
||||||
- c[4]*c[3]*c[14] - c[12]*c[2]*c[7] + c[12]*c[3]*c[6];
|
|
||||||
inv[10] = c[0]*c[5]*c[15] - c[0]*c[7]*c[13] - c[4]*c[1]*c[15]
|
|
||||||
+ c[4]*c[3]*c[13] + c[12]*c[1]*c[7] - c[12]*c[3]*c[5];
|
|
||||||
inv[14] = -c[0]*c[5]*c[14] + c[0]*c[6]*c[13] + c[4]*c[1]*c[14]
|
|
||||||
- c[4]*c[2]*c[13] - c[12]*c[1]*c[6] + c[12]*c[2]*c[5];
|
|
||||||
inv[3] = -c[1]*c[6]*c[11] + c[1]*c[7]*c[10] + c[5]*c[2]*c[11]
|
|
||||||
- c[5]*c[3]*c[10] - c[9]*c[2]*c[7] + c[9]*c[3]*c[6];
|
|
||||||
inv[7] = c[0]*c[6]*c[11] - c[0]*c[7]*c[10] - c[4]*c[2]*c[11]
|
|
||||||
+ c[4]*c[3]*c[10] + c[8]*c[2]*c[7] - c[8]*c[3]*c[6];
|
|
||||||
inv[11] = -c[0]*c[5]*c[11] + c[0]*c[7]*c[9] + c[4]*c[1]*c[11]
|
|
||||||
- c[4]*c[3]*c[9] - c[8]*c[1]*c[7] + c[8]*c[3]*c[5];
|
|
||||||
inv[15] = c[0]*c[5]*c[10] - c[0]*c[6]*c[9] - c[4]*c[1]*c[10]
|
|
||||||
+ c[4]*c[2]*c[9] + c[8]*c[1]*c[6] - c[8]*c[2]*c[5];
|
|
||||||
|
|
||||||
det = c[0]*inv[0] + c[1]*inv[4] + c[2]*inv[8] + c[3]*inv[12];
|
|
||||||
|
|
||||||
if (det == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
det = 1.0 / det;
|
|
||||||
|
|
||||||
for (i = 0; i < 16; i++) {
|
|
||||||
c[i] = inv[i] * det;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Matrix4::transpose() {
|
|
||||||
float trans[16];
|
|
||||||
for(int x=0; x<4; x++) {
|
|
||||||
for(int y=0; y<4; y++) {
|
|
||||||
trans[x + y * 4] = c[y + x * 4];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memcpy(c, trans, sizeof(float) * 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dot Product, returning Vector3 */
|
|
||||||
Vector3 Matrix4::Dot(const Matrix4 &m, const Vector3 &v) {
|
|
||||||
return Vector3(
|
|
||||||
v.c[0] * m.c[0] + v.c[1] * m.c[4] + v.c[2] * m.c[8] + m.c[12],
|
|
||||||
v.c[0] * m.c[1] + v.c[1] * m.c[5] + v.c[2] * m.c[9] + m.c[13],
|
|
||||||
v.c[0] * m.c[2] + v.c[1] * m.c[6] + v.c[2] * m.c[10] + m.c[14]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4 Matrix4::Dot4(const Matrix4 &m, const Vector4 &v) {
|
|
||||||
#ifdef KRAKEN_USE_ARM_NEON
|
|
||||||
|
|
||||||
Vector4 d;
|
|
||||||
asm volatile (
|
|
||||||
"vld1.32 {d0, d1}, [%1] \n\t" //Q0 = v
|
|
||||||
"vld1.32 {d18, d19}, [%0]! \n\t" //Q1 = m
|
|
||||||
"vld1.32 {d20, d21}, [%0]! \n\t" //Q2 = m+4
|
|
||||||
"vld1.32 {d22, d23}, [%0]! \n\t" //Q3 = m+8
|
|
||||||
"vld1.32 {d24, d25}, [%0]! \n\t" //Q4 = m+12
|
|
||||||
|
|
||||||
"vmul.f32 q13, q9, d0[0] \n\t" //Q5 = Q1*Q0[0]
|
|
||||||
"vmla.f32 q13, q10, d0[1] \n\t" //Q5 += Q1*Q0[1]
|
|
||||||
"vmla.f32 q13, q11, d1[0] \n\t" //Q5 += Q2*Q0[2]
|
|
||||||
"vmla.f32 q13, q12, d1[1] \n\t" //Q5 += Q3*Q0[3]
|
|
||||||
|
|
||||||
"vst1.32 {d26, d27}, [%2] \n\t" //Q4 = m+12
|
|
||||||
: /* no output registers */
|
|
||||||
: "r"(m.c), "r"(v.c), "r"(d.c)
|
|
||||||
: "q0", "q9", "q10","q11", "q12", "q13", "memory"
|
|
||||||
);
|
|
||||||
return d;
|
|
||||||
#else
|
|
||||||
return Vector4(
|
|
||||||
v.c[0] * m.c[0] + v.c[1] * m.c[4] + v.c[2] * m.c[8] + m.c[12],
|
|
||||||
v.c[0] * m.c[1] + v.c[1] * m.c[5] + v.c[2] * m.c[9] + m.c[13],
|
|
||||||
v.c[0] * m.c[2] + v.c[1] * m.c[6] + v.c[2] * m.c[10] + m.c[14],
|
|
||||||
v.c[0] * m.c[3] + v.c[1] * m.c[7] + v.c[2] * m.c[11] + m.c[15]
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dot product without including translation; useful for transforming normals and tangents
|
|
||||||
Vector3 Matrix4::DotNoTranslate(const Matrix4 &m, const Vector3 &v)
|
|
||||||
{
|
|
||||||
return Vector3(
|
|
||||||
v.x * m.c[0] + v.y * m.c[4] + v.z * m.c[8],
|
|
||||||
v.x * m.c[1] + v.y * m.c[5] + v.z * m.c[9],
|
|
||||||
v.x * m.c[2] + v.y * m.c[6] + v.z * m.c[10]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dot Product, returning w component as if it were a Vector4 (This will be deprecated once Vector4 is implemented instead*/
|
|
||||||
float Matrix4::DotW(const Matrix4 &m, const Vector3 &v) {
|
|
||||||
return v.x * m.c[0*4 + 3] + v.y * m.c[1*4 + 3] + v.z * m.c[2*4 + 3] + m.c[3*4 + 3];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dot Product followed by W-divide */
|
|
||||||
Vector3 Matrix4::DotWDiv(const Matrix4 &m, const Vector3 &v) {
|
|
||||||
Vector4 r = Dot4(m, Vector4(v, 1.0f));
|
|
||||||
return Vector3(r) / r.w;
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix4 Matrix4::LookAt(const Vector3 &cameraPos, const Vector3 &lookAtPos, const Vector3 &upDirection)
|
|
||||||
{
|
|
||||||
Matrix4 matLookat;
|
|
||||||
Vector3 lookat_z_axis = lookAtPos - cameraPos;
|
|
||||||
lookat_z_axis.normalize();
|
|
||||||
Vector3 lookat_x_axis = Vector3::Cross(upDirection, lookat_z_axis);
|
|
||||||
lookat_x_axis.normalize();
|
|
||||||
Vector3 lookat_y_axis = Vector3::Cross(lookat_z_axis, lookat_x_axis);
|
|
||||||
|
|
||||||
matLookat.getPointer()[0] = lookat_x_axis.x;
|
|
||||||
matLookat.getPointer()[1] = lookat_y_axis.x;
|
|
||||||
matLookat.getPointer()[2] = lookat_z_axis.x;
|
|
||||||
|
|
||||||
matLookat.getPointer()[4] = lookat_x_axis.y;
|
|
||||||
matLookat.getPointer()[5] = lookat_y_axis.y;
|
|
||||||
matLookat.getPointer()[6] = lookat_z_axis.y;
|
|
||||||
|
|
||||||
matLookat.getPointer()[8] = lookat_x_axis.z;
|
|
||||||
matLookat.getPointer()[9] = lookat_y_axis.z;
|
|
||||||
matLookat.getPointer()[10] = lookat_z_axis.z;
|
|
||||||
|
|
||||||
matLookat.getPointer()[12] = -Vector3::Dot(lookat_x_axis, cameraPos);
|
|
||||||
matLookat.getPointer()[13] = -Vector3::Dot(lookat_y_axis, cameraPos);
|
|
||||||
matLookat.getPointer()[14] = -Vector3::Dot(lookat_z_axis, cameraPos);
|
|
||||||
|
|
||||||
return matLookat;
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix4 Matrix4::Invert(const Matrix4 &m)
|
|
||||||
{
|
|
||||||
Matrix4 matInvert = m;
|
|
||||||
matInvert.invert();
|
|
||||||
return matInvert;
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix4 Matrix4::Transpose(const Matrix4 &m)
|
|
||||||
{
|
|
||||||
Matrix4 matTranspose = m;
|
|
||||||
matTranspose.transpose();
|
|
||||||
return matTranspose;
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix4 Matrix4::Translation(const Vector3 &v)
|
|
||||||
{
|
|
||||||
Matrix4 m;
|
|
||||||
m[12] = v.x;
|
|
||||||
m[13] = v.y;
|
|
||||||
m[14] = v.z;
|
|
||||||
// m.translate(v);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix4 Matrix4::Rotation(const Vector3 &v)
|
|
||||||
{
|
|
||||||
Matrix4 m;
|
|
||||||
m.rotate(v.x, X_AXIS);
|
|
||||||
m.rotate(v.y, Y_AXIS);
|
|
||||||
m.rotate(v.z, Z_AXIS);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix4 Matrix4::Scaling(const Vector3 &v)
|
|
||||||
{
|
|
||||||
Matrix4 m;
|
|
||||||
m.scale(v);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace kraken
|
|
||||||
|
|
||||||
@@ -1,11 +1,2 @@
|
|||||||
add_public_header(kraken.h)
|
add_public_header(kraken.h)
|
||||||
add_public_header(scalar.h)
|
set(KRAKEN_PUBLIC_HEADERS "${KRAKEN_PUBLIC_HEADERS}" PARENT_SCOPE)
|
||||||
add_public_header(vector2.h)
|
|
||||||
add_public_header(vector3.h)
|
|
||||||
add_public_header(vector4.h)
|
|
||||||
add_public_header(triangle3.h)
|
|
||||||
add_public_header(quaternion.h)
|
|
||||||
add_public_header(aabb.h)
|
|
||||||
add_public_header(matrix4.h)
|
|
||||||
add_public_header(hitinfo.h)
|
|
||||||
set(KRAKEN_PUBLIC_HEADERS "${KRAKEN_PUBLIC_HEADERS}" PARENT_SCOPE)
|
|
||||||
|
|||||||
@@ -1,102 +0,0 @@
|
|||||||
//
|
|
||||||
// KRAABB.h
|
|
||||||
// Kraken
|
|
||||||
//
|
|
||||||
// Copyright 2018 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.
|
|
||||||
//
|
|
||||||
|
|
||||||
// Axis aligned bounding box (AABB)
|
|
||||||
|
|
||||||
#ifndef KRAKEN_AABB_H
|
|
||||||
#define KRAKEN_AABB_H
|
|
||||||
|
|
||||||
#include <functional> // for hash<>
|
|
||||||
|
|
||||||
#include "vector2.h"
|
|
||||||
#include "vector3.h"
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
class Matrix4;
|
|
||||||
|
|
||||||
class AABB {
|
|
||||||
public:
|
|
||||||
Vector3 min;
|
|
||||||
Vector3 max;
|
|
||||||
|
|
||||||
AABB(const Vector3 &minPoint, const Vector3 &maxPoint);
|
|
||||||
AABB(const Vector3 &corner1, const Vector3 &corner2, const Matrix4 &modelMatrix);
|
|
||||||
AABB();
|
|
||||||
~AABB();
|
|
||||||
|
|
||||||
void scale(const Vector3 &s);
|
|
||||||
void scale(float s);
|
|
||||||
|
|
||||||
Vector3 center() const;
|
|
||||||
Vector3 size() const;
|
|
||||||
float volume() const;
|
|
||||||
bool intersects(const AABB& b) const;
|
|
||||||
bool contains(const AABB &b) const;
|
|
||||||
bool contains(const Vector3 &v) const;
|
|
||||||
|
|
||||||
bool intersectsLine(const Vector3 &v1, const Vector3 &v2) const;
|
|
||||||
bool intersectsRay(const Vector3 &v1, const Vector3 &dir) const;
|
|
||||||
bool intersectsSphere(const Vector3 ¢er, float radius) const;
|
|
||||||
void encapsulate(const AABB & b);
|
|
||||||
|
|
||||||
AABB& operator =(const AABB& b);
|
|
||||||
bool operator ==(const AABB& b) const;
|
|
||||||
bool operator !=(const AABB& b) const;
|
|
||||||
|
|
||||||
// Comparison operators are implemented to allow insertion into sorted containers such as std::set
|
|
||||||
bool operator >(const AABB& b) const;
|
|
||||||
bool operator <(const AABB& b) const;
|
|
||||||
|
|
||||||
static AABB Infinite();
|
|
||||||
static AABB Zero();
|
|
||||||
|
|
||||||
float longest_radius() const;
|
|
||||||
Vector3 nearestPoint(const Vector3 & v) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace kraken
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template<>
|
|
||||||
struct hash<kraken::AABB> {
|
|
||||||
public:
|
|
||||||
size_t operator()(const kraken::AABB &s) const
|
|
||||||
{
|
|
||||||
size_t h1 = hash<kraken::Vector3>()(s.min);
|
|
||||||
size_t h2 = hash<kraken::Vector3>()(s.max);
|
|
||||||
return h1 ^ ( h2 << 1 );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* defined(KRAKEN_AABB_H) */
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
//
|
|
||||||
// hitinfo.h
|
|
||||||
// Kraken
|
|
||||||
//
|
|
||||||
// Copyright 2018 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.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRAKEN_HITINFO_H
|
|
||||||
#define KRAKEN_HITINFO_H
|
|
||||||
|
|
||||||
#include "vector3.h"
|
|
||||||
|
|
||||||
class KRNode;
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
class HitInfo {
|
|
||||||
public:
|
|
||||||
HitInfo();
|
|
||||||
HitInfo(const Vector3 &position, const Vector3 &normal, const float distance);
|
|
||||||
HitInfo(const Vector3 &position, const Vector3 &normal, const float distance, KRNode *node);
|
|
||||||
~HitInfo();
|
|
||||||
|
|
||||||
Vector3 getPosition() const;
|
|
||||||
Vector3 getNormal() const;
|
|
||||||
float getDistance() const;
|
|
||||||
KRNode *getNode() const;
|
|
||||||
bool didHit() const;
|
|
||||||
|
|
||||||
HitInfo& operator =(const HitInfo& b);
|
|
||||||
|
|
||||||
private:
|
|
||||||
KRNode *m_node;
|
|
||||||
Vector3 m_position;
|
|
||||||
Vector3 m_normal;
|
|
||||||
float m_distance;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace kraken
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,44 +1,35 @@
|
|||||||
//
|
//
|
||||||
// Kraken
|
// Kraken
|
||||||
//
|
//
|
||||||
// Copyright 2018 Kearwood Gilbert. All rights reserved.
|
// Copyright 2018 Kearwood Gilbert. All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
// permitted provided that the following conditions are met:
|
// permitted provided that the following conditions are met:
|
||||||
//
|
//
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
// conditions and the following disclaimer.
|
// conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
// provided with the distribution.
|
// provided with the distribution.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
// or implied, of Kearwood Gilbert.
|
// or implied, of Kearwood Gilbert.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef KRAKEN_H
|
#ifndef KRAKEN_H
|
||||||
#define KRAKEN_H
|
#define KRAKEN_H
|
||||||
|
|
||||||
#include "scalar.h"
|
|
||||||
#include "vector2.h"
|
#endif // KRAKEN_H
|
||||||
#include "vector3.h"
|
|
||||||
#include "vector4.h"
|
|
||||||
#include "matrix4.h"
|
|
||||||
#include "quaternion.h"
|
|
||||||
#include "aabb.h"
|
|
||||||
#include "triangle3.h"
|
|
||||||
#include "hitinfo.h"
|
|
||||||
|
|
||||||
#endif // KRAKEN_H
|
|
||||||
|
|||||||
@@ -1,136 +0,0 @@
|
|||||||
//
|
|
||||||
// Matrix4.h
|
|
||||||
// Kraken
|
|
||||||
//
|
|
||||||
// Copyright 2018 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 "vector3.h"
|
|
||||||
#include "vector4.h"
|
|
||||||
|
|
||||||
#ifndef KRAKEN_MATRIX4_H
|
|
||||||
#define KRAKEN_MATRIX4_H
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
X_AXIS,
|
|
||||||
Y_AXIS,
|
|
||||||
Z_AXIS
|
|
||||||
} AXIS;
|
|
||||||
|
|
||||||
class Quaternion;
|
|
||||||
|
|
||||||
class Matrix4 {
|
|
||||||
public:
|
|
||||||
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
Vector4 axis_x, axis_y, axis_z, transform;
|
|
||||||
};
|
|
||||||
// Matrix components, in column-major order
|
|
||||||
float c[16];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Default constructor - Creates an identity matrix
|
|
||||||
Matrix4();
|
|
||||||
|
|
||||||
Matrix4(float *pMat);
|
|
||||||
|
|
||||||
Matrix4(const Vector3 &new_axis_x, const Vector3 &new_axis_y, const Vector3 &new_axis_z, const Vector3 &new_transform);
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
~Matrix4();
|
|
||||||
|
|
||||||
// Copy constructor
|
|
||||||
Matrix4(const Matrix4 &m);
|
|
||||||
|
|
||||||
// Overload assignment operator
|
|
||||||
Matrix4& operator=(const Matrix4 &m);
|
|
||||||
|
|
||||||
// Overload comparison operator
|
|
||||||
bool operator==(const Matrix4 &m) const;
|
|
||||||
|
|
||||||
// Overload compound multiply operator
|
|
||||||
Matrix4& operator*=(const Matrix4 &m);
|
|
||||||
|
|
||||||
float& operator[](unsigned i);
|
|
||||||
float operator[](unsigned i) const;
|
|
||||||
|
|
||||||
// Overload multiply operator
|
|
||||||
//Matrix4& operator*(const Matrix4 &m);
|
|
||||||
Matrix4 operator*(const Matrix4 &m) const;
|
|
||||||
|
|
||||||
float *getPointer();
|
|
||||||
|
|
||||||
void perspective(float fov, float aspect, float nearz, float farz);
|
|
||||||
void ortho(float left, float right, float top, float bottom, float nearz, float farz);
|
|
||||||
void translate(float x, float y, float z);
|
|
||||||
void translate(const Vector3 &v);
|
|
||||||
void scale(float x, float y, float z);
|
|
||||||
void scale(const Vector3 &v);
|
|
||||||
void scale(float s);
|
|
||||||
void rotate(float angle, AXIS axis);
|
|
||||||
void rotate(const Quaternion &q);
|
|
||||||
void bias();
|
|
||||||
bool invert();
|
|
||||||
void transpose();
|
|
||||||
|
|
||||||
static Vector3 DotNoTranslate(const Matrix4 &m, const Vector3 &v); // Dot product without including translation; useful for transforming normals and tangents
|
|
||||||
static Matrix4 Invert(const Matrix4 &m);
|
|
||||||
static Matrix4 Transpose(const Matrix4 &m);
|
|
||||||
static Vector3 Dot(const Matrix4 &m, const Vector3 &v);
|
|
||||||
static Vector4 Dot4(const Matrix4 &m, const Vector4 &v);
|
|
||||||
static float DotW(const Matrix4 &m, const Vector3 &v);
|
|
||||||
static Vector3 DotWDiv(const Matrix4 &m, const Vector3 &v);
|
|
||||||
|
|
||||||
static Matrix4 LookAt(const Vector3 &cameraPos, const Vector3 &lookAtPos, const Vector3 &upDirection);
|
|
||||||
|
|
||||||
static Matrix4 Translation(const Vector3 &v);
|
|
||||||
static Matrix4 Rotation(const Vector3 &v);
|
|
||||||
static Matrix4 Scaling(const Vector3 &v);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace kraken
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template<>
|
|
||||||
struct hash<kraken::Matrix4> {
|
|
||||||
public:
|
|
||||||
size_t operator()(const kraken::Matrix4 &s) const
|
|
||||||
{
|
|
||||||
size_t h1 = hash<kraken::Vector4>()(s.axis_x);
|
|
||||||
size_t h2 = hash<kraken::Vector4>()(s.axis_y);
|
|
||||||
size_t h3 = hash<kraken::Vector4>()(s.axis_z);
|
|
||||||
size_t h4 = hash<kraken::Vector4>()(s.transform);
|
|
||||||
return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
#endif // KRAKEN_MATRIX4_H
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
//
|
|
||||||
// Quaternion.h
|
|
||||||
// Kraken
|
|
||||||
//
|
|
||||||
// Copyright 2018 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.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRAKEN_QUATERNION_H
|
|
||||||
#define KRAKEN_QUATERNION_H
|
|
||||||
|
|
||||||
#include "vector3.h"
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
class Quaternion {
|
|
||||||
public:
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
float w, x, y, z;
|
|
||||||
};
|
|
||||||
float c[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
Quaternion();
|
|
||||||
Quaternion(float w, float x, float y, float z);
|
|
||||||
Quaternion(const Quaternion& p);
|
|
||||||
Quaternion(const Vector3 &euler);
|
|
||||||
Quaternion(const Vector3 &from_vector, const Vector3 &to_vector);
|
|
||||||
~Quaternion();
|
|
||||||
|
|
||||||
Quaternion& operator =( const Quaternion& p );
|
|
||||||
Quaternion operator +(const Quaternion &v) const;
|
|
||||||
Quaternion operator -(const Quaternion &v) const;
|
|
||||||
Quaternion operator +() const;
|
|
||||||
Quaternion operator -() const;
|
|
||||||
|
|
||||||
Quaternion operator *(const Quaternion &v);
|
|
||||||
Quaternion operator *(float num) const;
|
|
||||||
Quaternion operator /(float num) const;
|
|
||||||
|
|
||||||
Quaternion& operator +=(const Quaternion& v);
|
|
||||||
Quaternion& operator -=(const Quaternion& v);
|
|
||||||
Quaternion& operator *=(const Quaternion& v);
|
|
||||||
Quaternion& operator *=(const float& v);
|
|
||||||
Quaternion& operator /=(const float& v);
|
|
||||||
|
|
||||||
friend bool operator ==(Quaternion &v1, Quaternion &v2);
|
|
||||||
friend bool operator !=(Quaternion &v1, Quaternion &v2);
|
|
||||||
float& operator [](unsigned i);
|
|
||||||
float operator [](unsigned i) const;
|
|
||||||
|
|
||||||
void setEulerXYZ(const Vector3 &euler);
|
|
||||||
void setEulerZYX(const Vector3 &euler);
|
|
||||||
Vector3 eulerXYZ() const;
|
|
||||||
Matrix4 rotationMatrix() const;
|
|
||||||
|
|
||||||
void normalize();
|
|
||||||
static Quaternion Normalize(const Quaternion &v1);
|
|
||||||
|
|
||||||
void conjugate();
|
|
||||||
static Quaternion Conjugate(const Quaternion &v1);
|
|
||||||
|
|
||||||
static Quaternion FromAngleAxis(const Vector3 &axis, float angle);
|
|
||||||
static Quaternion Lerp(const Quaternion &a, const Quaternion &b, float t);
|
|
||||||
static Quaternion Slerp(const Quaternion &a, const Quaternion &b, float t);
|
|
||||||
static float Dot(const Quaternion &v1, const Quaternion &v2);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace kraken
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template<>
|
|
||||||
struct hash<kraken::Quaternion> {
|
|
||||||
public:
|
|
||||||
size_t operator()(const kraken::Quaternion &s) const
|
|
||||||
{
|
|
||||||
size_t h1 = hash<float>()(s.c[0]);
|
|
||||||
size_t h2 = hash<float>()(s.c[1]);
|
|
||||||
size_t h3 = hash<float>()(s.c[2]);
|
|
||||||
size_t h4 = hash<float>()(s.c[3]);
|
|
||||||
return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
#endif // KRAKEN_QUATERNION_H
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
//
|
|
||||||
// KRFloat.h
|
|
||||||
// Kraken
|
|
||||||
//
|
|
||||||
// Copyright 2018 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.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRAKEN_SCALAR_H
|
|
||||||
#define KRAKEN_SCALAR_H
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
float SmoothStep(float a, float b, float t);
|
|
||||||
|
|
||||||
}; // namespace kraken
|
|
||||||
|
|
||||||
#endif // KRAKEN_SCALAR_H
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
//
|
|
||||||
// KRTriangle.h
|
|
||||||
// Kraken
|
|
||||||
//
|
|
||||||
// Copyright 2018 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.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRAKEN_TRIANGLE3_H
|
|
||||||
#define KRAKEN_TRIANGLE3_H
|
|
||||||
|
|
||||||
#include "vector3.h"
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
class Triangle3
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Vector3 vert[3];
|
|
||||||
|
|
||||||
Triangle3(const Triangle3 &tri);
|
|
||||||
Triangle3(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3);
|
|
||||||
~Triangle3();
|
|
||||||
|
|
||||||
Vector3 calculateNormal() const;
|
|
||||||
|
|
||||||
bool operator ==(const Triangle3& b) const;
|
|
||||||
bool operator !=(const Triangle3& b) const;
|
|
||||||
Triangle3& operator =(const Triangle3& b);
|
|
||||||
Vector3& operator[](unsigned int i);
|
|
||||||
Vector3 operator[](unsigned int i) const;
|
|
||||||
|
|
||||||
bool rayCast(const Vector3 &start, const Vector3 &dir, Vector3 &hit_point) const;
|
|
||||||
bool sphereCast(const Vector3 &start, const Vector3 &dir, float radius, Vector3 &hit_point, float &hit_distance) const;
|
|
||||||
|
|
||||||
bool containsPoint(const Vector3 &p) const;
|
|
||||||
Vector3 closestPointOnTriangle(const Vector3 &p) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace kraken
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template<>
|
|
||||||
struct hash<kraken::Triangle3> {
|
|
||||||
public:
|
|
||||||
size_t operator()(const kraken::Triangle3 &s) const
|
|
||||||
{
|
|
||||||
size_t h1 = hash<kraken::Vector3>()(s.vert[0]);
|
|
||||||
size_t h2 = hash<kraken::Vector3>()(s.vert[1]);
|
|
||||||
size_t h3 = hash<kraken::Vector3>()(s.vert[2]);
|
|
||||||
return h1 ^ (h2 << 1) ^ (h3 << 2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
#endif // KRAKEN_TRIANGLE3_H
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
//
|
|
||||||
// vector2.h
|
|
||||||
// Kraken
|
|
||||||
//
|
|
||||||
// Copyright 2018 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.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRAKEN_VECTOR2_H
|
|
||||||
#define KRAKEN_VECTOR2_H
|
|
||||||
|
|
||||||
#include <functional> // for hash<>
|
|
||||||
#include <limits> // for std::numeric_limits<>
|
|
||||||
#include <math.h> // for sqrtf
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
class Vector2 {
|
|
||||||
|
|
||||||
public:
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
float x, y;
|
|
||||||
};
|
|
||||||
float c[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
Vector2();
|
|
||||||
Vector2(float X, float Y);
|
|
||||||
Vector2(float v);
|
|
||||||
Vector2(float *v);
|
|
||||||
Vector2(const Vector2 &v);
|
|
||||||
~Vector2();
|
|
||||||
|
|
||||||
// Vector2 swizzle getters
|
|
||||||
Vector2 yx() const;
|
|
||||||
|
|
||||||
// Vector2 swizzle setters
|
|
||||||
void yx(const Vector2 &v);
|
|
||||||
|
|
||||||
Vector2& operator =(const Vector2& b);
|
|
||||||
Vector2 operator +(const Vector2& b) const;
|
|
||||||
Vector2 operator -(const Vector2& b) const;
|
|
||||||
Vector2 operator +() const;
|
|
||||||
Vector2 operator -() const;
|
|
||||||
Vector2 operator *(const float v) const;
|
|
||||||
Vector2 operator /(const float v) const;
|
|
||||||
|
|
||||||
Vector2& operator +=(const Vector2& b);
|
|
||||||
Vector2& operator -=(const Vector2& b);
|
|
||||||
Vector2& operator *=(const float v);
|
|
||||||
Vector2& operator /=(const float v);
|
|
||||||
|
|
||||||
// Comparison operators are implemented to allow insertion into sorted containers such as std::set
|
|
||||||
bool operator >(const Vector2& b) const;
|
|
||||||
bool operator <(const Vector2& b) const;
|
|
||||||
|
|
||||||
bool operator ==(const Vector2& b) const;
|
|
||||||
bool operator !=(const Vector2& b) const;
|
|
||||||
|
|
||||||
float& operator[](unsigned i);
|
|
||||||
float operator[](unsigned i) const;
|
|
||||||
|
|
||||||
float sqrMagnitude() const;
|
|
||||||
float magnitude() const;
|
|
||||||
|
|
||||||
void normalize();
|
|
||||||
static Vector2 Normalize(const Vector2 &v);
|
|
||||||
|
|
||||||
static float Cross(const Vector2 &v1, const Vector2 &v2);
|
|
||||||
|
|
||||||
static float Dot(const Vector2 &v1, const Vector2 &v2);
|
|
||||||
static Vector2 Min();
|
|
||||||
static Vector2 Max();
|
|
||||||
static Vector2 Zero();
|
|
||||||
static Vector2 One();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace kraken
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template<>
|
|
||||||
struct hash<kraken::Vector2> {
|
|
||||||
public:
|
|
||||||
size_t operator()(const kraken::Vector2 &s) const
|
|
||||||
{
|
|
||||||
size_t h1 = hash<float>()(s.x);
|
|
||||||
size_t h2 = hash<float>()(s.y);
|
|
||||||
return h1 ^ (h2 << 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
#endif // KRAKEN_VECTOR2_H
|
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
//
|
|
||||||
// Vector3.h
|
|
||||||
// Kraken
|
|
||||||
//
|
|
||||||
// Copyright 2018 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.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRAKEN_VECTOR3_H
|
|
||||||
#define KRAKEN_VECTOR3_H
|
|
||||||
|
|
||||||
#include <functional> // for hash<>
|
|
||||||
|
|
||||||
#include "vector2.h"
|
|
||||||
#include "vector4.h"
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
class Vector3 {
|
|
||||||
|
|
||||||
public:
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
float x, y, z;
|
|
||||||
};
|
|
||||||
float c[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
Vector3();
|
|
||||||
Vector3(float X, float Y, float Z);
|
|
||||||
Vector3(float v);
|
|
||||||
Vector3(float *v);
|
|
||||||
Vector3(double *v);
|
|
||||||
Vector3(const Vector3 &v);
|
|
||||||
Vector3(const Vector4 &v);
|
|
||||||
~Vector3();
|
|
||||||
|
|
||||||
// Vector2 swizzle getters
|
|
||||||
Vector2 xx() const;
|
|
||||||
Vector2 xy() const;
|
|
||||||
Vector2 xz() const;
|
|
||||||
Vector2 yx() const;
|
|
||||||
Vector2 yy() const;
|
|
||||||
Vector2 yz() const;
|
|
||||||
Vector2 zx() const;
|
|
||||||
Vector2 zy() const;
|
|
||||||
Vector2 zz() const;
|
|
||||||
|
|
||||||
// Vector2 swizzle setters
|
|
||||||
void xy(const Vector2 &v);
|
|
||||||
void xz(const Vector2 &v);
|
|
||||||
void yx(const Vector2 &v);
|
|
||||||
void yz(const Vector2 &v);
|
|
||||||
void zx(const Vector2 &v);
|
|
||||||
void zy(const Vector2 &v);
|
|
||||||
|
|
||||||
Vector3& operator =(const Vector3& b);
|
|
||||||
Vector3& operator =(const Vector4& b);
|
|
||||||
Vector3 operator +(const Vector3& b) const;
|
|
||||||
Vector3 operator -(const Vector3& b) const;
|
|
||||||
Vector3 operator +() const;
|
|
||||||
Vector3 operator -() const;
|
|
||||||
Vector3 operator *(const float v) const;
|
|
||||||
Vector3 operator /(const float v) const;
|
|
||||||
|
|
||||||
Vector3& operator +=(const Vector3& b);
|
|
||||||
Vector3& operator -=(const Vector3& b);
|
|
||||||
Vector3& operator *=(const float v);
|
|
||||||
Vector3& operator /=(const float v);
|
|
||||||
|
|
||||||
bool operator ==(const Vector3& b) const;
|
|
||||||
bool operator !=(const Vector3& b) const;
|
|
||||||
|
|
||||||
// Comparison operators are implemented to allow insertion into sorted containers such as std::set
|
|
||||||
bool operator >(const Vector3& b) const;
|
|
||||||
bool operator <(const Vector3& b) const;
|
|
||||||
|
|
||||||
float& operator[](unsigned i);
|
|
||||||
float operator[](unsigned i) const;
|
|
||||||
|
|
||||||
float sqrMagnitude() const; // calculate the square of the magnitude (useful for comparison of magnitudes without the cost of a sqrt() function)
|
|
||||||
float magnitude() const;
|
|
||||||
|
|
||||||
void scale(const Vector3 &v);
|
|
||||||
void normalize();
|
|
||||||
static Vector3 Normalize(const Vector3 &v);
|
|
||||||
|
|
||||||
static Vector3 Cross(const Vector3 &v1, const Vector3 &v2);
|
|
||||||
|
|
||||||
static float Dot(const Vector3 &v1, const Vector3 &v2);
|
|
||||||
static Vector3 Min();
|
|
||||||
static Vector3 Max();
|
|
||||||
static const Vector3 &Zero();
|
|
||||||
static Vector3 One();
|
|
||||||
static Vector3 Forward();
|
|
||||||
static Vector3 Backward();
|
|
||||||
static Vector3 Up();
|
|
||||||
static Vector3 Down();
|
|
||||||
static Vector3 Left();
|
|
||||||
static Vector3 Right();
|
|
||||||
static Vector3 Scale(const Vector3 &v1, const Vector3 &v2);
|
|
||||||
static Vector3 Lerp(const Vector3 &v1, const Vector3 &v2, float d);
|
|
||||||
static Vector3 Slerp(const Vector3 &v1, const Vector3 &v2, float d);
|
|
||||||
static void OrthoNormalize(Vector3 &normal, Vector3 &tangent); // Gram-Schmidt Orthonormalization
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace kraken
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template<>
|
|
||||||
struct hash<kraken::Vector3> {
|
|
||||||
public:
|
|
||||||
size_t operator()(const kraken::Vector3 &s) const
|
|
||||||
{
|
|
||||||
size_t h1 = hash<float>()(s.x);
|
|
||||||
size_t h2 = hash<float>()(s.y);
|
|
||||||
size_t h3 = hash<float>()(s.z);
|
|
||||||
return h1 ^ (h2 << 1) ^ (h3 << 2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
#endif // KRAKEN_VECTOR3_H
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
//
|
|
||||||
// Vector4.h
|
|
||||||
// Kraken
|
|
||||||
//
|
|
||||||
// Copyright 2018 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.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRAKEN_VECTOR4_H
|
|
||||||
#define KRAKEN_VECTOR4_H
|
|
||||||
|
|
||||||
#include <functional> // for hash<>
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
class Vector3;
|
|
||||||
|
|
||||||
class Vector4 {
|
|
||||||
|
|
||||||
public:
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
float x, y, z, w;
|
|
||||||
};
|
|
||||||
float c[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
Vector4();
|
|
||||||
Vector4(float X, float Y, float Z, float W);
|
|
||||||
Vector4(float v);
|
|
||||||
Vector4(float *v);
|
|
||||||
Vector4(const Vector4 &v);
|
|
||||||
Vector4(const Vector3 &v, float W);
|
|
||||||
~Vector4();
|
|
||||||
|
|
||||||
|
|
||||||
Vector4& operator =(const Vector4& b);
|
|
||||||
Vector4 operator +(const Vector4& b) const;
|
|
||||||
Vector4 operator -(const Vector4& b) const;
|
|
||||||
Vector4 operator +() const;
|
|
||||||
Vector4 operator -() const;
|
|
||||||
Vector4 operator *(const float v) const;
|
|
||||||
Vector4 operator /(const float v) const;
|
|
||||||
|
|
||||||
Vector4& operator +=(const Vector4& b);
|
|
||||||
Vector4& operator -=(const Vector4& b);
|
|
||||||
Vector4& operator *=(const float v);
|
|
||||||
Vector4& operator /=(const float v);
|
|
||||||
|
|
||||||
bool operator ==(const Vector4& b) const;
|
|
||||||
bool operator !=(const Vector4& b) const;
|
|
||||||
|
|
||||||
// Comparison operators are implemented to allow insertion into sorted containers such as std::set
|
|
||||||
bool operator >(const Vector4& b) const;
|
|
||||||
bool operator <(const Vector4& b) const;
|
|
||||||
|
|
||||||
float& operator[](unsigned i);
|
|
||||||
float operator[](unsigned i) const;
|
|
||||||
|
|
||||||
float sqrMagnitude() const; // calculate the square of the magnitude (useful for comparison of magnitudes without the cost of a sqrt() function)
|
|
||||||
float magnitude() const;
|
|
||||||
|
|
||||||
void normalize();
|
|
||||||
static Vector4 Normalize(const Vector4 &v);
|
|
||||||
|
|
||||||
static float Dot(const Vector4 &v1, const Vector4 &v2);
|
|
||||||
static Vector4 Min();
|
|
||||||
static Vector4 Max();
|
|
||||||
static const Vector4 &Zero();
|
|
||||||
static Vector4 One();
|
|
||||||
static Vector4 Forward();
|
|
||||||
static Vector4 Backward();
|
|
||||||
static Vector4 Up();
|
|
||||||
static Vector4 Down();
|
|
||||||
static Vector4 Left();
|
|
||||||
static Vector4 Right();
|
|
||||||
static Vector4 Lerp(const Vector4 &v1, const Vector4 &v2, float d);
|
|
||||||
static Vector4 Slerp(const Vector4 &v1, const Vector4 &v2, float d);
|
|
||||||
static void OrthoNormalize(Vector4 &normal, Vector4 &tangent); // Gram-Schmidt Orthonormalization
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace kraken
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template<>
|
|
||||||
struct hash<kraken::Vector4> {
|
|
||||||
public:
|
|
||||||
size_t operator()(const kraken::Vector4 &s) const
|
|
||||||
{
|
|
||||||
size_t h1 = hash<float>()(s.x);
|
|
||||||
size_t h2 = hash<float>()(s.y);
|
|
||||||
size_t h3 = hash<float>()(s.z);
|
|
||||||
size_t h4 = hash<float>()(s.w);
|
|
||||||
return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
#endif // KRAKEN_VECTOR4_H
|
|
||||||
@@ -1,365 +0,0 @@
|
|||||||
//
|
|
||||||
// Quaternion.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 "public/kraken.h"
|
|
||||||
|
|
||||||
#include "KRHelpers.h"
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
Quaternion::Quaternion() {
|
|
||||||
c[0] = 1.0;
|
|
||||||
c[1] = 0.0;
|
|
||||||
c[2] = 0.0;
|
|
||||||
c[3] = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion::Quaternion(float w, float x, float y, float z) {
|
|
||||||
c[0] = w;
|
|
||||||
c[1] = x;
|
|
||||||
c[2] = y;
|
|
||||||
c[3] = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion::Quaternion(const Quaternion& p) {
|
|
||||||
c[0] = p[0];
|
|
||||||
c[1] = p[1];
|
|
||||||
c[2] = p[2];
|
|
||||||
c[3] = p[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion& Quaternion::operator =( const Quaternion& p ) {
|
|
||||||
c[0] = p[0];
|
|
||||||
c[1] = p[1];
|
|
||||||
c[2] = p[2];
|
|
||||||
c[3] = p[3];
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion::Quaternion(const Vector3 &euler) {
|
|
||||||
setEulerZYX(euler);
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion::Quaternion(const Vector3 &from_vector, const Vector3 &to_vector) {
|
|
||||||
|
|
||||||
Vector3 a = Vector3::Cross(from_vector, to_vector);
|
|
||||||
c[0] = a[0];
|
|
||||||
c[1] = a[1];
|
|
||||||
c[2] = a[2];
|
|
||||||
c[3] = sqrt(from_vector.sqrMagnitude() * to_vector.sqrMagnitude()) + Vector3::Dot(from_vector, to_vector);
|
|
||||||
normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion::~Quaternion() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Quaternion::setEulerXYZ(const Vector3 &euler)
|
|
||||||
{
|
|
||||||
*this = Quaternion::FromAngleAxis(Vector3(1.0f, 0.0f, 0.0f), euler.x)
|
|
||||||
* Quaternion::FromAngleAxis(Vector3(0.0f, 1.0f, 0.0f), euler.y)
|
|
||||||
* Quaternion::FromAngleAxis(Vector3(0.0f, 0.0f, 1.0f), euler.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Quaternion::setEulerZYX(const Vector3 &euler) {
|
|
||||||
// ZYX Order!
|
|
||||||
float c1 = cos(euler[0] * 0.5f);
|
|
||||||
float c2 = cos(euler[1] * 0.5f);
|
|
||||||
float c3 = cos(euler[2] * 0.5f);
|
|
||||||
float s1 = sin(euler[0] * 0.5f);
|
|
||||||
float s2 = sin(euler[1] * 0.5f);
|
|
||||||
float s3 = sin(euler[2] * 0.5f);
|
|
||||||
|
|
||||||
c[0] = c1 * c2 * c3 + s1 * s2 * s3;
|
|
||||||
c[1] = s1 * c2 * c3 - c1 * s2 * s3;
|
|
||||||
c[2] = c1 * s2 * c3 + s1 * c2 * s3;
|
|
||||||
c[3] = c1 * c2 * s3 - s1 * s2 * c3;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Quaternion::operator [](unsigned i) const {
|
|
||||||
return c[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
float &Quaternion::operator [](unsigned i) {
|
|
||||||
return c[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Quaternion::eulerXYZ() const {
|
|
||||||
double a2 = 2 * (c[0] * c[2] - c[1] * c[3]);
|
|
||||||
if(a2 <= -0.99999) {
|
|
||||||
return Vector3(
|
|
||||||
2.0 * atan2(c[1], c[0]),
|
|
||||||
-PI * 0.5f,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
} else if(a2 >= 0.99999) {
|
|
||||||
return Vector3(
|
|
||||||
2.0 * atan2(c[1], c[0]),
|
|
||||||
PI * 0.5f,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Vector3(
|
|
||||||
atan2(2 * (c[0] * c[1] + c[2] * c[3]), (1 - 2 * (c[1] * c[1] + c[2] * c[2]))),
|
|
||||||
asin(a2),
|
|
||||||
atan2(2 * (c[0] * c[3] + c[1] * c[2]), (1 - 2 * (c[2] * c[2] + c[3] * c[3])))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator ==(Quaternion &v1, Quaternion &v2) {
|
|
||||||
return
|
|
||||||
v1[0] == v2[0]
|
|
||||||
&& v1[1] == v2[1]
|
|
||||||
&& v1[2] == v2[2]
|
|
||||||
&& v1[3] == v2[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator !=(Quaternion &v1, Quaternion &v2) {
|
|
||||||
return
|
|
||||||
v1[0] != v2[0]
|
|
||||||
|| v1[1] != v2[1]
|
|
||||||
|| v1[2] != v2[2]
|
|
||||||
|| v1[3] != v2[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion Quaternion::operator *(const Quaternion &v) {
|
|
||||||
float t0 = (c[3]-c[2])*(v[2]-v[3]);
|
|
||||||
float t1 = (c[0]+c[1])*(v[0]+v[1]);
|
|
||||||
float t2 = (c[0]-c[1])*(v[2]+v[3]);
|
|
||||||
float t3 = (c[3]+c[2])*(v[0]-v[1]);
|
|
||||||
float t4 = (c[3]-c[1])*(v[1]-v[2]);
|
|
||||||
float t5 = (c[3]+c[1])*(v[1]+v[2]);
|
|
||||||
float t6 = (c[0]+c[2])*(v[0]-v[3]);
|
|
||||||
float t7 = (c[0]-c[2])*(v[0]+v[3]);
|
|
||||||
float t8 = t5+t6+t7;
|
|
||||||
float t9 = (t4+t8)/2;
|
|
||||||
|
|
||||||
return Quaternion(
|
|
||||||
t0+t9-t5,
|
|
||||||
t1+t9-t8,
|
|
||||||
t2+t9-t7,
|
|
||||||
t3+t9-t6
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion Quaternion::operator *(float v) const {
|
|
||||||
return Quaternion(c[0] * v, c[1] * v, c[2] * v, c[3] * v);
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion Quaternion::operator /(float num) const {
|
|
||||||
float inv_num = 1.0f / num;
|
|
||||||
return Quaternion(c[0] * inv_num, c[1] * inv_num, c[2] * inv_num, c[3] * inv_num);
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion Quaternion::operator +(const Quaternion &v) const {
|
|
||||||
return Quaternion(c[0] + v[0], c[1] + v[1], c[2] + v[2], c[3] + v[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion Quaternion::operator -(const Quaternion &v) const {
|
|
||||||
return Quaternion(c[0] - v[0], c[1] - v[1], c[2] - v[2], c[3] - v[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion& Quaternion::operator +=(const Quaternion& v) {
|
|
||||||
c[0] += v[0];
|
|
||||||
c[1] += v[1];
|
|
||||||
c[2] += v[2];
|
|
||||||
c[3] += v[3];
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion& Quaternion::operator -=(const Quaternion& v) {
|
|
||||||
c[0] -= v[0];
|
|
||||||
c[1] -= v[1];
|
|
||||||
c[2] -= v[2];
|
|
||||||
c[3] -= v[3];
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion& Quaternion::operator *=(const Quaternion& v) {
|
|
||||||
float t0 = (c[3]-c[2])*(v[2]-v[3]);
|
|
||||||
float t1 = (c[0]+c[1])*(v[0]+v[1]);
|
|
||||||
float t2 = (c[0]-c[1])*(v[2]+v[3]);
|
|
||||||
float t3 = (c[3]+c[2])*(v[0]-v[1]);
|
|
||||||
float t4 = (c[3]-c[1])*(v[1]-v[2]);
|
|
||||||
float t5 = (c[3]+c[1])*(v[1]+v[2]);
|
|
||||||
float t6 = (c[0]+c[2])*(v[0]-v[3]);
|
|
||||||
float t7 = (c[0]-c[2])*(v[0]+v[3]);
|
|
||||||
float t8 = t5+t6+t7;
|
|
||||||
float t9 = (t4+t8)/2;
|
|
||||||
|
|
||||||
c[0] = t0+t9-t5;
|
|
||||||
c[1] = t1+t9-t8;
|
|
||||||
c[2] = t2+t9-t7;
|
|
||||||
c[3] = t3+t9-t6;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion& Quaternion::operator *=(const float& v) {
|
|
||||||
c[0] *= v;
|
|
||||||
c[1] *= v;
|
|
||||||
c[2] *= v;
|
|
||||||
c[3] *= v;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion& Quaternion::operator /=(const float& v) {
|
|
||||||
float inv_v = 1.0f / v;
|
|
||||||
c[0] *= inv_v;
|
|
||||||
c[1] *= inv_v;
|
|
||||||
c[2] *= inv_v;
|
|
||||||
c[3] *= inv_v;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion Quaternion::operator +() const {
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion Quaternion::operator -() const {
|
|
||||||
return Quaternion(-c[0], -c[1], -c[2], -c[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion Normalize(const Quaternion &v1) {
|
|
||||||
float inv_magnitude = 1.0f / sqrtf(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2] + v1[3] * v1[3]);
|
|
||||||
return Quaternion(
|
|
||||||
v1[0] * inv_magnitude,
|
|
||||||
v1[1] * inv_magnitude,
|
|
||||||
v1[2] * inv_magnitude,
|
|
||||||
v1[3] * inv_magnitude
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Quaternion::normalize() {
|
|
||||||
float inv_magnitude = 1.0f / sqrtf(c[0] * c[0] + c[1] * c[1] + c[2] * c[2] + c[3] * c[3]);
|
|
||||||
c[0] *= inv_magnitude;
|
|
||||||
c[1] *= inv_magnitude;
|
|
||||||
c[2] *= inv_magnitude;
|
|
||||||
c[3] *= inv_magnitude;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion Conjugate(const Quaternion &v1) {
|
|
||||||
return Quaternion(v1[0], -v1[1], -v1[2], -v1[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Quaternion::conjugate() {
|
|
||||||
c[1] = -c[1];
|
|
||||||
c[2] = -c[2];
|
|
||||||
c[3] = -c[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix4 Quaternion::rotationMatrix() const {
|
|
||||||
Matrix4 matRotate;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Vector3 euler = eulerXYZ();
|
|
||||||
|
|
||||||
matRotate.rotate(euler.x, X_AXIS);
|
|
||||||
matRotate.rotate(euler.y, Y_AXIS);
|
|
||||||
matRotate.rotate(euler.z, Z_AXIS);
|
|
||||||
*/
|
|
||||||
|
|
||||||
// FINDME - Determine why the more optimal routine commented below wasn't working
|
|
||||||
|
|
||||||
|
|
||||||
matRotate.c[0] = 1.0 - 2.0 * (c[2] * c[2] + c[3] * c[3]);
|
|
||||||
matRotate.c[1] = 2.0 * (c[1] * c[2] - c[0] * c[3]);
|
|
||||||
matRotate.c[2] = 2.0 * (c[0] * c[2] + c[1] * c[3]);
|
|
||||||
|
|
||||||
matRotate.c[4] = 2.0 * (c[1] * c[2] + c[0] * c[3]);
|
|
||||||
matRotate.c[5] = 1.0 - 2.0 * (c[1] * c[1] + c[3] * c[3]);
|
|
||||||
matRotate.c[6] = 2.0 * (c[2] * c[3] - c[0] * c[1]);
|
|
||||||
|
|
||||||
matRotate.c[8] = 2.0 * (c[1] * c[3] - c[0] * c[2]);
|
|
||||||
matRotate.c[9] = 2.0 * (c[0] * c[1] + c[2] * c[3]);
|
|
||||||
matRotate.c[10] = 1.0 - 2.0 * (c[1] * c[1] + c[2] * c[2]);
|
|
||||||
|
|
||||||
return matRotate;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Quaternion Quaternion::FromAngleAxis(const Vector3 &axis, float angle)
|
|
||||||
{
|
|
||||||
float ha = angle * 0.5f;
|
|
||||||
float sha = sin(ha);
|
|
||||||
return Quaternion(cos(ha), axis.x * sha, axis.y * sha, axis.z * sha);
|
|
||||||
}
|
|
||||||
|
|
||||||
float Quaternion::Dot(const Quaternion &v1, const Quaternion &v2)
|
|
||||||
{
|
|
||||||
return v1.c[0] * v2.c[0] + v1.c[1] * v2.c[1] + v1.c[2] * v2.c[2] + v1.c[3] * v2.c[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion Quaternion::Lerp(const Quaternion &a, const Quaternion &b, float t)
|
|
||||||
{
|
|
||||||
if (t <= 0.0f) {
|
|
||||||
return a;
|
|
||||||
} else if (t >= 1.0f) {
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
return a * (1.0f - t) + b * t;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion Quaternion::Slerp(const Quaternion &a, const Quaternion &b, float t)
|
|
||||||
{
|
|
||||||
if (t <= 0.0f) {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t >= 1.0f) {
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
float coshalftheta = Dot(a, b);
|
|
||||||
Quaternion c = a;
|
|
||||||
|
|
||||||
// Angle is greater than 180. We can negate the angle/quat to get the
|
|
||||||
// shorter rotation to reach the same destination.
|
|
||||||
if ( coshalftheta < 0.0f ) {
|
|
||||||
coshalftheta = -coshalftheta;
|
|
||||||
c = -c;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( coshalftheta > (1.0f - std::numeric_limits<float>::epsilon())) {
|
|
||||||
// Angle is tiny - save some computation by lerping instead.
|
|
||||||
return Lerp(c, b, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
float halftheta = acos(coshalftheta);
|
|
||||||
|
|
||||||
return (c * sin((1.0f - t) * halftheta) + b * sin(t * halftheta)) / sin(halftheta);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace kraken
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
//
|
|
||||||
// KRFloat.cpp
|
|
||||||
// Kraken
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 2013-05-03.
|
|
||||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "public/kraken.h"
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
float SmoothStep(float a, float b, float t)
|
|
||||||
{
|
|
||||||
float d = (3.0 * t * t - 2.0 * t * t * t);
|
|
||||||
return a * (1.0f - d) + b * d;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace kraken
|
|
||||||
@@ -1,331 +0,0 @@
|
|||||||
//
|
|
||||||
// KRTriangle.cpp
|
|
||||||
// Kraken
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 2/8/2014.
|
|
||||||
// Copyright (c) 2014 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "public/kraken.h"
|
|
||||||
|
|
||||||
using namespace kraken;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
bool _intersectSphere(const Vector3 &start, const Vector3 &dir, const Vector3 &sphere_center, float sphere_radius, float &distance)
|
|
||||||
{
|
|
||||||
// dir must be normalized
|
|
||||||
|
|
||||||
// From: http://archive.gamedev.net/archive/reference/articles/article1026.html
|
|
||||||
|
|
||||||
// TODO - Move to another class?
|
|
||||||
Vector3 Q = sphere_center - start;
|
|
||||||
float c = Q.magnitude();
|
|
||||||
float v = Vector3::Dot(Q, dir);
|
|
||||||
float d = sphere_radius * sphere_radius - (c * c - v * v);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (d < 0.0) {
|
|
||||||
// No intersection
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the distance to the [first] intersecting point
|
|
||||||
|
|
||||||
distance = v - sqrt(d);
|
|
||||||
if (distance < 0.0f) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _sameSide(const Vector3 &p1, const Vector3 &p2, const Vector3 &a, const Vector3 &b)
|
|
||||||
{
|
|
||||||
// TODO - Move to Vector3 class?
|
|
||||||
// From: http://stackoverflow.com/questions/995445/determine-if-a-3d-point-is-within-a-triangle
|
|
||||||
|
|
||||||
Vector3 cp1 = Vector3::Cross(b - a, p1 - a);
|
|
||||||
Vector3 cp2 = Vector3::Cross(b - a, p2 - a);
|
|
||||||
if (Vector3::Dot(cp1, cp2) >= 0) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 _closestPointOnLine(const Vector3 &a, const Vector3 &b, const Vector3 &p)
|
|
||||||
{
|
|
||||||
// From: http://stackoverflow.com/questions/995445/determine-if-a-3d-point-is-within-a-triangle
|
|
||||||
|
|
||||||
// Determine t (the length of the vector from ‘a’ to ‘p’)
|
|
||||||
|
|
||||||
Vector3 c = p - a;
|
|
||||||
Vector3 V = Vector3::Normalize(b - a);
|
|
||||||
float d = (a - b).magnitude();
|
|
||||||
float t = Vector3::Dot(V, c);
|
|
||||||
|
|
||||||
// Check to see if ‘t’ is beyond the extents of the line segment
|
|
||||||
|
|
||||||
if (t < 0) return a;
|
|
||||||
if (t > d) return b;
|
|
||||||
|
|
||||||
// Return the point between ‘a’ and ‘b’
|
|
||||||
|
|
||||||
return a + V * t;
|
|
||||||
}
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
Triangle3::Triangle3(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3)
|
|
||||||
{
|
|
||||||
vert[0] = v1;
|
|
||||||
vert[1] = v2;
|
|
||||||
vert[2] = v3;
|
|
||||||
}
|
|
||||||
|
|
||||||
Triangle3::Triangle3(const Triangle3 &tri)
|
|
||||||
{
|
|
||||||
vert[0] = tri[0];
|
|
||||||
vert[1] = tri[1];
|
|
||||||
vert[3] = tri[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Triangle3::~Triangle3()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Triangle3::operator ==(const Triangle3& b) const
|
|
||||||
{
|
|
||||||
return vert[0] == b[0] && vert[1] == b[1] && vert[2] == b[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Triangle3::operator !=(const Triangle3& b) const
|
|
||||||
{
|
|
||||||
return vert[0] != b[0] || vert[1] != b[1] || vert[2] != b[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
Triangle3& Triangle3::operator =(const Triangle3& b)
|
|
||||||
{
|
|
||||||
|
|
||||||
vert[0] = b[0];
|
|
||||||
vert[1] = b[1];
|
|
||||||
vert[3] = b[3];
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3& Triangle3::operator[](unsigned int i)
|
|
||||||
{
|
|
||||||
return vert[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Triangle3::operator[](unsigned int i) const
|
|
||||||
{
|
|
||||||
return vert[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Triangle3::rayCast(const Vector3 &start, const Vector3 &dir, Vector3 &hit_point) const
|
|
||||||
{
|
|
||||||
// algorithm based on Dan Sunday's implementation at http://geomalgorithms.com/a06-_intersect-2.html
|
|
||||||
const float SMALL_NUM = 0.00000001; // anything that avoids division overflow
|
|
||||||
Vector3 u, v, n; // triangle vectors
|
|
||||||
Vector3 w0, w; // ray vectors
|
|
||||||
float r, a, b; // params to calc ray-plane intersect
|
|
||||||
|
|
||||||
// get triangle edge vectors and plane normal
|
|
||||||
u = vert[1] - vert[0];
|
|
||||||
v = vert[2] - vert[0];
|
|
||||||
n = Vector3::Cross(u, v); // cross product
|
|
||||||
if (n == Vector3::Zero()) // triangle is degenerate
|
|
||||||
return false; // do not deal with this case
|
|
||||||
|
|
||||||
w0 = start - vert[0];
|
|
||||||
a = -Vector3::Dot(n, w0);
|
|
||||||
b = Vector3::Dot(n,dir);
|
|
||||||
if (fabs(b) < SMALL_NUM) { // ray is parallel to triangle plane
|
|
||||||
if (a == 0)
|
|
||||||
return false; // ray lies in triangle plane
|
|
||||||
else {
|
|
||||||
return false; // ray disjoint from plane
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get intersect point of ray with triangle plane
|
|
||||||
r = a / b;
|
|
||||||
if (r < 0.0) // ray goes away from triangle
|
|
||||||
return false; // => no intersect
|
|
||||||
// for a segment, also test if (r > 1.0) => no intersect
|
|
||||||
|
|
||||||
|
|
||||||
Vector3 plane_hit_point = start + dir * r; // intersect point of ray and plane
|
|
||||||
|
|
||||||
// is plane_hit_point inside triangle?
|
|
||||||
float uu, uv, vv, wu, wv, D;
|
|
||||||
uu = Vector3::Dot(u,u);
|
|
||||||
uv = Vector3::Dot(u,v);
|
|
||||||
vv = Vector3::Dot(v,v);
|
|
||||||
w = plane_hit_point - vert[0];
|
|
||||||
wu = Vector3::Dot(w,u);
|
|
||||||
wv = Vector3::Dot(w,v);
|
|
||||||
D = uv * uv - uu * vv;
|
|
||||||
|
|
||||||
// get and test parametric coords
|
|
||||||
float s, t;
|
|
||||||
s = (uv * wv - vv * wu) / D;
|
|
||||||
if (s < 0.0 || s > 1.0) // plane_hit_point is outside triangle
|
|
||||||
return false;
|
|
||||||
t = (uv * wu - uu * wv) / D;
|
|
||||||
if (t < 0.0 || (s + t) > 1.0) // plane_hit_point is outside triangle
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// plane_hit_point is inside the triangle
|
|
||||||
hit_point = plane_hit_point;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Triangle3::calculateNormal() const
|
|
||||||
{
|
|
||||||
Vector3 v1 = vert[1] - vert[0];
|
|
||||||
Vector3 v2 = vert[2] - vert[0];
|
|
||||||
|
|
||||||
return Vector3::Normalize(Vector3::Cross(v1, v2));
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Triangle3::closestPointOnTriangle(const Vector3 &p) const
|
|
||||||
{
|
|
||||||
Vector3 a = vert[0];
|
|
||||||
Vector3 b = vert[1];
|
|
||||||
Vector3 c = vert[2];
|
|
||||||
|
|
||||||
Vector3 Rab = _closestPointOnLine(a, b, p);
|
|
||||||
Vector3 Rbc = _closestPointOnLine(b, c, p);
|
|
||||||
Vector3 Rca = _closestPointOnLine(c, a, p);
|
|
||||||
|
|
||||||
// return closest [Rab, Rbc, Rca] to p;
|
|
||||||
float sd_Rab = (p - Rab).sqrMagnitude();
|
|
||||||
float sd_Rbc = (p - Rbc).sqrMagnitude();
|
|
||||||
float sd_Rca = (p - Rca).sqrMagnitude();
|
|
||||||
|
|
||||||
if(sd_Rab < sd_Rbc && sd_Rab < sd_Rca) {
|
|
||||||
return Rab;
|
|
||||||
} else if(sd_Rbc < sd_Rab && sd_Rbc < sd_Rca) {
|
|
||||||
return Rbc;
|
|
||||||
} else {
|
|
||||||
return Rca;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Triangle3::sphereCast(const Vector3 &start, const Vector3 &dir, float radius, Vector3 &hit_point, float &hit_distance) const
|
|
||||||
{
|
|
||||||
// Dir must be normalized
|
|
||||||
const float SMALL_NUM = 0.001f; // anything that avoids division overflow
|
|
||||||
|
|
||||||
Vector3 tri_normal = calculateNormal();
|
|
||||||
|
|
||||||
float d = Vector3::Dot(tri_normal, vert[0]);
|
|
||||||
float e = Vector3::Dot(tri_normal, start) - radius;
|
|
||||||
float cotangent_distance = e - d;
|
|
||||||
|
|
||||||
Vector3 plane_intersect;
|
|
||||||
float plane_intersect_distance;
|
|
||||||
|
|
||||||
float denom = Vector3::Dot(tri_normal, dir);
|
|
||||||
|
|
||||||
if(denom > -SMALL_NUM) {
|
|
||||||
return false; // dir is co-planar with the triangle or going in the direction of the normal; no intersection
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect an embedded plane, caused by a sphere that is already intersecting the plane.
|
|
||||||
if(cotangent_distance <= 0 && cotangent_distance >= -radius * 2.0f) {
|
|
||||||
// Embedded plane - Sphere is already intersecting the plane.
|
|
||||||
// Use the point closest to the origin of the sphere as the intersection
|
|
||||||
plane_intersect = start - tri_normal * (cotangent_distance + radius);
|
|
||||||
plane_intersect_distance = 0.0f;
|
|
||||||
} else {
|
|
||||||
// Sphere is not intersecting the plane
|
|
||||||
// Determine the first point hit by the swept sphere on the triangle's plane
|
|
||||||
|
|
||||||
plane_intersect_distance = -(cotangent_distance / denom);
|
|
||||||
plane_intersect = start + dir * plane_intersect_distance - tri_normal * radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(plane_intersect_distance < 0.0f) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(containsPoint(plane_intersect)) {
|
|
||||||
// Triangle contains point
|
|
||||||
hit_point = plane_intersect;
|
|
||||||
hit_distance = plane_intersect_distance;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// Triangle does not contain point, cast ray back to sphere from closest point on triangle edge or vertice
|
|
||||||
Vector3 closest_point = closestPointOnTriangle(plane_intersect);
|
|
||||||
float reverse_hit_distance;
|
|
||||||
if(_intersectSphere(closest_point, -dir, start, radius, reverse_hit_distance)) {
|
|
||||||
// Reverse cast hit sphere
|
|
||||||
hit_distance = reverse_hit_distance;
|
|
||||||
hit_point = closest_point;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// Reverse cast did not hit sphere
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Triangle3::containsPoint(const Vector3 &p) const
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
// From: http://stackoverflow.com/questions/995445/determine-if-a-3d-point-is-within-a-triangle
|
|
||||||
|
|
||||||
const float SMALL_NUM = 0.00000001f; // anything that avoids division overflow
|
|
||||||
// Vector3 A = vert[0], B = vert[1], C = vert[2];
|
|
||||||
if (_sameSide(p, vert[0], vert[1], vert[2]) && _sameSide(p, vert[1], vert[0], vert[2]) && _sameSide(p, vert[2], vert[0], vert[1])) {
|
|
||||||
Vector3 vc1 = Vector3::Cross(vert[0] - vert[1], vert[0] - vert[2]);
|
|
||||||
if(fabs(Vector3::Dot(vert[0] - p, vc1)) <= SMALL_NUM) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
*/
|
|
||||||
|
|
||||||
// From: http://blogs.msdn.com/b/rezanour/archive/2011/08/07/barycentric-coordinates-and-point-in-triangle-tests.aspx
|
|
||||||
|
|
||||||
Vector3 A = vert[0];
|
|
||||||
Vector3 B = vert[1];
|
|
||||||
Vector3 C = vert[2];
|
|
||||||
Vector3 P = p;
|
|
||||||
|
|
||||||
// Prepare our barycentric variables
|
|
||||||
Vector3 u = B - A;
|
|
||||||
Vector3 v = C - A;
|
|
||||||
Vector3 w = P - A;
|
|
||||||
|
|
||||||
Vector3 vCrossW = Vector3::Cross(v, w);
|
|
||||||
Vector3 vCrossU = Vector3::Cross(v, u);
|
|
||||||
|
|
||||||
// Test sign of r
|
|
||||||
if (Vector3::Dot(vCrossW, vCrossU) < 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Vector3 uCrossW = Vector3::Cross(u, w);
|
|
||||||
Vector3 uCrossV = Vector3::Cross(u, v);
|
|
||||||
|
|
||||||
// Test sign of t
|
|
||||||
if (Vector3::Dot(uCrossW, uCrossV) < 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// At this point, we know that r and t and both > 0.
|
|
||||||
// Therefore, as long as their sum is <= 1, each must be less <= 1
|
|
||||||
float denom = uCrossV.magnitude();
|
|
||||||
float r = vCrossW.magnitude() / denom;
|
|
||||||
float t = uCrossW.magnitude() / denom;
|
|
||||||
|
|
||||||
return (r + t <= 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace kraken
|
|
||||||
@@ -1,215 +0,0 @@
|
|||||||
//
|
|
||||||
// Vector2.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 12-03-22.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "public/kraken.h"
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
Vector2::Vector2() {
|
|
||||||
x = 0.0;
|
|
||||||
y = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2::Vector2(float X, float Y) {
|
|
||||||
x = X;
|
|
||||||
y = Y;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2::Vector2(float v) {
|
|
||||||
x = v;
|
|
||||||
y = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2::Vector2(float *v) {
|
|
||||||
x = v[0];
|
|
||||||
y = v[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2::Vector2(const Vector2 &v) {
|
|
||||||
x = v.x;
|
|
||||||
y = v.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Vector2 swizzle getters
|
|
||||||
Vector2 Vector2::yx() const
|
|
||||||
{
|
|
||||||
return Vector2(y,x);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vector2 swizzle setters
|
|
||||||
void Vector2::yx(const Vector2 &v)
|
|
||||||
{
|
|
||||||
y = v.x;
|
|
||||||
x = v.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector2::Min() {
|
|
||||||
return Vector2(-std::numeric_limits<float>::max());
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector2::Max() {
|
|
||||||
return Vector2(std::numeric_limits<float>::max());
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector2::Zero() {
|
|
||||||
return Vector2(0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector2::One() {
|
|
||||||
return Vector2(1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2::~Vector2() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2& Vector2::operator =(const Vector2& b) {
|
|
||||||
x = b.x;
|
|
||||||
y = b.y;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector2::operator +(const Vector2& b) const {
|
|
||||||
return Vector2(x + b.x, y + b.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector2::operator -(const Vector2& b) const {
|
|
||||||
return Vector2(x - b.x, y - b.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector2::operator +() const {
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector2::operator -() const {
|
|
||||||
return Vector2(-x, -y);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector2::operator *(const float v) const {
|
|
||||||
return Vector2(x * v, y * v);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector2::operator /(const float v) const {
|
|
||||||
float inv_v = 1.0f / v;
|
|
||||||
return Vector2(x * inv_v, y * inv_v);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2& Vector2::operator +=(const Vector2& b) {
|
|
||||||
x += b.x;
|
|
||||||
y += b.y;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2& Vector2::operator -=(const Vector2& b) {
|
|
||||||
x -= b.x;
|
|
||||||
y -= b.y;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Vector2& Vector2::operator *=(const float v) {
|
|
||||||
x *= v;
|
|
||||||
y *= v;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2& Vector2::operator /=(const float v) {
|
|
||||||
float inv_v = 1.0f / v;
|
|
||||||
x *= inv_v;
|
|
||||||
y *= inv_v;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Vector2::operator ==(const Vector2& b) const {
|
|
||||||
return x == b.x && y == b.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Vector2::operator !=(const Vector2& b) const {
|
|
||||||
return x != b.x || y != b.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Vector2::operator >(const Vector2& b) const
|
|
||||||
{
|
|
||||||
// Comparison operators are implemented to allow insertion into sorted containers such as std::set
|
|
||||||
if(x > b.x) {
|
|
||||||
return true;
|
|
||||||
} else if(x < b.x) {
|
|
||||||
return false;
|
|
||||||
} else if(y > b.y) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Vector2::operator <(const Vector2& b) const
|
|
||||||
{
|
|
||||||
// Comparison operators are implemented to allow insertion into sorted containers such as std::set
|
|
||||||
if(x < b.x) {
|
|
||||||
return true;
|
|
||||||
} else if(x > b.x) {
|
|
||||||
return false;
|
|
||||||
} else if(y < b.y) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float& Vector2::operator[] (unsigned i) {
|
|
||||||
switch(i) {
|
|
||||||
case 0:
|
|
||||||
return x;
|
|
||||||
case 1:
|
|
||||||
default:
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float Vector2::operator[](unsigned i) const {
|
|
||||||
switch(i) {
|
|
||||||
case 0:
|
|
||||||
return x;
|
|
||||||
case 1:
|
|
||||||
default:
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vector2::normalize() {
|
|
||||||
float inv_magnitude = 1.0f / sqrtf(x * x + y * y);
|
|
||||||
x *= inv_magnitude;
|
|
||||||
y *= inv_magnitude;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Vector2::sqrMagnitude() const {
|
|
||||||
return x * x + y * y;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Vector2::magnitude() const {
|
|
||||||
return sqrtf(x * x + y * y);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Vector2 Vector2::Normalize(const Vector2 &v) {
|
|
||||||
float inv_magnitude = 1.0f / sqrtf(v.x * v.x + v.y * v.y);
|
|
||||||
return Vector2(v.x * inv_magnitude, v.y * inv_magnitude);
|
|
||||||
}
|
|
||||||
|
|
||||||
float Vector2::Cross(const Vector2 &v1, const Vector2 &v2) {
|
|
||||||
return v1.x * v2.y - v1.y * v2.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Vector2::Dot(const Vector2 &v1, const Vector2 &v2) {
|
|
||||||
return v1.x * v2.x + v1.y * v2.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namepsace kraken
|
|
||||||
@@ -1,418 +0,0 @@
|
|||||||
//
|
|
||||||
// Vector3.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 "public/kraken.h"
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
const Vector3 Vector3_ZERO(0.0f, 0.0f, 0.0f);
|
|
||||||
|
|
||||||
//default constructor
|
|
||||||
Vector3::Vector3()
|
|
||||||
{
|
|
||||||
x = 0.0f;
|
|
||||||
y = 0.0f;
|
|
||||||
z = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3::Vector3(const Vector3 &v) {
|
|
||||||
x = v.x;
|
|
||||||
y = v.y;
|
|
||||||
z = v.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3::Vector3(const Vector4 &v) {
|
|
||||||
x = v.x;
|
|
||||||
y = v.y;
|
|
||||||
z = v.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3::Vector3(float *v) {
|
|
||||||
x = v[0];
|
|
||||||
y = v[1];
|
|
||||||
z = v[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3::Vector3(double *v) {
|
|
||||||
x = (float)v[0];
|
|
||||||
y = (float)v[1];
|
|
||||||
z = (float)v[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector3::xx() const
|
|
||||||
{
|
|
||||||
return Vector2(x,x);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector3::xy() const
|
|
||||||
{
|
|
||||||
return Vector2(x,y);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector3::xz() const
|
|
||||||
{
|
|
||||||
return Vector2(x,z);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector3::yx() const
|
|
||||||
{
|
|
||||||
return Vector2(y,x);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector3::yy() const
|
|
||||||
{
|
|
||||||
return Vector2(y,y);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector3::yz() const
|
|
||||||
{
|
|
||||||
return Vector2(y,z);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector3::zx() const
|
|
||||||
{
|
|
||||||
return Vector2(z,x);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector3::zy() const
|
|
||||||
{
|
|
||||||
return Vector2(z,y);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 Vector3::zz() const
|
|
||||||
{
|
|
||||||
return Vector2(z,z);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vector3::xy(const Vector2 &v)
|
|
||||||
{
|
|
||||||
x = v.x;
|
|
||||||
y = v.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vector3::xz(const Vector2 &v)
|
|
||||||
{
|
|
||||||
x = v.x;
|
|
||||||
z = v.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vector3::yx(const Vector2 &v)
|
|
||||||
{
|
|
||||||
y = v.x;
|
|
||||||
x = v.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vector3::yz(const Vector2 &v)
|
|
||||||
{
|
|
||||||
y = v.x;
|
|
||||||
z = v.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vector3::zx(const Vector2 &v)
|
|
||||||
{
|
|
||||||
z = v.x;
|
|
||||||
x = v.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vector3::zy(const Vector2 &v)
|
|
||||||
{
|
|
||||||
z = v.x;
|
|
||||||
y = v.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::Min() {
|
|
||||||
return Vector3(-std::numeric_limits<float>::max());
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::Max() {
|
|
||||||
return Vector3(std::numeric_limits<float>::max());
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector3 &Vector3::Zero() {
|
|
||||||
return Vector3_ZERO;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::One() {
|
|
||||||
return Vector3(1.0f, 1.0f, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::Forward() {
|
|
||||||
return Vector3(0.0f, 0.0f, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::Backward() {
|
|
||||||
return Vector3(0.0f, 0.0f, -1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::Up() {
|
|
||||||
return Vector3(0.0f, 1.0f, 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::Down() {
|
|
||||||
return Vector3(0.0f, -1.0f, 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::Left() {
|
|
||||||
return Vector3(-1.0f, 0.0f, 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::Right() {
|
|
||||||
return Vector3(1.0f, 0.0f, 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Vector3::scale(const Vector3 &v)
|
|
||||||
{
|
|
||||||
x *= v.x;
|
|
||||||
y *= v.y;
|
|
||||||
z *= v.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::Scale(const Vector3 &v1, const Vector3 &v2)
|
|
||||||
{
|
|
||||||
return Vector3(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::Lerp(const Vector3 &v1, const Vector3 &v2, float d) {
|
|
||||||
return v1 + (v2 - v1) * d;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::Slerp(const Vector3 &v1, const Vector3 &v2, float d) {
|
|
||||||
// From: http://keithmaggio.wordpress.com/2011/02/15/math-magician-lerp-slerp-and-nlerp/
|
|
||||||
// Dot product - the cosine of the angle between 2 vectors.
|
|
||||||
float dot = Vector3::Dot(v1, v2);
|
|
||||||
// Clamp it to be in the range of Acos()
|
|
||||||
if(dot < -1.0f) dot = -1.0f;
|
|
||||||
if(dot > 1.0f) dot = 1.0f;
|
|
||||||
// Acos(dot) returns the angle between start and end,
|
|
||||||
// And multiplying that by percent returns the angle between
|
|
||||||
// start and the final result.
|
|
||||||
float theta = acos(dot)*d;
|
|
||||||
Vector3 RelativeVec = v2 - v1*dot;
|
|
||||||
RelativeVec.normalize(); // Orthonormal basis
|
|
||||||
// The final result.
|
|
||||||
return ((v1*cos(theta)) + (RelativeVec*sin(theta)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vector3::OrthoNormalize(Vector3 &normal, Vector3 &tangent) {
|
|
||||||
// Gram-Schmidt Orthonormalization
|
|
||||||
normal.normalize();
|
|
||||||
Vector3 proj = normal * Dot(tangent, normal);
|
|
||||||
tangent = tangent - proj;
|
|
||||||
tangent.normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3::Vector3(float v) {
|
|
||||||
x = v;
|
|
||||||
y = v;
|
|
||||||
z = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3::Vector3(float X, float Y, float Z)
|
|
||||||
{
|
|
||||||
x = X;
|
|
||||||
y = Y;
|
|
||||||
z = Z;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3::~Vector3()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3& Vector3::operator =(const Vector3& b) {
|
|
||||||
x = b.x;
|
|
||||||
y = b.y;
|
|
||||||
z = b.z;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3& Vector3::operator =(const Vector4 &b) {
|
|
||||||
x = b.x;
|
|
||||||
y = b.y;
|
|
||||||
z = b.z;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::operator +(const Vector3& b) const {
|
|
||||||
return Vector3(x + b.x, y + b.y, z + b.z);
|
|
||||||
}
|
|
||||||
Vector3 Vector3::operator -(const Vector3& b) const {
|
|
||||||
return Vector3(x - b.x, y - b.y, z - b.z);
|
|
||||||
}
|
|
||||||
Vector3 Vector3::operator +() const {
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
Vector3 Vector3::operator -() const {
|
|
||||||
return Vector3(-x, -y, -z);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::operator *(const float v) const {
|
|
||||||
return Vector3(x * v, y * v, z * v);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::operator /(const float v) const {
|
|
||||||
float inv_v = 1.0f / v;
|
|
||||||
return Vector3(x * inv_v, y * inv_v, z * inv_v);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3& Vector3::operator +=(const Vector3& b) {
|
|
||||||
x += b.x;
|
|
||||||
y += b.y;
|
|
||||||
z += b.z;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3& Vector3::operator -=(const Vector3& b) {
|
|
||||||
x -= b.x;
|
|
||||||
y -= b.y;
|
|
||||||
z -= b.z;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3& Vector3::operator *=(const float v) {
|
|
||||||
x *= v;
|
|
||||||
y *= v;
|
|
||||||
z *= v;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3& Vector3::operator /=(const float v) {
|
|
||||||
float inv_v = 1.0f / v;
|
|
||||||
x *= inv_v;
|
|
||||||
y *= inv_v;
|
|
||||||
z *= inv_v;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Vector3::operator ==(const Vector3& b) const {
|
|
||||||
return x == b.x && y == b.y && z == b.z;
|
|
||||||
|
|
||||||
}
|
|
||||||
bool Vector3::operator !=(const Vector3& b) const {
|
|
||||||
return x != b.x || y != b.y || z != b.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
float& Vector3::operator[](unsigned i) {
|
|
||||||
switch(i) {
|
|
||||||
case 0:
|
|
||||||
return x;
|
|
||||||
case 1:
|
|
||||||
return y;
|
|
||||||
default:
|
|
||||||
case 2:
|
|
||||||
return z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float Vector3::operator[](unsigned i) const {
|
|
||||||
switch(i) {
|
|
||||||
case 0:
|
|
||||||
return x;
|
|
||||||
case 1:
|
|
||||||
return y;
|
|
||||||
case 2:
|
|
||||||
default:
|
|
||||||
return z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float Vector3::sqrMagnitude() const {
|
|
||||||
// calculate the square of the magnitude (useful for comparison of magnitudes without the cost of a sqrt() function)
|
|
||||||
return x * x + y * y + z * z;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Vector3::magnitude() const {
|
|
||||||
return sqrtf(x * x + y * y + z * z);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vector3::normalize() {
|
|
||||||
float inv_magnitude = 1.0f / sqrtf(x * x + y * y + z * z);
|
|
||||||
x *= inv_magnitude;
|
|
||||||
y *= inv_magnitude;
|
|
||||||
z *= inv_magnitude;
|
|
||||||
}
|
|
||||||
Vector3 Vector3::Normalize(const Vector3 &v) {
|
|
||||||
float inv_magnitude = 1.0f / sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
|
|
||||||
return Vector3(v.x * inv_magnitude, v.y * inv_magnitude, v.z * inv_magnitude);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::Cross(const Vector3 &v1, const Vector3 &v2) {
|
|
||||||
return Vector3(v1.y * v2.z - v1.z * v2.y,
|
|
||||||
v1.z * v2.x - v1.x * v2.z,
|
|
||||||
v1.x * v2.y - v1.y * v2.x);
|
|
||||||
}
|
|
||||||
|
|
||||||
float Vector3::Dot(const Vector3 &v1, const Vector3 &v2) {
|
|
||||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Vector3::operator >(const Vector3& b) const
|
|
||||||
{
|
|
||||||
// Comparison operators are implemented to allow insertion into sorted containers such as std::set
|
|
||||||
if(x > b.x) {
|
|
||||||
return true;
|
|
||||||
} else if(x < b.x) {
|
|
||||||
return false;
|
|
||||||
} else if(y > b.y) {
|
|
||||||
return true;
|
|
||||||
} else if(y < b.y) {
|
|
||||||
return false;
|
|
||||||
} else if(z > b.z) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Vector3::operator <(const Vector3& b) const
|
|
||||||
{
|
|
||||||
// Comparison operators are implemented to allow insertion into sorted containers such as std::set
|
|
||||||
if(x < b.x) {
|
|
||||||
return true;
|
|
||||||
} else if(x > b.x) {
|
|
||||||
return false;
|
|
||||||
} else if(y < b.y) {
|
|
||||||
return true;
|
|
||||||
} else if(y > b.y) {
|
|
||||||
return false;
|
|
||||||
} else if(z < b.z) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace kraken
|
|
||||||
|
|
||||||
@@ -1,303 +0,0 @@
|
|||||||
//
|
|
||||||
// Vector4.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 "public/kraken.h"
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
|
|
||||||
const Vector4 Vector4_ZERO(0.0f, 0.0f, 0.0f, 0.0f);
|
|
||||||
|
|
||||||
//default constructor
|
|
||||||
Vector4::Vector4()
|
|
||||||
{
|
|
||||||
x = 0.0f;
|
|
||||||
y = 0.0f;
|
|
||||||
z = 0.0f;
|
|
||||||
w = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4::Vector4(const Vector4 &v) {
|
|
||||||
x = v.x;
|
|
||||||
y = v.y;
|
|
||||||
z = v.z;
|
|
||||||
w = v.w;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4::Vector4(const Vector3 &v, float W) {
|
|
||||||
x = v.x;
|
|
||||||
y = v.y;
|
|
||||||
z = v.z;
|
|
||||||
w = W;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4::Vector4(float *v) {
|
|
||||||
x = v[0];
|
|
||||||
y = v[1];
|
|
||||||
z = v[2];
|
|
||||||
w = v[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4 Vector4::Min() {
|
|
||||||
return Vector4(-std::numeric_limits<float>::max());
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4 Vector4::Max() {
|
|
||||||
return Vector4(std::numeric_limits<float>::max());
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector4 &Vector4::Zero() {
|
|
||||||
return Vector4_ZERO;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4 Vector4::One() {
|
|
||||||
return Vector4(1.0f, 1.0f, 1.0f, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4 Vector4::Forward() {
|
|
||||||
return Vector4(0.0f, 0.0f, 1.0f, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4 Vector4::Backward() {
|
|
||||||
return Vector4(0.0f, 0.0f, -1.0f, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4 Vector4::Up() {
|
|
||||||
return Vector4(0.0f, 1.0f, 0.0f, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4 Vector4::Down() {
|
|
||||||
return Vector4(0.0f, -1.0f, 0.0f, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4 Vector4::Left() {
|
|
||||||
return Vector4(-1.0f, 0.0f, 0.0f, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4 Vector4::Right() {
|
|
||||||
return Vector4(1.0f, 0.0f, 0.0f, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4 Vector4::Lerp(const Vector4 &v1, const Vector4 &v2, float d) {
|
|
||||||
return v1 + (v2 - v1) * d;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4 Vector4::Slerp(const Vector4 &v1, const Vector4 &v2, float d) {
|
|
||||||
// From: http://keithmaggio.wordpress.com/2011/02/15/math-magician-lerp-slerp-and-nlerp/
|
|
||||||
// Dot product - the cosine of the angle between 2 vectors.
|
|
||||||
float dot = Vector4::Dot(v1, v2);
|
|
||||||
// Clamp it to be in the range of Acos()
|
|
||||||
if(dot < -1.0f) dot = -1.0f;
|
|
||||||
if(dot > 1.0f) dot = 1.0f;
|
|
||||||
// Acos(dot) returns the angle between start and end,
|
|
||||||
// And multiplying that by percent returns the angle between
|
|
||||||
// start and the final result.
|
|
||||||
float theta = acos(dot)*d;
|
|
||||||
Vector4 RelativeVec = v2 - v1*dot;
|
|
||||||
RelativeVec.normalize(); // Orthonormal basis
|
|
||||||
// The final result.
|
|
||||||
return ((v1*cos(theta)) + (RelativeVec*sin(theta)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vector4::OrthoNormalize(Vector4 &normal, Vector4 &tangent) {
|
|
||||||
// Gram-Schmidt Orthonormalization
|
|
||||||
normal.normalize();
|
|
||||||
Vector4 proj = normal * Dot(tangent, normal);
|
|
||||||
tangent = tangent - proj;
|
|
||||||
tangent.normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4::Vector4(float v) {
|
|
||||||
x = v;
|
|
||||||
y = v;
|
|
||||||
z = v;
|
|
||||||
w = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4::Vector4(float X, float Y, float Z, float W)
|
|
||||||
{
|
|
||||||
x = X;
|
|
||||||
y = Y;
|
|
||||||
z = Z;
|
|
||||||
w = W;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4::~Vector4()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4& Vector4::operator =(const Vector4& b) {
|
|
||||||
x = b.x;
|
|
||||||
y = b.y;
|
|
||||||
z = b.z;
|
|
||||||
w = b.w;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
Vector4 Vector4::operator +(const Vector4& b) const {
|
|
||||||
return Vector4(x + b.x, y + b.y, z + b.z, w + b.w);
|
|
||||||
}
|
|
||||||
Vector4 Vector4::operator -(const Vector4& b) const {
|
|
||||||
return Vector4(x - b.x, y - b.y, z - b.z, w - b.w);
|
|
||||||
}
|
|
||||||
Vector4 Vector4::operator +() const {
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
Vector4 Vector4::operator -() const {
|
|
||||||
return Vector4(-x, -y, -z, -w);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4 Vector4::operator *(const float v) const {
|
|
||||||
return Vector4(x * v, y * v, z * v, w * v);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4 Vector4::operator /(const float v) const {
|
|
||||||
return Vector4(x / v, y / v, z / v, w/ v);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4& Vector4::operator +=(const Vector4& b) {
|
|
||||||
x += b.x;
|
|
||||||
y += b.y;
|
|
||||||
z += b.z;
|
|
||||||
w += b.w;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4& Vector4::operator -=(const Vector4& b) {
|
|
||||||
x -= b.x;
|
|
||||||
y -= b.y;
|
|
||||||
z -= b.z;
|
|
||||||
w -= b.w;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4& Vector4::operator *=(const float v) {
|
|
||||||
x *= v;
|
|
||||||
y *= v;
|
|
||||||
z *= v;
|
|
||||||
w *= v;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4& Vector4::operator /=(const float v) {
|
|
||||||
float inv_v = 1.0f / v;
|
|
||||||
x *= inv_v;
|
|
||||||
y *= inv_v;
|
|
||||||
z *= inv_v;
|
|
||||||
w *= inv_v;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Vector4::operator ==(const Vector4& b) const {
|
|
||||||
return x == b.x && y == b.y && z == b.z && w == b.w;
|
|
||||||
|
|
||||||
}
|
|
||||||
bool Vector4::operator !=(const Vector4& b) const {
|
|
||||||
return x != b.x || y != b.y || z != b.z || w != b.w;
|
|
||||||
}
|
|
||||||
|
|
||||||
float& Vector4::operator[](unsigned i) {
|
|
||||||
switch(i) {
|
|
||||||
case 0:
|
|
||||||
return x;
|
|
||||||
case 1:
|
|
||||||
return y;
|
|
||||||
case 2:
|
|
||||||
return z;
|
|
||||||
default:
|
|
||||||
case 3:
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float Vector4::operator[](unsigned i) const {
|
|
||||||
switch(i) {
|
|
||||||
case 0:
|
|
||||||
return x;
|
|
||||||
case 1:
|
|
||||||
return y;
|
|
||||||
case 2:
|
|
||||||
return z;
|
|
||||||
default:
|
|
||||||
case 3:
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float Vector4::sqrMagnitude() const {
|
|
||||||
// calculate the square of the magnitude (useful for comparison of magnitudes without the cost of a sqrt() function)
|
|
||||||
return x * x + y * y + z * z + w * w;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Vector4::magnitude() const {
|
|
||||||
return sqrtf(x * x + y * y + z * z + w * w);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vector4::normalize() {
|
|
||||||
float inv_magnitude = 1.0f / sqrtf(x * x + y * y + z * z + w * w);
|
|
||||||
x *= inv_magnitude;
|
|
||||||
y *= inv_magnitude;
|
|
||||||
z *= inv_magnitude;
|
|
||||||
w *= inv_magnitude;
|
|
||||||
}
|
|
||||||
Vector4 Vector4::Normalize(const Vector4 &v) {
|
|
||||||
float inv_magnitude = 1.0f / sqrtf(v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w);
|
|
||||||
return Vector4(v.x * inv_magnitude, v.y * inv_magnitude, v.z * inv_magnitude, v.w * inv_magnitude);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
float Vector4::Dot(const Vector4 &v1, const Vector4 &v2) {
|
|
||||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Vector4::operator >(const Vector4& b) const
|
|
||||||
{
|
|
||||||
// Comparison operators are implemented to allow insertion into sorted containers such as std::set
|
|
||||||
if(x != b.x) return x > b.x;
|
|
||||||
if(y != b.y) return y > b.y;
|
|
||||||
if(z != b.z) return z > b.z;
|
|
||||||
if(w != b.w) return w > b.w;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Vector4::operator <(const Vector4& b) const
|
|
||||||
{
|
|
||||||
// Comparison operators are implemented to allow insertion into sorted containers such as std::set
|
|
||||||
if(x != b.x) return x < b.x;
|
|
||||||
if(y != b.y) return y < b.y;
|
|
||||||
if(z != b.z) return z < b.z;
|
|
||||||
if(w != b.w) return w < b.w;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace kraken
|
|
||||||
Reference in New Issue
Block a user