Updated Subrepos, hydra data types are now POD -- refactored Kraken to match. Eliminated some warnings

This commit is contained in:
2018-07-27 00:18:30 -07:00
parent d31a9b0538
commit 96412e1530
60 changed files with 12557 additions and 16027 deletions

12
.gitignore vendored
View File

@@ -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/glfw vendored

2
hydra

Submodule hydra updated: 00bb9b6689...759b7af066

View File

@@ -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)

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,229 +1,229 @@
// //
// KRCollider.cpp // KRCollider.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRCollider.h" #include "KRCollider.h"
#include "KRContext.h" #include "KRContext.h"
#include "KRMesh.h" #include "KRMesh.h"
KRCollider::KRCollider(KRScene &scene, std::string collider_name, std::string model_name, unsigned int layer_mask, float audio_occlusion) : KRNode(scene, collider_name) { KRCollider::KRCollider(KRScene &scene, std::string collider_name, std::string model_name, unsigned int layer_mask, float audio_occlusion) : KRNode(scene, collider_name) {
m_model_name = model_name; m_model_name = model_name;
m_layer_mask = layer_mask; m_layer_mask = layer_mask;
m_audio_occlusion = audio_occlusion; m_audio_occlusion = audio_occlusion;
} }
KRCollider::~KRCollider() { KRCollider::~KRCollider() {
} }
std::string KRCollider::getElementName() { std::string KRCollider::getElementName() {
return "collider"; return "collider";
} }
tinyxml2::XMLElement *KRCollider::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRCollider::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("mesh", m_model_name.c_str()); e->SetAttribute("mesh", m_model_name.c_str());
e->SetAttribute("layer_mask", m_layer_mask); e->SetAttribute("layer_mask", m_layer_mask);
e->SetAttribute("audio_occlusion", m_audio_occlusion); e->SetAttribute("audio_occlusion", m_audio_occlusion);
return e; return e;
} }
void KRCollider::loadXML(tinyxml2::XMLElement *e) { void KRCollider::loadXML(tinyxml2::XMLElement *e) {
KRNode::loadXML(e); KRNode::loadXML(e);
m_model_name = e->Attribute("mesh"); m_model_name = e->Attribute("mesh");
m_layer_mask = 65535; m_layer_mask = 65535;
if(e->QueryUnsignedAttribute("layer_mask", &m_layer_mask) != tinyxml2::XML_SUCCESS) { if(e->QueryUnsignedAttribute("layer_mask", &m_layer_mask) != tinyxml2::XML_SUCCESS) {
m_layer_mask = 65535; m_layer_mask = 65535;
} }
m_audio_occlusion = 1.0f; m_audio_occlusion = 1.0f;
if(e->QueryFloatAttribute("audio_occlusion", &m_audio_occlusion) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("audio_occlusion", &m_audio_occlusion) != tinyxml2::XML_SUCCESS) {
m_audio_occlusion = 1.0f; m_audio_occlusion = 1.0f;
} }
} }
void KRCollider::loadModel() { void KRCollider::loadModel() {
if(m_models.size() == 0) { if(m_models.size() == 0) {
m_models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first m_models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first
if(m_models.size() > 0) { if(m_models.size() > 0) {
getScene().notify_sceneGraphModify(this); getScene().notify_sceneGraphModify(this);
} }
} }
} }
AABB KRCollider::getBounds() { AABB KRCollider::getBounds() {
loadModel(); loadModel();
if(m_models.size() > 0) { if(m_models.size() > 0) {
return AABB(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;
} }
} }
} }

View File

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

View File

@@ -1,135 +1,135 @@
// //
// KRDirectionalLight.cpp // KRDirectionalLight.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-04-05. // Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRDirectionalLight.h" #include "KRDirectionalLight.h"
#include "KRShader.h" #include "KRShader.h"
#include "KRContext.h" #include "KRContext.h"
#include "assert.h" #include "assert.h"
#include "KRStockGeometry.h" #include "KRStockGeometry.h"
KRDirectionalLight::KRDirectionalLight(KRScene &scene, std::string name) : KRLight(scene, name) KRDirectionalLight::KRDirectionalLight(KRScene &scene, std::string name) : KRLight(scene, name)
{ {
} }
KRDirectionalLight::~KRDirectionalLight() KRDirectionalLight::~KRDirectionalLight()
{ {
} }
std::string KRDirectionalLight::getElementName() { std::string KRDirectionalLight::getElementName() {
return "directional_light"; return "directional_light";
} }
Vector3 KRDirectionalLight::getWorldLightDirection() { Vector3 KRDirectionalLight::getWorldLightDirection() {
return Matrix4::Dot(getWorldRotation().rotationMatrix(), getLocalLightDirection()); return Matrix4::Dot(getWorldRotation().rotationMatrix(), getLocalLightDirection());
} }
Vector3 KRDirectionalLight::getLocalLightDirection() { Vector3 KRDirectionalLight::getLocalLightDirection() {
return Vector3::Up(); //&KRF HACK changed from Vector3::Forward(); - to compensate for the way Maya handles post rotation. return Vector3::Up(); //&KRF HACK changed from Vector3::Forward(); - to compensate for the way Maya handles post rotation.
} }
int KRDirectionalLight::configureShadowBufferViewports(const KRViewport &viewport) { int KRDirectionalLight::configureShadowBufferViewports(const KRViewport &viewport) {
const float KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE = 1.25f; // Scale to apply to view frustrum bounds so that we don't need to refresh shadows on every frame const float KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE = 1.25f; // Scale to apply to view frustrum bounds so that we don't need to refresh shadows on every frame
int cShadows = 1; int cShadows = 1;
for(int iShadow=0; iShadow < cShadows; iShadow++) { for(int iShadow=0; iShadow < cShadows; iShadow++) {
/* /*
TODO - Determine if we still need this... TODO - Determine if we still need this...
GLfloat shadowMinDepths[3][3] = {{0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f},{0.0f, 0.05f, 0.3f}}; GLfloat shadowMinDepths[3][3] = {{0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f},{0.0f, 0.05f, 0.3f}};
GLfloat shadowMaxDepths[3][3] = {{0.0f, 0.0f, 1.0f},{0.1f, 0.0f, 0.0f},{0.1f, 0.3f, 1.0f}}; GLfloat shadowMaxDepths[3][3] = {{0.0f, 0.0f, 1.0f},{0.1f, 0.0f, 0.0f},{0.1f, 0.3f, 1.0f}};
float min_depth = 0.0f; float min_depth = 0.0f;
float max_depth = 1.0f; float max_depth = 1.0f;
*/ */
AABB worldSpacefrustrumSliceBounds = AABB(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();
} }

View File

@@ -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>

View File

@@ -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__)

View File

@@ -1,173 +1,173 @@
// //
// KRLODGroup.cpp // KRLODGroup.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-12-06. // Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KRLODGroup.h" #include "KRLODGroup.h"
#include "KRLODSet.h" #include "KRLODSet.h"
#include "KRContext.h" #include "KRContext.h"
KRLODGroup::KRLODGroup(KRScene &scene, std::string name) : KRNode(scene, name) KRLODGroup::KRLODGroup(KRScene &scene, std::string name) : KRNode(scene, name)
{ {
m_min_distance = 0.0f; m_min_distance = 0.0f;
m_max_distance = 0.0f; m_max_distance = 0.0f;
m_reference = AABB(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;
} }

View File

@@ -1,485 +1,485 @@
// //
// KRLight.cpp // KRLight.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-04-05. // Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRLight.h" #include "KRLight.h"
#include "KRNode.h" #include "KRNode.h"
#include "KRCamera.h" #include "KRCamera.h"
#include "KRContext.h" #include "KRContext.h"
#include "KRShaderManager.h" #include "KRShaderManager.h"
#include "KRShader.h" #include "KRShader.h"
#include "KRStockGeometry.h" #include "KRStockGeometry.h"
#include "KRDirectionalLight.h" #include "KRDirectionalLight.h"
#include "KRSpotLight.h" #include "KRSpotLight.h"
#include "KRPointLight.h" #include "KRPointLight.h"
KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name) KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name)
{ {
m_intensity = 1.0f; m_intensity = 1.0f;
m_dust_particle_intensity = 1.0f; m_dust_particle_intensity = 1.0f;
m_color = Vector3::One(); m_color = Vector3::One();
m_flareTexture = ""; m_flareTexture = "";
m_pFlareTexture = NULL; m_pFlareTexture = NULL;
m_flareSize = 0.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, &params)); GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, &params));
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery)); GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
if(params) { if(params) {
if(!m_pFlareTexture && m_flareTexture.size()) { if(!m_pFlareTexture && m_flareTexture.size()) {
m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture); m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture);
} }
if(m_pFlareTexture) { if(m_pFlareTexture) {
// Disable z-buffer test // Disable z-buffer test
GLDEBUG(glDisable(GL_DEPTH_TEST)); GLDEBUG(glDisable(GL_DEPTH_TEST));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
// Render light flare on transparency pass // Render light flare on transparency pass
KRShader *pShader = getContext().getShaderManager()->getShader("flare", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRShader *pShader = getContext().getShaderManager()->getShader("flare", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, 1.0f); pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, 1.0f);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_flareSize); pShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_flareSize);
m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture, 0.0f, KRTexture::TEXTURE_USAGE_LIGHT_FLARE); m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture, 0.0f, KRTexture::TEXTURE_USAGE_LIGHT_FLARE);
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f); m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
} }
} }
} }
} }
} }
} }
} }
void KRLight::allocateShadowBuffers(int cBuffers) { void KRLight::allocateShadowBuffers(int cBuffers) {
// First deallocate buffers no longer needed // First deallocate buffers no longer needed
for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) { for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) {
if (shadowDepthTexture[iShadow]) { if (shadowDepthTexture[iShadow]) {
GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow)); GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow));
shadowDepthTexture[iShadow] = 0; shadowDepthTexture[iShadow] = 0;
} }
if (shadowFramebuffer[iShadow]) { if (shadowFramebuffer[iShadow]) {
GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow)); GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow));
shadowFramebuffer[iShadow] = 0; shadowFramebuffer[iShadow] = 0;
} }
} }
// Allocate newly required buffers // Allocate newly required buffers
for(int iShadow = 0; iShadow < cBuffers; iShadow++) { for(int iShadow = 0; iShadow < cBuffers; iShadow++) {
Vector2 viewportSize = m_shadowViewports[iShadow].getSize(); Vector2 viewportSize = m_shadowViewports[iShadow].getSize();
if(!shadowDepthTexture[iShadow]) { if(!shadowDepthTexture[iShadow]) {
shadowValid[iShadow] = false; shadowValid[iShadow] = false;
GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow)); GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow));
GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow)); GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow));
// ===== Create offscreen shadow framebuffer object ===== // ===== Create offscreen shadow framebuffer object =====
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow])); GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
// ----- Create Depth Texture for shadowFramebuffer ----- // ----- Create Depth Texture for shadowFramebuffer -----
GLDEBUG( glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow])); GLDEBUG( glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow]));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
m_pContext->getTextureManager()->_setWrapModeS(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE); m_pContext->getTextureManager()->_setWrapModeS(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
m_pContext->getTextureManager()->_setWrapModeT(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE); m_pContext->getTextureManager()->_setWrapModeT(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
#if GL_EXT_shadow_samplers #if GL_EXT_shadow_samplers
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_COMPARE_REF_TO_TEXTURE_EXT)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_COMPARE_REF_TO_TEXTURE_EXT)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_EXT, GL_LEQUAL)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_EXT, GL_LEQUAL)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
#endif #endif
GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, viewportSize.x, viewportSize.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL)); GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, viewportSize.x, viewportSize.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0)); GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
} }
} }
m_cShadowBuffers = cBuffers; m_cShadowBuffers = cBuffers;
} }
void KRLight::deleteBuffers() void KRLight::deleteBuffers()
{ {
// Called when this light wasn't used in the last frame, so we can free the resources for use by other lights // Called when this light wasn't used in the last frame, so we can free the resources for use by other lights
allocateShadowBuffers(0); allocateShadowBuffers(0);
} }
void KRLight::invalidateShadowBuffers() void KRLight::invalidateShadowBuffers()
{ {
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) { for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
shadowValid[iShadow] = false; shadowValid[iShadow] = false;
} }
} }
int KRLight::configureShadowBufferViewports(const KRViewport &viewport) int KRLight::configureShadowBufferViewports(const KRViewport &viewport)
{ {
return 0; return 0;
} }
void KRLight::renderShadowBuffers(KRCamera *pCamera) void KRLight::renderShadowBuffers(KRCamera *pCamera)
{ {
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) { for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
if(!shadowValid[iShadow]) { if(!shadowValid[iShadow]) {
shadowValid[iShadow] = true; shadowValid[iShadow] = true;
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow])); GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0)); GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
GLDEBUG(glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y)); GLDEBUG(glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y));
GLDEBUG(glClearDepthf(0.0f)); GLDEBUG(glClearDepthf(0.0f));
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT)); GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
GLDEBUG(glViewport(1, 1, m_shadowViewports[iShadow].getSize().x - 2, m_shadowViewports[iShadow].getSize().y - 2)); GLDEBUG(glViewport(1, 1, m_shadowViewports[iShadow].getSize().x - 2, m_shadowViewports[iShadow].getSize().y - 2));
GLDEBUG(glClearDepthf(1.0f)); GLDEBUG(glClearDepthf(1.0f));
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT)); GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
GLDEBUG(glDisable(GL_DITHER)); GLDEBUG(glDisable(GL_DITHER));
//GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts //GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts
//GLDEBUG(glEnable(GL_CULL_FACE)); //GLDEBUG(glEnable(GL_CULL_FACE));
GLDEBUG(glDisable(GL_CULL_FACE)); GLDEBUG(glDisable(GL_CULL_FACE));
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LESS)); GLDEBUG(glDepthFunc(GL_LESS));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
// Disable alpha blending as we are using alpha channel for packed depth info // Disable alpha blending as we are using alpha channel for packed depth info
GLDEBUG(glDisable(GL_BLEND)); GLDEBUG(glDisable(GL_BLEND));
// Use shader program // Use shader program
KRShader *shadowShader = m_pContext->getShaderManager()->getShader("ShadowShader", pCamera, std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); KRShader *shadowShader = m_pContext->getShaderManager()->getShader("ShadowShader", pCamera, std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
getContext().getShaderManager()->selectShader(*pCamera, shadowShader, m_shadowViewports[iShadow], Matrix4(), std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, KRNode::RENDER_PASS_SHADOWMAP, Vector3::Zero(), 0.0f, Vector4::Zero()); getContext().getShaderManager()->selectShader(*pCamera, shadowShader, m_shadowViewports[iShadow], Matrix4(), std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, KRNode::RENDER_PASS_SHADOWMAP, Vector3::Zero(), 0.0f, Vector4::Zero());
getScene().render(pCamera, m_shadowViewports[iShadow].getVisibleBounds(), m_shadowViewports[iShadow], KRNode::RENDER_PASS_SHADOWMAP, true); getScene().render(pCamera, m_shadowViewports[iShadow].getVisibleBounds(), m_shadowViewports[iShadow], KRNode::RENDER_PASS_SHADOWMAP, true);
GLDEBUG(glEnable(GL_CULL_FACE)); GLDEBUG(glEnable(GL_CULL_FACE));
} }
} }
} }
int KRLight::getShadowBufferCount() int KRLight::getShadowBufferCount()
{ {
int cBuffers=0; int cBuffers=0;
for(int iBuffer=0; iBuffer < m_cShadowBuffers; iBuffer++) { for(int iBuffer=0; iBuffer < m_cShadowBuffers; iBuffer++) {
if(shadowValid[iBuffer]) { if(shadowValid[iBuffer]) {
cBuffers++; cBuffers++;
} else { } else {
break; break;
} }
} }
return cBuffers; return cBuffers;
} }
GLuint *KRLight::getShadowTextures() GLuint *KRLight::getShadowTextures()
{ {
return shadowDepthTexture; return shadowDepthTexture;
} }
KRViewport *KRLight::getShadowViewports() KRViewport *KRLight::getShadowViewports()
{ {
return m_shadowViewports; return m_shadowViewports;
} }

View File

@@ -1,422 +1,422 @@
// //
// KRMaterial.cpp // KRMaterial.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRMaterial.h" #include "KRMaterial.h"
#include "KRTextureManager.h" #include "KRTextureManager.h"
#include "KRContext.h" #include "KRContext.h"
KRMaterial::KRMaterial(KRContext &context, const char *szName) : KRResource(context, szName) { KRMaterial::KRMaterial(KRContext &context, const char *szName) : KRResource(context, szName) {
m_name = szName; m_name = szName;
m_pAmbientMap = NULL; m_pAmbientMap = NULL;
m_pDiffuseMap = NULL; m_pDiffuseMap = NULL;
m_pSpecularMap = NULL; m_pSpecularMap = NULL;
m_pNormalMap = NULL; m_pNormalMap = NULL;
m_pReflectionMap = NULL; m_pReflectionMap = NULL;
m_pReflectionCube = NULL; m_pReflectionCube = NULL;
m_ambientColor = Vector3::Zero(); m_ambientColor = Vector3::Zero();
m_diffuseColor = Vector3::One(); m_diffuseColor = Vector3::One();
m_specularColor = Vector3::One(); m_specularColor = Vector3::One();
m_reflectionColor = Vector3::Zero(); m_reflectionColor = Vector3::Zero();
m_tr = (GLfloat)1.0f; m_tr = (GLfloat)1.0f;
m_ns = (GLfloat)0.0f; m_ns = (GLfloat)0.0f;
m_ambientMap = ""; m_ambientMap = "";
m_diffuseMap = ""; m_diffuseMap = "";
m_specularMap = ""; m_specularMap = "";
m_normalMap = ""; m_normalMap = "";
m_reflectionMap = ""; m_reflectionMap = "";
m_reflectionCube = ""; m_reflectionCube = "";
m_ambientMapOffset = Vector2(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;
} }

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

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

View File

@@ -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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,156 +1,156 @@
// //
// KROctree.cpp // KROctree.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-08-29. // Created by Kearwood Gilbert on 2012-08-29.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "public/kraken.h" #include "public/kraken.h"
#include "KROctree.h" #include "KROctree.h"
#include "KRNode.h" #include "KRNode.h"
#include "KRCollider.h" #include "KRCollider.h"
KROctree::KROctree() KROctree::KROctree()
{ {
m_pRootNode = NULL; m_pRootNode = NULL;
} }
KROctree::~KROctree() KROctree::~KROctree()
{ {
if(m_pRootNode) { if(m_pRootNode) {
delete m_pRootNode; delete m_pRootNode;
} }
} }
void KROctree::add(KRNode *pNode) void KROctree::add(KRNode *pNode)
{ {
AABB nodeBounds = pNode->getBounds(); AABB nodeBounds = pNode->getBounds();
if(nodeBounds == AABB::Zero()) { if(nodeBounds == AABB::Zero()) {
// This item is not visible, don't add it to the octree or outer scene nodes // This item is not visible, don't add it to the octree or outer scene nodes
} else if(nodeBounds == AABB::Infinite()) { } else if(nodeBounds == AABB::Infinite()) {
// This item is infinitely large; we track it separately // This item is infinitely large; we track it separately
m_outerSceneNodes.insert(pNode); m_outerSceneNodes.insert(pNode);
} else { } else {
if(m_pRootNode == NULL) { if(m_pRootNode == NULL) {
// First item inserted, create a node large enough to fit it // First item inserted, create a node large enough to fit it
m_pRootNode = new KROctreeNode(NULL, nodeBounds); m_pRootNode = new KROctreeNode(NULL, nodeBounds);
m_pRootNode->add(pNode); m_pRootNode->add(pNode);
} else { } else {
// Keep encapsulating the root node until the new root contains the inserted node // Keep encapsulating the root node until the new root contains the inserted node
bool bInsideRoot = false; bool bInsideRoot = false;
while(!bInsideRoot) { while(!bInsideRoot) {
AABB rootBounds = m_pRootNode->getBounds(); AABB rootBounds = m_pRootNode->getBounds();
Vector3 rootSize = rootBounds.size(); Vector3 rootSize = rootBounds.size();
if(nodeBounds.min.x < rootBounds.min.x || nodeBounds.min.y < rootBounds.min.y || nodeBounds.min.z < rootBounds.min.z) { if(nodeBounds.min.x < rootBounds.min.x || nodeBounds.min.y < rootBounds.min.y || nodeBounds.min.z < rootBounds.min.z) {
m_pRootNode = new KROctreeNode(NULL, AABB(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;
} }

View File

@@ -1,290 +1,290 @@
// //
// KROctreeNode.cpp // KROctreeNode.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-08-29. // Created by Kearwood Gilbert on 2012-08-29.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KROctreeNode.h" #include "KROctreeNode.h"
#include "KRNode.h" #include "KRNode.h"
#include "KRCollider.h" #include "KRCollider.h"
KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds) : m_bounds(bounds) KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds) : m_bounds(bounds)
{ {
m_parent = parent; m_parent = parent;
for(int i=0; i<8; i++) m_children[i] = NULL; for(int i=0; i<8; i++) m_children[i] = NULL;
m_occlusionQuery = 0; m_occlusionQuery = 0;
m_occlusionTested = false; m_occlusionTested = false;
m_activeQuery = false; m_activeQuery = false;
} }
KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds, int iChild, KROctreeNode *pChild) : m_bounds(bounds) KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds, int iChild, KROctreeNode *pChild) : m_bounds(bounds)
{ {
// This constructor is used when expanding the octree and replacing the root node with a new root that encapsulates it // This constructor is used when expanding the octree and replacing the root node with a new root that encapsulates it
m_parent = parent; m_parent = parent;
for(int i=0; i<8; i++) m_children[i] = NULL; for(int i=0; i<8; i++) m_children[i] = NULL;
m_children[iChild] = pChild; m_children[iChild] = pChild;
pChild->m_parent = this; pChild->m_parent = this;
m_occlusionQuery = 0; m_occlusionQuery = 0;
m_occlusionTested = false; m_occlusionTested = false;
m_activeQuery = false; m_activeQuery = false;
} }
KROctreeNode::~KROctreeNode() KROctreeNode::~KROctreeNode()
{ {
for(int i=0; i<8; i++) { for(int i=0; i<8; i++) {
if(m_children[i] != NULL) { if(m_children[i] != NULL) {
delete m_children[i]; delete m_children[i];
} }
} }
if(m_occlusionTested) { if(m_occlusionTested) {
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery)); GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
} }
} }
void KROctreeNode::beginOcclusionQuery() void KROctreeNode::beginOcclusionQuery()
{ {
if(!m_occlusionTested){ if(!m_occlusionTested){
GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery)); GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery));
#if TARGET_OS_IPHONE #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;
} }

View File

@@ -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) */

View File

@@ -1,226 +1,226 @@
// //
// KRPointLight.cpp // KRPointLight.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-04-05. // Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRPointLight.h" #include "KRPointLight.h"
#include "KRCamera.h" #include "KRCamera.h"
#include "KRContext.h" #include "KRContext.h"
#include "KRStockGeometry.h" #include "KRStockGeometry.h"
KRPointLight::KRPointLight(KRScene &scene, std::string name) : KRLight(scene, name) KRPointLight::KRPointLight(KRScene &scene, std::string name) : KRLight(scene, name)
{ {
m_sphereVertices = NULL; m_sphereVertices = NULL;
m_cVertices = 0; m_cVertices = 0;
} }
KRPointLight::~KRPointLight() KRPointLight::~KRPointLight()
{ {
if(m_sphereVertices) { if(m_sphereVertices) {
delete m_sphereVertices; delete m_sphereVertices;
m_cVertices = 0; m_cVertices = 0;
} }
} }
std::string KRPointLight::getElementName() { std::string KRPointLight::getElementName() {
return "point_light"; return "point_light";
} }
AABB KRPointLight::getBounds() { AABB KRPointLight::getBounds() {
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE); float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
if(influence_radius < m_flareOcclusionSize) { if(influence_radius < m_flareOcclusionSize) {
influence_radius = m_flareOcclusionSize; influence_radius = m_flareOcclusionSize;
} }
return AABB(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;
} }
} }
} }

View File

@@ -1,204 +1,204 @@
// //
// KRRenderSettings.cpp // KRRenderSettings.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-12-20. // Created by Kearwood Gilbert on 2012-12-20.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KRRenderSettings.h" #include "KRRenderSettings.h"
KRRenderSettings::KRRenderSettings() KRRenderSettings::KRRenderSettings()
{ {
siren_enable = true; siren_enable = true;
siren_enable_reverb = true; siren_enable_reverb = true;
siren_enable_hrtf = true; siren_enable_hrtf = true;
siren_reverb_max_length = 2.0f; siren_reverb_max_length = 2.0f;
m_enable_realtime_occlusion = false; m_enable_realtime_occlusion = false;
bShowShadowBuffer = false; bShowShadowBuffer = false;
bShowOctree = false; bShowOctree = false;
bShowDeferred = false; bShowDeferred = false;
bEnablePerPixel = true; bEnablePerPixel = true;
bEnableDiffuseMap = true; bEnableDiffuseMap = true;
bEnableNormalMap = true; bEnableNormalMap = true;
bEnableSpecMap = true; bEnableSpecMap = true;
bEnableReflectionMap = true; bEnableReflectionMap = true;
bEnableReflection = true; bEnableReflection = true;
bDebugPSSM = false; bDebugPSSM = false;
bEnableAmbient = true; bEnableAmbient = true;
bEnableDiffuse = true; bEnableDiffuse = true;
bEnableSpecular = true; bEnableSpecular = true;
bEnableLightMap = true; bEnableLightMap = true;
bEnableDeferredLighting = false; bEnableDeferredLighting = false;
max_anisotropy = 4.0f; max_anisotropy = 4.0f;
ambient_intensity = Vector3::Zero(); ambient_intensity = Vector3::Zero();
light_intensity = Vector3::One(); light_intensity = Vector3::One();
perspective_fov = 45.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;
} }

View File

@@ -1,341 +1,341 @@
// //
// KRResource_obj.cpp // KRResource_obj.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-03-22. // Created by Kearwood Gilbert on 12-03-22.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRResource.h" #include "KRResource.h"
#include "KRMesh.h" #include "KRMesh.h"
std::vector<KRResource *> KRResource::LoadObj(KRContext &context, const std::string& path) std::vector<KRResource *> KRResource::LoadObj(KRContext &context, const std::string& path)
{ {
std::vector<KRResource *> resources; std::vector<KRResource *> resources;
KRMesh *new_mesh = new KRMesh(context, KRResource::GetFileBase(path)); KRMesh *new_mesh = new KRMesh(context, KRResource::GetFileBase(path));
resources.push_back(new_mesh); resources.push_back(new_mesh);
KRMesh::mesh_info mi; KRMesh::mesh_info mi;
std::vector<std::string> material_names_t; std::vector<std::string> material_names_t;
KRDataBlock data; KRDataBlock data;
char szSymbol[500][256]; char szSymbol[500][256];
int *pFaces = NULL; int *pFaces = NULL;
vector<KRMesh::pack_material *> m_materials; vector<KRMesh::pack_material *> m_materials;
if(data.load(path)) { if(data.load(path)) {
// -----=====----- Get counts -----=====----- // -----=====----- Get counts -----=====-----
int cVertexData = 0; int cVertexData = 0;
int cFaces = 1; int cFaces = 1;
int cMaterialFaceStart = 1; int cMaterialFaceStart = 1;
char *pScan = (char *)data.getStart(); char *pScan = (char *)data.getStart();
char *pEnd = (char *)data.getEnd(); char *pEnd = (char *)data.getEnd();
while(pScan < pEnd) { while(pScan < pEnd) {
// Scan through whitespace // Scan through whitespace
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) { while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
pScan++; pScan++;
} }
if(*pScan == '#') { if(*pScan == '#') {
// Line is a comment line // Line is a comment line
// Scan to the end of the line // Scan to the end of the line
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') { while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
pScan++; pScan++;
} }
} else { } else {
int cSymbols = 0; int cSymbols = 0;
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') { while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
char *pDest = szSymbol[cSymbols++]; char *pDest = szSymbol[cSymbols++];
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') { while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
*pDest++ = *pScan++; *pDest++ = *pScan++;
} }
*pDest = '\0'; *pDest = '\0';
// Scan through whitespace, but don't advance to next line // Scan through whitespace, but don't advance to next line
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) { while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
pScan++; pScan++;
} }
} }
if(strcmp(szSymbol[0], "v") == 0) { if(strcmp(szSymbol[0], "v") == 0) {
// Vertex (v) // Vertex (v)
} else if(strcmp(szSymbol[0], "vt") == 0) { } else if(strcmp(szSymbol[0], "vt") == 0) {
// Vertex Texture UV Coordinate (vt) // Vertex Texture UV Coordinate (vt)
} else if(strcmp(szSymbol[0], "vn") == 0) { } else if(strcmp(szSymbol[0], "vn") == 0) {
// Vertex Normal (vn) // Vertex Normal (vn)
} else if(strcmp(szSymbol[0], "f") == 0) { } else if(strcmp(szSymbol[0], "f") == 0) {
// Face (f) // Face (f)
int cFaceVertexes = (cSymbols - 3) * 3; // 3 vertexes per triangle. Triangles have 4 symbols. Quads have 5 symbols and generate two triangles. int cFaceVertexes = (cSymbols - 3) * 3; // 3 vertexes per triangle. Triangles have 4 symbols. Quads have 5 symbols and generate two triangles.
cVertexData += cFaceVertexes; cVertexData += cFaceVertexes;
cFaces += cFaceVertexes * 3 + 1; // Allocate space for count of vertices, Vertex Index, Texture Coordinate Index, and Normal Index cFaces += cFaceVertexes * 3 + 1; // Allocate space for count of vertices, Vertex Index, Texture Coordinate Index, and Normal Index
} else if(strcmp(szSymbol[0], "usemtl") == 0) { } else if(strcmp(szSymbol[0], "usemtl") == 0) {
// Use Material (usemtl) // Use Material (usemtl)
if(cMaterialFaceStart - cFaces > 0) { if(cMaterialFaceStart - cFaces > 0) {
cFaces++; cFaces++;
} }
material_names_t.push_back(std::string(szSymbol[1])); material_names_t.push_back(std::string(szSymbol[1]));
} }
} }
} }
// -----=====----- Populate vertexes and faces -----=====----- // -----=====----- Populate vertexes and faces -----=====-----
int *pFaces = (int *)malloc(sizeof(int) * (cFaces + 1)); int *pFaces = (int *)malloc(sizeof(int) * (cFaces + 1));
assert(pFaces != NULL); assert(pFaces != NULL);
std::vector<Vector3> indexed_vertices; std::vector<Vector3> indexed_vertices;
std::vector<Vector2> indexed_uva; std::vector<Vector2> indexed_uva;
std::vector<Vector3> indexed_normals; std::vector<Vector3> indexed_normals;
int *pFace = pFaces; int *pFace = pFaces;
int *pMaterialFaces = pFace++; int *pMaterialFaces = pFace++;
*pMaterialFaces = 0; *pMaterialFaces = 0;
// -------- // --------
pScan = (char *)data.getStart(); pScan = (char *)data.getStart();
while(pScan < pEnd) { while(pScan < pEnd) {
// Scan through whitespace // Scan through whitespace
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) { while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
pScan++; pScan++;
} }
if(*pScan == '#') { if(*pScan == '#') {
// Line is a comment line // Line is a comment line
// Scan to the end of the line // Scan to the end of the line
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') { while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
pScan++; pScan++;
} }
} else { } else {
int cSymbols = 0; int cSymbols = 0;
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') { while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
char *pDest = szSymbol[cSymbols++]; char *pDest = szSymbol[cSymbols++];
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') { while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
*pDest++ = *pScan++; *pDest++ = *pScan++;
} }
*pDest = '\0'; *pDest = '\0';
// Scan through whitespace, but don't advance to next line // Scan through whitespace, but don't advance to next line
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) { while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
pScan++; pScan++;
} }
} }
if(strcmp(szSymbol[0], "v") == 0) { if(strcmp(szSymbol[0], "v") == 0) {
// Vertex (v) // Vertex (v)
float x, y, z; float x, y, z;
char *pChar = szSymbol[1]; char *pChar = szSymbol[1];
x = strtof(pChar, &pChar); x = strtof(pChar, &pChar);
pChar = szSymbol[2]; pChar = szSymbol[2];
y = strtof(pChar, &pChar); y = strtof(pChar, &pChar);
pChar = szSymbol[3]; pChar = szSymbol[3];
z = strtof(pChar, &pChar); z = strtof(pChar, &pChar);
indexed_vertices.push_back(Vector3(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;
} }

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@@ -1,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 &current_lod_max_dim, bool compress, bool premultiply_alpha) bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, bool compress, bool premultiply_alpha)
{ {
m_pData->lock(); m_pData->lock();
TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart(); TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart();
unsigned char *pData = (unsigned char *)pHeader + (long)pHeader->idlength + (long)pHeader->colourmaplength * (long)pHeader->colourmaptype + sizeof(TGA_HEADER); unsigned char *pData = (unsigned char *)pHeader + (long)pHeader->idlength + (long)pHeader->colourmaplength * (long)pHeader->colourmaptype + sizeof(TGA_HEADER);
GLenum internal_format = GL_RGBA; GLenum internal_format = GL_RGBA;
#if !TARGET_OS_IPHONE #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";
} }

View File

@@ -1,264 +1,264 @@
// //
// KRViewport.cpp // KRViewport.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-10-25. // Created by Kearwood Gilbert on 2012-10-25.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#define KRENGINE_SWAP_INT(x,y) {int t;t=x;x=y;y=t;} #define KRENGINE_SWAP_INT(x,y) {int t;t=x;x=y;y=t;}
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRViewport.h" #include "KRViewport.h"
KRViewport::KRViewport() KRViewport::KRViewport()
{ {
m_size = Vector2::One(); m_size = Vector2::One();
m_matProjection = Matrix4(); m_matProjection = Matrix4();
m_matView = Matrix4(); m_matView = Matrix4();
m_lodBias = 0.0f; m_lodBias = 0.0f;
calculateDerivedValues(); calculateDerivedValues();
} }
KRViewport::KRViewport(const Vector2 &size, const Matrix4 &matView, const Matrix4 &matProjection) KRViewport::KRViewport(const Vector2 &size, const Matrix4 &matView, const Matrix4 &matProjection)
{ {
m_size = size; m_size = size;
m_matView = matView; m_matView = matView;
m_matProjection = matProjection; m_matProjection = matProjection;
calculateDerivedValues(); calculateDerivedValues();
} }
KRViewport& KRViewport::operator=(const KRViewport &v) { KRViewport& KRViewport::operator=(const KRViewport &v) {
if(this != &v) { // Prevent self-assignment. if(this != &v) { // Prevent self-assignment.
m_size = v.m_size; m_size = v.m_size;
m_matProjection = v.m_matProjection; m_matProjection = v.m_matProjection;
m_matView = v.m_matView; m_matView = v.m_matView;
m_lodBias = v.m_lodBias; m_lodBias = v.m_lodBias;
calculateDerivedValues(); calculateDerivedValues();
} }
return *this; return *this;
} }
KRViewport::~KRViewport() KRViewport::~KRViewport()
{ {
} }
const Vector2 &KRViewport::getSize() const const Vector2 &KRViewport::getSize() const
{ {
return m_size; return m_size;
} }
const Matrix4 &KRViewport::getViewMatrix() const const Matrix4 &KRViewport::getViewMatrix() const
{ {
return m_matView; return m_matView;
} }
const Matrix4 &KRViewport::getProjectionMatrix() const const Matrix4 &KRViewport::getProjectionMatrix() const
{ {
return m_matProjection; return m_matProjection;
} }
void KRViewport::setSize(const Vector2 &size) void KRViewport::setSize(const Vector2 &size)
{ {
m_size = size; m_size = size;
} }
void KRViewport::setViewMatrix(const Matrix4 &matView) void KRViewport::setViewMatrix(const Matrix4 &matView)
{ {
m_matView = matView; m_matView = matView;
calculateDerivedValues(); calculateDerivedValues();
} }
void KRViewport::setProjectionMatrix(const Matrix4 &matProjection) void KRViewport::setProjectionMatrix(const Matrix4 &matProjection)
{ {
m_matProjection = matProjection; m_matProjection = matProjection;
calculateDerivedValues(); calculateDerivedValues();
} }
const Matrix4 &KRViewport::KRViewport::getViewProjectionMatrix() const const Matrix4 &KRViewport::KRViewport::getViewProjectionMatrix() const
{ {
return m_matViewProjection; return m_matViewProjection;
} }
const Matrix4 &KRViewport::getInverseViewMatrix() const const Matrix4 &KRViewport::getInverseViewMatrix() const
{ {
return m_matInverseView; return m_matInverseView;
} }
const Matrix4 &KRViewport::getInverseProjectionMatrix() const const Matrix4 &KRViewport::getInverseProjectionMatrix() const
{ {
return m_matInverseProjection; return m_matInverseProjection;
} }
const Vector3 &KRViewport::getCameraDirection() const const Vector3 &KRViewport::getCameraDirection() const
{ {
return m_cameraDirection; return m_cameraDirection;
} }
const Vector3 &KRViewport::getCameraPosition() const const Vector3 &KRViewport::getCameraPosition() const
{ {
return m_cameraPosition; return m_cameraPosition;
} }
const int *KRViewport::getFrontToBackOrder() const const int *KRViewport::getFrontToBackOrder() const
{ {
return &m_frontToBackOrder[0]; return &m_frontToBackOrder[0];
} }
const int *KRViewport::getBackToFrontOrder() const const int *KRViewport::getBackToFrontOrder() const
{ {
return &m_backToFrontOrder[0]; return &m_backToFrontOrder[0];
} }
void KRViewport::calculateDerivedValues() void KRViewport::calculateDerivedValues()
{ {
m_matViewProjection = m_matView * m_matProjection; m_matViewProjection = m_matView * m_matProjection;
m_matInverseView = Matrix4::Invert(m_matView); m_matInverseView = Matrix4::Invert(m_matView);
m_matInverseProjection = Matrix4::Invert(m_matProjection); m_matInverseProjection = Matrix4::Invert(m_matProjection);
m_cameraPosition = Matrix4::Dot(m_matInverseView, Vector3::Zero()); m_cameraPosition = Matrix4::Dot(m_matInverseView, Vector3::Zero());
m_cameraDirection = Matrix4::Dot(m_matInverseView, Vector3(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;
} }

View File

@@ -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

View File

@@ -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 &center, 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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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 &center, 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) */

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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