Performance Optimizes

Small bug fixes
Implemented KRVector4
This commit is contained in:
2013-04-24 12:48:55 -07:00
parent 0d7cb8b315
commit e6207fbb83
29 changed files with 1115 additions and 269 deletions

View File

@@ -315,6 +315,10 @@
E4E6F6BF16BA5E0A00E410F8 /* volumetric_fog_osx.fsh in Resources */ = {isa = PBXBuildFile; fileRef = E4E6F62916BA5D8300E410F8 /* volumetric_fog_osx.fsh */; };
E4E6F6C016BA5E0A00E410F8 /* volumetric_fog_osx.vsh in Resources */ = {isa = PBXBuildFile; fileRef = E4E6F62A16BA5D8300E410F8 /* volumetric_fog_osx.vsh */; };
E4EC73B8171F32780065299F /* forsyth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4FE6AAA16B21D7E0058B8CE /* forsyth.cpp */; };
E4EC73C11720B1FF0065299F /* KRVector4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4EC73BF1720B1FF0065299F /* KRVector4.cpp */; };
E4EC73C21720B1FF0065299F /* KRVector4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4EC73BF1720B1FF0065299F /* KRVector4.cpp */; };
E4EC73C31720B1FF0065299F /* KRVector4.h in Headers */ = {isa = PBXBuildFile; fileRef = E4EC73C01720B1FF0065299F /* KRVector4.h */; };
E4EC73C41720B1FF0065299F /* KRVector4.h in Headers */ = {isa = PBXBuildFile; fileRef = E4EC73C01720B1FF0065299F /* KRVector4.h */; };
E4F027C716979CCD00D4427D /* KRAudioManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4F027C516979CCD00D4427D /* KRAudioManager.cpp */; };
E4F027C816979CCD00D4427D /* KRAudioManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4F027C516979CCD00D4427D /* KRAudioManager.cpp */; };
E4F027C916979CCD00D4427D /* KRAudioManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F027C616979CCD00D4427D /* KRAudioManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -582,6 +586,8 @@
E4E6F66416BA5D9400E410F8 /* volumetric_fog_downsampled.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = volumetric_fog_downsampled.vsh; sourceTree = "<group>"; };
E4E6F66516BA5D9400E410F8 /* volumetric_fog.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = volumetric_fog.fsh; sourceTree = "<group>"; };
E4E6F66616BA5D9400E410F8 /* volumetric_fog.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = volumetric_fog.vsh; sourceTree = "<group>"; };
E4EC73BF1720B1FF0065299F /* KRVector4.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KRVector4.cpp; sourceTree = "<group>"; };
E4EC73C01720B1FF0065299F /* KRVector4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRVector4.h; sourceTree = "<group>"; };
E4F027C516979CCD00D4427D /* KRAudioManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = KRAudioManager.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
E4F027C616979CCD00D4427D /* KRAudioManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = KRAudioManager.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
E4F027CC16979CE200D4427D /* KRAudioSample.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = KRAudioSample.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
@@ -784,6 +790,8 @@
E42CB1EF158446AB0066E0D8 /* KRQuaternion.cpp */,
E40BA45215EFF79500D7C3DD /* KRAABB.cpp */,
E40BA45315EFF79500D7C3DD /* KRAABB.h */,
E4EC73BF1720B1FF0065299F /* KRVector4.cpp */,
E4EC73C01720B1FF0065299F /* KRVector4.h */,
);
name = Math;
sourceTree = "<group>";
@@ -1220,6 +1228,7 @@
E450273B16E0491D00FDEC5C /* KRReverbZone.h in Headers */,
E4FE6AA816B21D660058B8CE /* forsyth.h in Headers */,
E4AE635F1704FB0A00B460CD /* KRLODGroup.h in Headers */,
E4EC73C31720B1FF0065299F /* KRVector4.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1296,6 +1305,7 @@
E4AE63601704FB0A00B460CD /* KRLODGroup.h in Headers */,
E499BF1F16AE753E007FCDBE /* KRCollider.h in Headers */,
E499BF2316AE7636007FCDBE /* kraken-prefix.pch in Headers */,
E4EC73C41720B1FF0065299F /* KRVector4.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1558,6 +1568,7 @@
E4FE6AAB16B21D7E0058B8CE /* forsyth.cpp in Sources */,
E450273916E0491D00FDEC5C /* KRReverbZone.cpp in Sources */,
E4AE635D1704FB0A00B460CD /* KRLODGroup.cpp in Sources */,
E4EC73C11720B1FF0065299F /* KRVector4.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1631,6 +1642,7 @@
E4943232169E08D200BCB891 /* KRAmbientZone.cpp in Sources */,
E450273A16E0491D00FDEC5C /* KRReverbZone.cpp in Sources */,
E4AE635E1704FB0A00B460CD /* KRLODGroup.cpp in Sources */,
E4EC73C21720B1FF0065299F /* KRVector4.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -71,7 +71,7 @@ bool KRAABB::operator !=(const KRAABB& b) const
KRVector3 KRAABB::center() const
{
return (min + max) / 2.0f;
return (min + max) * 0.5f;
}
KRVector3 KRAABB::size() const
@@ -155,86 +155,6 @@ KRAABB KRAABB::Zero()
return KRAABB(KRVector3::Zero(), KRVector3::Zero());
}
bool KRAABB::visible(const KRMat4 &matViewProjection) const
{
// test if bounding box would be within the visible range of the clip space transformed by matViewProjection
// This is used for view frustrum culling
int outside_count[6] = {0, 0, 0, 0, 0, 0};
for(int iCorner=0; iCorner<8; iCorner++) {
KRVector3 sourceCornerVertex = KRVector3(
(iCorner & 1) == 0 ? min.x : max.x,
(iCorner & 2) == 0 ? min.y : max.y,
(iCorner & 4) == 0 ? min.z : max.z);
KRVector3 cornerVertex = KRMat4::Dot(matViewProjection, sourceCornerVertex);
float cornerVertexW = KRMat4::DotW(matViewProjection, sourceCornerVertex);
if(cornerVertex.x < -cornerVertexW) {
outside_count[0]++;
}
if(cornerVertex.y < -cornerVertexW) {
outside_count[1]++;
}
if(cornerVertex.z < -cornerVertexW) {
outside_count[2]++;
}
if(cornerVertex.x > cornerVertexW) {
outside_count[3]++;
}
if(cornerVertex.y > cornerVertexW) {
outside_count[4]++;
}
if(cornerVertex.z > cornerVertexW) {
outside_count[5]++;
}
}
bool is_visible = true;
for(int iFace=0; iFace < 6; iFace++) {
if(outside_count[iFace] == 8) {
is_visible = false;
}
}
if(!is_visible) {
//fprintf(stderr, "AABB culled: %i%i%i%i%i%i out, (%f, %f, %f) - (%f, %f, %f)\n", outside_count[0], outside_count[1], outside_count[2], outside_count[3], outside_count[4], outside_count[5], min.x, min.y, min.z, max.x, max.y, max.z);
} else {
//fprintf(stderr, "AABB visible: %i%i%i%i%i%i out, (%f, %f, %f) - (%f, %f, %f)\n", outside_count[0], outside_count[1], outside_count[2], outside_count[3], outside_count[4], outside_count[5], min.x, min.y, min.z, max.x, max.y, max.z);
}
//is_visible = true;
return is_visible;
}
float KRAABB::coverage(const KRMat4 &matVP, const KRVector2 viewportSize) const
{
if(!visible(matVP)) {
return 0.0f; // Culled out by view frustrum
} else {
KRVector2 screen_min;
KRVector2 screen_max;
// Loop through all corners and transform them to screen space
for(int i=0; i<8; i++) {
KRVector3 screen_pos = KRMat4::DotWDiv(matVP, KRVector3(i & 1 ? min.x : max.x, i & 2 ? min.y : max.y, i & 4 ? min.z : max.z));
if(i==0) {
screen_min.x = screen_pos.x;
screen_min.y = screen_pos.y;
screen_max.x = screen_pos.x;
screen_max.y = screen_pos.y;
} else {
if(screen_pos.x < screen_min.x) screen_min.x = screen_pos.x;
if(screen_pos.y < screen_min.y) screen_min.y = screen_pos.y;
if(screen_pos.x > screen_max.x) screen_max.x = screen_pos.x;
if(screen_pos.y > screen_max.y) screen_max.y = screen_pos.y;
}
}
return (screen_max.x - screen_min.x) * (screen_max.y - screen_min.y);
}
}
float KRAABB::longest_radius() const
{
float radius1 = (center() - min).magnitude();

View File

@@ -32,7 +32,7 @@ public:
bool intersects(const KRAABB& b) const;
bool contains(const KRAABB &b) const;
bool contains(const KRVector3 &v) const;
bool visible(const KRMat4 &matViewProjection) const;
bool intersectsLine(const KRVector3 &v1, const KRVector3 &v2) const;
bool intersectsRay(const KRVector3 &v1, const KRVector3 &dir) const;
void encapsulate(const KRAABB & b);
@@ -50,7 +50,7 @@ public:
static KRAABB Infinite();
static KRAABB Zero();
float coverage(const KRMat4 &matVP, const KRVector2 viewportSize) const;
float longest_radius() const;
KRVector3 nearestPoint(const KRVector3 & v) const;
};

View File

@@ -442,7 +442,7 @@ void KRCamera::renderFrame(float deltaTime, GLint renderBufferWidth, GLint rende
m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_3D_CUBE, KRENGINE_VBO_3D_CUBE_SIZE, NULL, 0, true, false, false, false, false, false, false, true);
for(std::map<KRAABB, int>::iterator itr=m_viewport.getVisibleBounds().begin(); itr != m_viewport.getVisibleBounds().end(); itr++) {
KRMat4 matModel = KRMat4();
matModel.scale((*itr).first.size() / 2.0f);
matModel.scale((*itr).first.size() * 0.5f);
matModel.translate((*itr).first.center());
if(getContext().getShaderManager()->selectShader(*this, pVisShader, m_viewport, matModel, std::vector<KRLight *>(), 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) {

View File

@@ -183,8 +183,8 @@ void KRLight::render(KRCamera *pCamera, std::vector<KRLight *> &lights, const KR
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES && pCamera->settings.dust_particle_enable) {
// Render brownian particles for dust floating in air
if(m_cShadowBuffers >= 1 && shadowValid[0] && m_dust_particle_density > 0.0f && m_dust_particle_size > 0.0f && m_dust_particle_intensity > 0.0f) {
float lod_coverage = getBounds().coverage(viewport.getViewProjectionMatrix(), viewport.getSize()); // This also checks the view frustrum culling
if(lod_coverage > 0.0f || true) { // FINDME, HACK need to remove "|| true"?
if(viewport.visible(getBounds()) || true) { // FINDME, HACK need to remove "|| true"?
float particle_range = 600.0f;
@@ -299,7 +299,7 @@ void KRLight::render(KRCamera *pCamera, std::vector<KRLight *> &lights, const KR
if(params) {
if(!m_pFlareTexture && m_flareTexture.size()) {
m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture.c_str());
m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture);
}
if(m_pFlareTexture) {

View File

@@ -126,7 +126,7 @@ void KRMat4::perspective(GLfloat fov, GLfloat aspect, GLfloat nearz, GLfloat far
memset(m_mat, 0, sizeof(GLfloat) * 16);
GLfloat range= tan(fov / 2.0f) * nearz;
GLfloat range= tan(fov * 0.5) * nearz;
m_mat[0] = (2 * nearz) / ((range * aspect) - (-range * aspect));
m_mat[5] = (2 * nearz) / (2 * range);
m_mat[10] = -(farz + nearz) / (farz - nearz);

View File

@@ -217,19 +217,19 @@ bool KRMaterial::bind(KRMaterial **prevBoundMaterial, char *szPrevShaderKey, KRC
bool bLightMap = pLightMap && pCamera->settings.bEnableLightMap;
if(!m_pAmbientMap && m_ambientMap.size()) {
m_pAmbientMap = getContext().getTextureManager()->getTexture(m_ambientMap.c_str());
m_pAmbientMap = getContext().getTextureManager()->getTexture(m_ambientMap);
}
if(!m_pDiffuseMap && m_diffuseMap.size()) {
m_pDiffuseMap = getContext().getTextureManager()->getTexture(m_diffuseMap.c_str());
m_pDiffuseMap = getContext().getTextureManager()->getTexture(m_diffuseMap);
}
if(!m_pNormalMap && m_normalMap.size()) {
m_pNormalMap = getContext().getTextureManager()->getTexture(m_normalMap.c_str());
m_pNormalMap = getContext().getTextureManager()->getTexture(m_normalMap);
}
if(!m_pSpecularMap && m_specularMap.size()) {
m_pSpecularMap = getContext().getTextureManager()->getTexture(m_specularMap.c_str());
m_pSpecularMap = getContext().getTextureManager()->getTexture(m_specularMap);
}
if(!m_pReflectionMap && m_reflectionMap.size()) {
m_pReflectionMap = getContext().getTextureManager()->getTexture(m_reflectionMap.c_str());
m_pReflectionMap = getContext().getTextureManager()->getTexture(m_reflectionMap);
}
if(!m_pReflectionCube && m_reflectionCube.size()) {
m_pReflectionCube = getContext().getTextureManager()->getTextureCube(m_reflectionCube.c_str());

View File

@@ -38,6 +38,7 @@
#include "KRShader.h"
#include "KRShaderManager.h"
#include "KRContext.h"
#include "forsyth.h"
KRMesh::KRMesh(KRContext &context, std::string name) : KRResource(context, name) {
@@ -135,11 +136,10 @@ void KRMesh::render(const std::string &object_name, KRCamera *pCamera, std::vect
//fprintf(stderr, "Rendering model: %s\n", m_name.c_str());
if(renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) {
getSubmeshes();
if(m_materials.size() == 0) {
vector<KRMesh::Submesh *> submeshes = getSubmeshes();
for(std::vector<KRMesh::Submesh *>::iterator itr = submeshes.begin(); itr != submeshes.end(); itr++) {
for(std::vector<KRMesh::Submesh *>::iterator itr = m_submeshes.begin(); itr != m_submeshes.end(); itr++) {
const char *szMaterialName = (*itr)->szMaterialName;
KRMaterial *pMaterial = getContext().getMaterialManager()->getMaterial(szMaterialName);
m_materials.push_back(pMaterial);
@@ -162,7 +162,7 @@ void KRMesh::render(const std::string &object_name, KRCamera *pCamera, std::vect
KRMaterial *pPrevBoundMaterial = NULL;
char szPrevShaderKey[256];
szPrevShaderKey[0] = '\0';
int cSubmeshes = getSubmeshes().size();
int cSubmeshes = m_submeshes.size();
if(renderPass == KRNode::RENDER_PASS_SHADOWMAP) {
for(int iSubmesh=0; iSubmesh<cSubmeshes; iSubmesh++) {
KRMaterial *pMaterial = m_materials[iSubmesh];
@@ -228,7 +228,7 @@ bool KRMesh::hasTransparency() {
}
vector<KRMesh::Submesh *> KRMesh::getSubmeshes() {
void KRMesh::getSubmeshes() {
if(m_submeshes.size() == 0) {
pack_header *pHeader = getHeader();
pack_material *pPackMaterials = (pack_material *)(pHeader+1);
@@ -246,87 +246,106 @@ vector<KRMesh::Submesh *> KRMesh::getSubmeshes() {
m_submeshes.push_back(pSubmesh);
}
}
return m_submeshes;
}
void KRMesh::renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const std::string &object_name, const std::string &material_name) {
unsigned char *pVertexData = getVertexData();
pack_header *pHeader = getHeader();
int cBuffers = (pHeader->vertex_count + MAX_VBO_SIZE - 1) / MAX_VBO_SIZE;
vector<KRMesh::Submesh *> submeshes = getSubmeshes();
Submesh *pSubmesh = submeshes[iSubmesh];
int iVertex = pSubmesh->start_vertex;
int iBuffer = iVertex / MAX_VBO_SIZE;
iVertex = iVertex % MAX_VBO_SIZE;
getSubmeshes();
Submesh *pSubmesh = m_submeshes[iSubmesh];
int cVertexes = pSubmesh->vertex_count;
while(cVertexes > 0) {
GLsizei cBufferVertexes = iBuffer < cBuffers - 1 ? MAX_VBO_SIZE : pHeader->vertex_count % MAX_VBO_SIZE;
int vertex_size = m_vertex_size;
void *vbo_end = (unsigned char *)pVertexData + iBuffer * MAX_VBO_SIZE * vertex_size + vertex_size * cBufferVertexes;
void *buffer_end = m_pData->getEnd();
assert(vbo_end <= buffer_end);
assert(cBufferVertexes <= 65535);
// fprintf(stderr, "start - object: %s material: %s vertices: %i\n", object_name.c_str(), material_name.c_str(), cVertexes);
unsigned char *pVertexData = getVertexData();
pack_header *pHeader = getHeader();
m_pContext->getModelManager()->bindVBO((unsigned char *)pVertexData + iBuffer * MAX_VBO_SIZE * vertex_size, vertex_size * cBufferVertexes, NULL, 0, has_vertex_attribute(KRENGINE_ATTRIB_VERTEX), has_vertex_attribute(KRENGINE_ATTRIB_NORMAL), has_vertex_attribute(KRENGINE_ATTRIB_TANGENT), has_vertex_attribute(KRENGINE_ATTRIB_TEXUVA), has_vertex_attribute(KRENGINE_ATTRIB_TEXUVB), has_vertex_attribute(KRENGINE_ATTRIB_BONEINDEXES),
has_vertex_attribute(KRENGINE_ATTRIB_BONEWEIGHTS), true);
if(getModelFormat() == KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES) {
if(iVertex + cVertexes >= MAX_VBO_SIZE) {
assert(iVertex + (MAX_VBO_SIZE - iVertex) <= cBufferVertexes);
switch (getModelFormat()) {
case KRENGINE_MODEL_FORMAT_TRIANGLES:
GLDEBUG(glDrawArrays(GL_TRIANGLES, iVertex, (MAX_VBO_SIZE - iVertex)));
break;
case KRENGINE_MODEL_FORMAT_STRIP:
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, iVertex, (MAX_VBO_SIZE - iVertex)));
break;
case KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES:
GLDEBUG(glDrawArrays(GL_TRIANGLES, iVertex, (MAX_VBO_SIZE - iVertex)));
break;
case KRENGINE_MODEL_FORMAT_INDEXED_STRIP:
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, iVertex, (MAX_VBO_SIZE - iVertex)));
break;
default:
break;
}
m_pContext->getModelManager()->log_draw_call(renderPass, object_name, material_name, (MAX_VBO_SIZE - iVertex));
cVertexes -= (MAX_VBO_SIZE - iVertex);
iVertex = 0;
iBuffer++;
} else {
assert(iVertex + cVertexes <= cBufferVertexes);
switch (getModelFormat()) {
case KRENGINE_MODEL_FORMAT_TRIANGLES:
GLDEBUG(glDrawArrays(GL_TRIANGLES, iVertex, cVertexes));
break;
case KRENGINE_MODEL_FORMAT_STRIP:
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, iVertex, cVertexes));
break;
default:
break;
}
m_pContext->getModelManager()->log_draw_call(renderPass, object_name, material_name, cVertexes);
__uint16_t *index_data = getIndexData();
int submesh_index_group = 0;
while(cVertexes > 0) {
cVertexes = 0;
int start_index_offset, start_vertex_offset, index_count, vertex_count;
getIndexedRange(iSubmesh, submesh_index_group++, start_index_offset, start_vertex_offset, index_count, vertex_count);
m_pContext->getModelManager()->bindVBO((unsigned char *)pVertexData + start_vertex_offset * m_vertex_size, m_vertex_size * vertex_count, index_data + start_index_offset, index_count * 4, has_vertex_attribute(KRENGINE_ATTRIB_VERTEX), has_vertex_attribute(KRENGINE_ATTRIB_NORMAL), has_vertex_attribute(KRENGINE_ATTRIB_TANGENT), has_vertex_attribute(KRENGINE_ATTRIB_TEXUVA), has_vertex_attribute(KRENGINE_ATTRIB_TEXUVB), has_vertex_attribute(KRENGINE_ATTRIB_BONEINDEXES), has_vertex_attribute(KRENGINE_ATTRIB_BONEWEIGHTS), true);
glDrawElements(GL_TRIANGLES, index_count, GL_UNSIGNED_SHORT, 0);
m_pContext->getModelManager()->log_draw_call(renderPass, object_name, material_name, index_count);
cVertexes -= index_count;
}
} else {
int cBuffers = (pHeader->vertex_count + MAX_VBO_SIZE - 1) / MAX_VBO_SIZE;
int iVertex = pSubmesh->start_vertex;
int iBuffer = iVertex / MAX_VBO_SIZE;
iVertex = iVertex % MAX_VBO_SIZE;
while(cVertexes > 0) {
GLsizei cBufferVertexes = iBuffer < cBuffers - 1 ? MAX_VBO_SIZE : pHeader->vertex_count % MAX_VBO_SIZE;
int vertex_size = m_vertex_size;
void *vbo_end = (unsigned char *)pVertexData + iBuffer * MAX_VBO_SIZE * vertex_size + vertex_size * cBufferVertexes;
void *buffer_end = m_pData->getEnd();
assert(vbo_end <= buffer_end);
assert(cBufferVertexes <= 65535);
m_pContext->getModelManager()->bindVBO((unsigned char *)pVertexData + iBuffer * MAX_VBO_SIZE * vertex_size, vertex_size * cBufferVertexes, NULL, 0, has_vertex_attribute(KRENGINE_ATTRIB_VERTEX), has_vertex_attribute(KRENGINE_ATTRIB_NORMAL), has_vertex_attribute(KRENGINE_ATTRIB_TANGENT), has_vertex_attribute(KRENGINE_ATTRIB_TEXUVA), has_vertex_attribute(KRENGINE_ATTRIB_TEXUVB), has_vertex_attribute(KRENGINE_ATTRIB_BONEINDEXES), has_vertex_attribute(KRENGINE_ATTRIB_BONEWEIGHTS), true);
if(iVertex + cVertexes >= MAX_VBO_SIZE) {
assert(iVertex + (MAX_VBO_SIZE - iVertex) <= cBufferVertexes);
switch (getModelFormat()) {
case KRENGINE_MODEL_FORMAT_TRIANGLES:
GLDEBUG(glDrawArrays(GL_TRIANGLES, iVertex, (MAX_VBO_SIZE - iVertex)));
break;
case KRENGINE_MODEL_FORMAT_STRIP:
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, iVertex, (MAX_VBO_SIZE - iVertex)));
break;
case KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES:
GLDEBUG(glDrawArrays(GL_TRIANGLES, iVertex, (MAX_VBO_SIZE - iVertex)));
break;
case KRENGINE_MODEL_FORMAT_INDEXED_STRIP:
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, iVertex, (MAX_VBO_SIZE - iVertex)));
break;
default:
break;
}
m_pContext->getModelManager()->log_draw_call(renderPass, object_name, material_name, (MAX_VBO_SIZE - iVertex));
cVertexes -= (MAX_VBO_SIZE - iVertex);
iVertex = 0;
iBuffer++;
} else {
assert(iVertex + cVertexes <= cBufferVertexes);
switch (getModelFormat()) {
case KRENGINE_MODEL_FORMAT_TRIANGLES:
GLDEBUG(glDrawArrays(GL_TRIANGLES, iVertex, cVertexes));
break;
case KRENGINE_MODEL_FORMAT_STRIP:
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, iVertex, cVertexes));
break;
default:
break;
}
m_pContext->getModelManager()->log_draw_call(renderPass, object_name, material_name, cVertexes);
cVertexes = 0;
}
}
}
// fprintf(stderr, "end object\n");
}
void KRMesh::LoadData(std::vector<KRVector3> vertices, std::vector<KRVector2> uva, std::vector<KRVector2> uvb, std::vector<KRVector3> normals, std::vector<KRVector3> tangents, std::vector<int> submesh_starts, std::vector<int> submesh_lengths, std::vector<std::string> material_names, std::vector<std::string> bone_names, std::vector<std::vector<int> > bone_indexes, std::vector<std::vector<float> > bone_weights, KRMesh::model_format_t model_format) {
void KRMesh::LoadData(std::vector<__uint16_t> vertex_indexes, std::vector<std::pair<int, int> > vertex_index_bases, std::vector<KRVector3> vertices, std::vector<KRVector2> uva, std::vector<KRVector2> uvb, std::vector<KRVector3> normals, std::vector<KRVector3> tangents, std::vector<int> submesh_starts, std::vector<int> submesh_lengths, std::vector<std::string> material_names, std::vector<std::string> bone_names, std::vector<std::vector<int> > bone_indexes, std::vector<std::vector<float> > bone_weights, KRMesh::model_format_t model_format, bool calculate_normals, bool calculate_tangents) {
clearData();
bool calculate_normals = true;
bool calculate_tangents = true;
__int32_t vertex_attrib_flags = 0;
if(vertices.size()) {
@@ -348,11 +367,13 @@ void KRMesh::LoadData(std::vector<KRVector3> vertices, std::vector<KRVector2> uv
vertex_attrib_flags += (1 << KRENGINE_ATTRIB_BONEINDEXES) + (1 << KRENGINE_ATTRIB_BONEWEIGHTS);
}
size_t vertex_size = VertexSizeForAttributes(vertex_attrib_flags);
size_t index_count = 0;
size_t index_count = vertex_indexes.size();
size_t index_base_count = vertex_index_bases.size();
size_t submesh_count = submesh_lengths.size();
size_t vertex_count = vertices.size();
size_t bone_count = bone_names.size();
size_t new_file_size = sizeof(pack_header) + sizeof(pack_material) * submesh_count + sizeof(pack_bone) * bone_count + KRALIGN(2 * index_count) + vertex_size * vertex_count;
size_t new_file_size = sizeof(pack_header) + sizeof(pack_material) * submesh_count + sizeof(pack_bone) * bone_count + KRALIGN(2 * index_count) + KRALIGN(8 * index_base_count) + vertex_size * vertex_count;
m_pData->expand(new_file_size);
pack_header *pHeader = getHeader();
@@ -362,8 +383,9 @@ void KRMesh::LoadData(std::vector<KRVector3> vertices, std::vector<KRVector2> uv
pHeader->vertex_count = (__int32_t)vertex_count;
pHeader->bone_count = (__int32_t)bone_count;
pHeader->index_count = (__int32_t)index_count;
pHeader->index_base_count = (__int32_t)index_base_count;
pHeader->model_format = model_format;
strcpy(pHeader->szTag, "KROBJPACK1.1 ");
strcpy(pHeader->szTag, "KROBJPACK1.2 ");
updateAttributeOffsets();
pack_material *pPackMaterials = (pack_material *)(pHeader+1);
@@ -384,8 +406,6 @@ void KRMesh::LoadData(std::vector<KRVector3> vertices, std::vector<KRVector2> uv
bool bFirstVertex = true;
// VertexData *pVertexData = (VertexData *)(pPackMaterials + pHeader->submesh_count);
// VertexData *pVertex = pVertexData;
memset(getVertexData(), 0, m_vertex_size * vertices.size());
for(int iVertex=0; iVertex < vertices.size(); iVertex++) {
KRVector3 source_vertex = vertices[iVertex];
@@ -430,54 +450,69 @@ void KRMesh::LoadData(std::vector<KRVector3> vertices, std::vector<KRVector2> uv
pHeader->maxz = m_maxPoint.z;
// Calculate missing surface normals and tangents
//cout << " Calculate surface normals and tangents\n";
__uint16_t *index_data = getIndexData();
for(std::vector<__uint16_t>::iterator itr=vertex_indexes.begin(); itr != vertex_indexes.end(); itr++) {
*index_data++ = *itr;
}
for(int iVertex=0; iVertex < vertices.size(); iVertex+= 3) {
KRVector3 p1 = getVertexPosition(iVertex);
KRVector3 p2 = getVertexPosition(iVertex+1);
KRVector3 p3 = getVertexPosition(iVertex+2);
KRVector3 v1 = p2 - p1;
KRVector3 v2 = p3 - p1;
__uint32_t *index_base_data = getIndexBaseData();
for(std::vector<std::pair<int, int> >::iterator itr=vertex_index_bases.begin(); itr != vertex_index_bases.end(); itr++) {
*index_base_data++ = (*itr).first;
*index_base_data++ = (*itr).second;
}
if(getModelFormat() == KRENGINE_MODEL_FORMAT_TRIANGLES) {
// Calculate missing surface normals and tangents
//cout << " Calculate surface normals and tangents\n";
if(calculate_normals || calculate_tangents) {
// NOTE: This will not work properly if the vertices are already indexed
for(int iVertex=0; iVertex < vertices.size(); iVertex+= 3) {
KRVector3 p1 = getVertexPosition(iVertex);
KRVector3 p2 = getVertexPosition(iVertex+1);
KRVector3 p3 = getVertexPosition(iVertex+2);
KRVector3 v1 = p2 - p1;
KRVector3 v2 = p3 - p1;
// -- Calculate normal if missing --
if(calculate_normals) {
KRVector3 first_normal = getVertexNormal(iVertex);
if(first_normal.x == 0.0f && first_normal.y == 0.0f && first_normal.z == 0.0f) {
// Note - We don't take into consideration smoothing groups or smoothing angles when generating normals; all generated normals represent flat shaded polygons
KRVector3 normal = KRVector3::Cross(v1, v2);
// -- Calculate normal if missing --
if(calculate_normals) {
KRVector3 first_normal = getVertexNormal(iVertex);
if(first_normal.x == 0.0f && first_normal.y == 0.0f && first_normal.z == 0.0f) {
// Note - We don't take into consideration smoothing groups or smoothing angles when generating normals; all generated normals represent flat shaded polygons
KRVector3 normal = KRVector3::Cross(v1, v2);
normal.normalize();
setVertexNormal(iVertex, normal);
setVertexNormal(iVertex+1, normal);
setVertexNormal(iVertex+2, normal);
}
}
normal.normalize();
setVertexNormal(iVertex, normal);
setVertexNormal(iVertex+1, normal);
setVertexNormal(iVertex+2, normal);
}
}
// -- Calculate tangent vector for normal mapping --
if(calculate_tangents) {
KRVector3 first_tangent = getVertexTangent(iVertex);
if(first_tangent.x == 0.0f && first_tangent.y == 0.0f && first_tangent.z == 0.0f) {
// -- Calculate tangent vector for normal mapping --
if(calculate_tangents) {
KRVector3 first_tangent = getVertexTangent(iVertex);
if(first_tangent.x == 0.0f && first_tangent.y == 0.0f && first_tangent.z == 0.0f) {
KRVector2 uv0 = getVertexUVA(iVertex);
KRVector2 uv1 = getVertexUVA(iVertex + 1);
KRVector2 uv2 = getVertexUVA(iVertex + 2);
KRVector2 uv0 = getVertexUVA(iVertex);
KRVector2 uv1 = getVertexUVA(iVertex + 1);
KRVector2 uv2 = getVertexUVA(iVertex + 2);
KRVector2 st1 = KRVector2(uv1.x - uv0.x, uv1.y - uv0.y);
KRVector2 st2 = KRVector2(uv2.x - uv0.x, uv2.y - uv0.y);
double coef = 1/ (st1.x * st2.y - st2.x * st1.y);
KRVector2 st1 = KRVector2(uv1.x - uv0.x, uv1.y - uv0.y);
KRVector2 st2 = KRVector2(uv2.x - uv0.x, uv2.y - uv0.y);
double coef = 1/ (st1.x * st2.y - st2.x * st1.y);
KRVector3 tangent(
coef * ((v1.x * st2.y) + (v2.x * -st1.y)),
coef * ((v1.y * st2.y) + (v2.y * -st1.y)),
coef * ((v1.z * st2.y) + (v2.z * -st1.y))
);
KRVector3 tangent(
coef * ((v1.x * st2.y) + (v2.x * -st1.y)),
coef * ((v1.y * st2.y) + (v2.y * -st1.y)),
coef * ((v1.z * st2.y) + (v2.z * -st1.y))
);
tangent.normalize();
setVertexTangent(iVertex, tangent);
setVertexTangent(iVertex+1, tangent);
setVertexTangent(iVertex+2, tangent);
tangent.normalize();
setVertexTangent(iVertex, tangent);
setVertexTangent(iVertex+1, tangent);
setVertexTangent(iVertex+2, tangent);
}
}
}
}
}
@@ -533,12 +568,17 @@ KRMesh::pack_bone *KRMesh::getBone(int index)
unsigned char *KRMesh::getVertexData() const {
pack_header *pHeader = getHeader();
return ((unsigned char *)m_pData->getStart()) + sizeof(pack_header) + sizeof(pack_material) * pHeader->submesh_count + sizeof(pack_bone) * pHeader->bone_count + KRALIGN(2 * pHeader->index_count);
return ((unsigned char *)m_pData->getStart()) + sizeof(pack_header) + sizeof(pack_material) * pHeader->submesh_count + sizeof(pack_bone) * pHeader->bone_count + KRALIGN(2 * pHeader->index_count) + KRALIGN(8 * pHeader->index_base_count);
}
__uint16_t *KRMesh::getIndexData() const {
pack_header *pHeader = getHeader();
return (__uint16_t *)((unsigned char *)m_pData->getStart()) + sizeof(pack_header) + sizeof(pack_material) * pHeader->submesh_count + sizeof(pack_bone) * pHeader->bone_count;
return (__uint16_t *)((unsigned char *)m_pData->getStart() + sizeof(pack_header) + sizeof(pack_material) * pHeader->submesh_count + sizeof(pack_bone) * pHeader->bone_count);
}
__uint32_t *KRMesh::getIndexBaseData() const {
pack_header *pHeader = getHeader();
return (__uint32_t *)((unsigned char *)m_pData->getStart() + sizeof(pack_header) + sizeof(pack_material) * pHeader->submesh_count + sizeof(pack_bone) * pHeader->bone_count + KRALIGN(2 * pHeader->index_count));
}
@@ -815,27 +855,47 @@ bool KRMesh::rayCast(const KRVector3 &line_v0, const KRVector3 &dir, const KRVec
return true; // hit_point is in triangle
}
/*
bool KRMesh::rayCast(const KRVector3 &line_v0, const KRVector3 &dir, int tri_index0, int tri_index1, int tri_index2, KRHitInfo &hitinfo) const
{
return rayCast(line_v0, dir, getVertexPosition(tri_index0), getVertexPosition(tri_index1), getVertexPosition(tri_index2), getVertexNormal(tri_index0), getVertexNormal(tri_index1), getVertexNormal(tri_index2), hitinfo);
}
*/
bool KRMesh::rayCast(const KRVector3 &v0, const KRVector3 &dir, KRHitInfo &hitinfo) const
{
bool hit_found = false;
for(int submesh_index=0; submesh_index < getSubmeshCount(); submesh_index++) {
// int vertex_start = getSubmesh(submesh_index)->start_vertex;
int vertex_count = getVertexCount(submesh_index);
switch(getModelFormat()) {
case KRENGINE_MODEL_FORMAT_TRIANGLES:
case KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES:
for(int triangle_index=0; triangle_index < vertex_count / 3; triangle_index++) {
if(rayCast(v0, dir, getVertexPosition(triangle_index*3), getVertexPosition(triangle_index*3+1), getVertexPosition(triangle_index*3+2), getVertexNormal(triangle_index*3), getVertexNormal(triangle_index*3+1), getVertexNormal(triangle_index*3+2), hitinfo)) hit_found = true;
int tri_vert_index[3]; // FINDME, HACK! This is not very efficient for indexed collider meshes...
tri_vert_index[0] = getTriangleVertexIndex(submesh_index, triangle_index*3);
tri_vert_index[1] = getTriangleVertexIndex(submesh_index, triangle_index*3 + 1);
tri_vert_index[2] = getTriangleVertexIndex(submesh_index, triangle_index*3 + 2);
if(rayCast(v0, dir, getVertexPosition(tri_vert_index[0]), getVertexPosition(tri_vert_index[1]), getVertexPosition(tri_vert_index[2]), getVertexNormal(tri_vert_index[0]), getVertexNormal(tri_vert_index[1]), getVertexNormal(tri_vert_index[2]), hitinfo)) hit_found = true;
}
break;
/*
NOTE: Not yet supported:
case KRENGINE_MODEL_FORMAT_STRIP:
case KRENGINE_MODEL_FORMAT_INDEXED_STRIP:
for(int triangle_index=0; triangle_index < vertex_count - 2; triangle_index++) {
if(rayCast(v0, dir, getVertexPosition(triangle_index), getVertexPosition(triangle_index+1), getVertexPosition(triangle_index+2), getVertexNormal(triangle_index), getVertexNormal(triangle_index+1), getVertexNormal(triangle_index+2), hitinfo)) hit_found = true;
int tri_vert_index[3];
tri_vert_index[0] = getTriangleVertexIndex(submesh_index, vertex_start + triangle_index*3);
tri_vert_index[1] = getTriangleVertexIndex(submesh_index, vertex_start + triangle_index*3 + 1);
tri_vert_index[2] = getTriangleVertexIndex(submesh_index, vertex_start + triangle_index*3 + 2);
if(rayCast(v0, dir, getVertexPosition(vertex_start + triangle_index), getVertexPosition(vertex_start + triangle_index+1), getVertexPosition(vertex_start + triangle_index+2), getVertexNormal(vertex_start + triangle_index), getVertexNormal(vertex_start + triangle_index+1), getVertexNormal(vertex_start + triangle_index+2), hitinfo)) hit_found = true;
}
break;
*/
default:
break;
}
@@ -857,14 +917,296 @@ bool KRMesh::lineCast(const KRVector3 &v0, const KRVector3 &v1, KRHitInfo &hitin
return false; // Either no hit, or the hit was beyond v1
}
void KRMesh::convert(model_format_t model_format)
void KRMesh::convertToIndexed()
{
// Convert model to indexed vertices, identying vertexes with identical attributes and optimizing order of trianges for best usage post-vertex-transform cache on GPU
std::vector<__uint16_t> vertex_indexes;
std::vector<std::pair<int, int> > vertex_index_bases;
std::vector<KRVector3> vertices;
std::vector<KRVector2> uva;
std::vector<KRVector2> uvb;
std::vector<KRVector3> normals;
std::vector<KRVector3> tangents;
std::vector<int> submesh_starts;
std::vector<int> submesh_lengths;
std::vector<std::string> material_names;
std::vector<std::string> bone_names;
std::vector<std::vector<int> > bone_indexes;
std::vector<std::vector<float> > bone_weights;
int bone_count = getBoneCount();
for(int bone_index=0; bone_index < bone_count; bone_index++) {
bone_names.push_back(getBoneName(bone_index));
}
for(int submesh_index=0; submesh_index < getSubmeshCount(); submesh_index++) {
material_names.push_back(getSubmesh(submesh_index)->szName);
int vertexes_remaining = getVertexCount(submesh_index);
submesh_starts.push_back(vertex_index_bases.size());
submesh_lengths.push_back(vertexes_remaining);
int source_index = getSubmesh(submesh_index)->start_vertex;
while(vertexes_remaining) {
vertex_index_bases.push_back(std::pair<int, int>(vertex_indexes.size(), vertices.size()));
int vertex_count = vertexes_remaining;
if(vertex_count > 0xffff) {
vertex_count = 0xffff;
}
int vertex_index_base_start_vertex = vertices.size();
std::map<std::pair<std::vector<float>, std::vector<int> >, int> prev_indexes = std::map<std::pair<std::vector<float>, std::vector<int> >, int>();
for(int i=0; i < vertex_count; i++) {
KRVector3 vertex_position = getVertexPosition(source_index);
KRVector2 vertex_uva = getVertexUVA(source_index);
KRVector2 vertex_uvb = getVertexUVB(source_index);
KRVector3 vertex_normal = getVertexNormal(source_index);
KRVector3 vertex_tangent = getVertexTangent(source_index);
std::vector<int> vertex_bone_indexes;
if(has_vertex_attribute(KRENGINE_ATTRIB_BONEINDEXES)) {
vertex_bone_indexes.push_back(getBoneIndex(source_index, 0));
vertex_bone_indexes.push_back(getBoneIndex(source_index, 1));
vertex_bone_indexes.push_back(getBoneIndex(source_index, 2));
vertex_bone_indexes.push_back(getBoneIndex(source_index, 3));
}
std::vector<float> vertex_bone_weights;
if(has_vertex_attribute(KRENGINE_ATTRIB_BONEWEIGHTS)) {
vertex_bone_weights.push_back(getBoneWeight(source_index, 0));
vertex_bone_weights.push_back(getBoneWeight(source_index, 1));
vertex_bone_weights.push_back(getBoneWeight(source_index, 2));
vertex_bone_weights.push_back(getBoneWeight(source_index, 3));
}
std::pair<std::vector<float>, std::vector<int> > vertex_key; // = std::make_pair(std::vector<float>(), std::vector<int>());
if(has_vertex_attribute(KRENGINE_ATTRIB_VERTEX)) {
vertex_key.first.push_back(vertex_position.x);
vertex_key.first.push_back(vertex_position.y);
vertex_key.first.push_back(vertex_position.z);
}
if(has_vertex_attribute(KRENGINE_ATTRIB_NORMAL)) {
vertex_key.first.push_back(vertex_normal.x);
vertex_key.first.push_back(vertex_normal.y);
vertex_key.first.push_back(vertex_normal.z);
}
if(has_vertex_attribute(KRENGINE_ATTRIB_TEXUVA)) {
vertex_key.first.push_back(vertex_uva.x);
vertex_key.first.push_back(vertex_uva.y);
}
if(has_vertex_attribute(KRENGINE_ATTRIB_TEXUVB)) {
vertex_key.first.push_back(vertex_uvb.x);
vertex_key.first.push_back(vertex_uvb.y);
}
if(has_vertex_attribute(KRENGINE_ATTRIB_TANGENT)) {
vertex_key.first.push_back(vertex_tangent.x);
vertex_key.first.push_back(vertex_tangent.y);
vertex_key.first.push_back(vertex_tangent.z);
}
if(has_vertex_attribute(KRENGINE_ATTRIB_BONEINDEXES)) {
vertex_key.second.push_back(vertex_bone_indexes[0]);
vertex_key.second.push_back(vertex_bone_indexes[1]);
vertex_key.second.push_back(vertex_bone_indexes[2]);
vertex_key.second.push_back(vertex_bone_indexes[3]);
}
if(has_vertex_attribute(KRENGINE_ATTRIB_BONEWEIGHTS)) {
vertex_key.first.push_back(vertex_bone_weights[0]);
vertex_key.first.push_back(vertex_bone_weights[1]);
vertex_key.first.push_back(vertex_bone_weights[2]);
vertex_key.first.push_back(vertex_bone_weights[3]);
}
int found_index = -1;
if(prev_indexes.count(vertex_key) == 0) {
found_index = vertices.size() - vertex_index_base_start_vertex;
if(has_vertex_attribute(KRENGINE_ATTRIB_VERTEX)) {
vertices.push_back(vertex_position);
}
if(has_vertex_attribute(KRENGINE_ATTRIB_NORMAL)) {
normals.push_back(vertex_normal);
}
if(has_vertex_attribute(KRENGINE_ATTRIB_TANGENT)) {
tangents.push_back(vertex_tangent);
}
if(has_vertex_attribute(KRENGINE_ATTRIB_TEXUVA)) {
uva.push_back(vertex_uva);
}
if(has_vertex_attribute(KRENGINE_ATTRIB_TEXUVB)) {
uvb.push_back(vertex_uvb);
}
if(has_vertex_attribute(KRENGINE_ATTRIB_BONEINDEXES)) {
bone_indexes.push_back(vertex_bone_indexes);
}
if(has_vertex_attribute(KRENGINE_ATTRIB_BONEWEIGHTS)) {
bone_weights.push_back(vertex_bone_weights);
}
prev_indexes[vertex_key] = found_index;
} else {
found_index = prev_indexes[vertex_key];
}
vertex_indexes.push_back(found_index);
source_index++;
}
vertexes_remaining -= vertex_count;
}
}
fprintf(stderr, "Convert to indexed, before: %i after: %i \(%.2f%% saving)\n", getHeader()->vertex_count, vertices.size(), ((float)getHeader()->vertex_count - (float)vertices.size()) / (float)getHeader()->vertex_count * 100.0f);
LoadData(vertex_indexes, vertex_index_bases, vertices, uva, uvb, normals, tangents, submesh_starts, submesh_lengths, material_names, bone_names, bone_indexes, bone_weights, KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES, false, false);
}
void KRMesh::optimize()
{
convert(KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES);
// TODO - Add algorithm to convert model to indexed vertices, identying vertexes with identical attributes and optimizing order of trianges for best usage post-vertex-transform cache on GPU
switch(getModelFormat()) {
case KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES:
optimizeIndexes();
break;
default:
convertToIndexed(); // HACK, FINDME, TODO - This may not be ideal in every case and should be exposed through the API independently
break;
}
}
void KRMesh::getIndexedRange(int submesh, int submesh_index_group, int &start_index_offset, int &start_vertex_offset, int &index_count, int &vertex_count) const {
pack_header *h = getHeader();
int index_group = getSubmesh(submesh)->start_vertex + submesh_index_group;
__uint32_t *index_base_data = getIndexBaseData();
start_index_offset = index_base_data[index_group * 2];
start_vertex_offset = index_base_data[index_group * 2 + 1];
if(index_group + 1 < h->index_base_count) {
index_count = index_base_data[index_group * 2 + 2] - start_index_offset;
vertex_count = index_base_data[index_group * 2 + 3] - start_vertex_offset;
} else {
index_count = h->index_count - start_index_offset;
vertex_count = h->vertex_count - start_vertex_offset;
}
}
int KRMesh::getTriangleVertexIndex(int submesh, int index) const
{
switch(getModelFormat()) {
case KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES:
{
int remaining_vertices = index;
int submesh_index_group = 0;
int start_index_offset, start_vertex_offset, index_count, vertex_count;
getIndexedRange(submesh, submesh_index_group++, start_index_offset, start_vertex_offset, index_count, vertex_count);
while(remaining_vertices >= index_count) {
remaining_vertices -= index_count;
getIndexedRange(submesh, submesh_index_group++, start_index_offset, start_vertex_offset, index_count, vertex_count);
}
return getIndexData()[start_index_offset + remaining_vertices] + start_vertex_offset;
}
break;
default:
return getSubmesh(submesh)->start_vertex + index;
break;
}
}
void KRMesh::optimizeIndexes()
{
if(getModelFormat() != KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES) return;
__uint16_t *new_indices = (__uint16_t *)malloc(0x10000 * sizeof(__uint16_t));
__uint16_t *vertex_mapping = (__uint16_t *)malloc(0x10000 * sizeof(__uint16_t));
unsigned char *new_vertex_data = (unsigned char *)malloc(m_vertex_size * 0x10000);
// FINDME, TODO, HACK - This will segfault if the KRData object is still mmap'ed to a read-only file. Need to detach from the file before calling this function. Currently, this function is only being used during the import process, so it isn't going to cause any problems for now.
pack_header *header = getHeader();
__uint16_t *index_data = getIndexData();
unsigned char *vertex_data = getVertexData();
for(int submesh_index=0; submesh_index < header->submesh_count; submesh_index++) {
pack_material *submesh = getSubmesh(submesh_index);
int vertexes_remaining = submesh->vertex_count;
int submesh_index_group = 0;
while(vertexes_remaining > 0) {
int start_index_offset, start_vertex_offset, index_count, vertex_count;
getIndexedRange(submesh_index, submesh_index_group++, start_index_offset, start_vertex_offset, index_count, vertex_count);
__uint16_t *index_data_start = index_data + start_index_offset;
unsigned char * vertex_data_start = vertex_data + start_vertex_offset * m_vertex_size;
// ----====---- Step 1: Optimize triangle drawing order to maximize use of the GPU's post-transform vertex cache ----====----
Forsyth::OptimizeFaces(index_data_start, index_count, vertex_count, new_indices, 16); // FINDME, TODO - GPU post-transform vertex cache size of 16 should be configureable
memcpy(index_data_start, new_indices, index_count * sizeof(__uint16_t));
vertexes_remaining -= index_count;
/*
// ----====---- Step 2: Re-order the vertex data to maintain cache coherency ----====----
for(int i=0; i < vertex_count; i++) {
vertex_mapping[i] = i;
}
int new_vertex_index=0;
for(int index_number=0; index_number<index_count; index_number++) {
int prev_vertex_index = index_data_start[index_number];
if(prev_vertex_index > new_vertex_index) {
// Swap prev_vertex_index and new_vertex_index
for(int i=0; i < index_count; i++) {
if(index_data_start[i] == prev_vertex_index) {
index_data_start[i] = new_vertex_index;
} else if(index_data_start[i] == new_vertex_index) {
index_data_start[i] = prev_vertex_index;
}
}
int tmp = vertex_mapping[prev_vertex_index];
vertex_mapping[prev_vertex_index] = vertex_mapping[new_vertex_index];
vertex_mapping[new_vertex_index] = tmp;
new_vertex_index++;
}
}
for(int i=0; i < vertex_count; i++) {
memcpy(new_vertex_data + vertex_mapping[i] * m_vertex_size, vertex_data_start + i * m_vertex_size, m_vertex_size);
}
memcpy(vertex_data_start, new_vertex_data, vertex_count * m_vertex_size);
*/
}
}
free(new_indices);
free(vertex_mapping);
free(new_vertex_data);
/*
if(getModelFormat() == KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES) {
int cVertexes = pSubmesh->vertex_count;
//fprintf(stderr, "start - object: %s material: %s vertices: %i\n", object_name.c_str(), material_name.c_str(), cVertexes);
__uint16_t *index_data = getIndexData();
int submesh_index_group = 0;
while(cVertexes > 0) {
int start_index_offset, start_vertex_offset, index_count, vertex_count;
getIndexedRange(iSubmesh, submesh_index_group++, start_index_offset, start_vertex_offset, index_count, vertex_count);
m_pContext->getModelManager()->bindVBO((unsigned char *)pVertexData + start_vertex_offset * m_vertex_size, m_vertex_size * vertex_count, index_data + start_index_offset, index_count * 4, has_vertex_attribute(KRENGINE_ATTRIB_VERTEX), has_vertex_attribute(KRENGINE_ATTRIB_NORMAL), has_vertex_attribute(KRENGINE_ATTRIB_TANGENT), has_vertex_attribute(KRENGINE_ATTRIB_TEXUVA), has_vertex_attribute(KRENGINE_ATTRIB_TEXUVB), has_vertex_attribute(KRENGINE_ATTRIB_BONEINDEXES), has_vertex_attribute(KRENGINE_ATTRIB_BONEWEIGHTS), true);
glDrawElements(GL_TRIANGLES, index_count, GL_UNSIGNED_SHORT, 0);
cVertexes -= index_count;
}
*/
}

View File

@@ -91,11 +91,12 @@ public:
virtual bool save(const std::string& path);
virtual bool save(KRDataBlock &data);
void LoadData(std::vector<KRVector3> vertices, std::vector<KRVector2> uva, std::vector<KRVector2> uvb, std::vector<KRVector3> normals, std::vector<KRVector3> tangents, std::vector<int> submesh_starts, std::vector<int> submesh_lengths, std::vector<std::string> material_names, std::vector<std::string> bone_names, std::vector<std::vector<int> > bone_indexes, std::vector<std::vector<float> > bone_weights, model_format_t model_format);
void LoadData(std::vector<__uint16_t> vertex_indexes, std::vector<std::pair<int, int> > vertex_index_bases, std::vector<KRVector3> vertices, std::vector<KRVector2> uva, std::vector<KRVector2> uvb, std::vector<KRVector3> normals, std::vector<KRVector3> tangents, std::vector<int> submesh_starts, std::vector<int> submesh_lengths, std::vector<std::string> material_names, std::vector<std::string> bone_names, std::vector<std::vector<int> > bone_indexes, std::vector<std::vector<float> > bone_weights, model_format_t model_format, bool calculate_normals, bool calculate_tangents);
void loadPack(KRDataBlock *data);
void convert(model_format_t model_format);
void convertToIndexed();
void optimize();
void optimizeIndexes();
void renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const std::string &object_name, const std::string &material_name);
@@ -131,8 +132,6 @@ public:
TexCoord uvb;
} VertexData;
vector<Submesh *> getSubmeshes();
typedef struct {
int32_t start_vertex;
int32_t vertex_count;
@@ -152,6 +151,7 @@ public:
int getSubmeshCount() const;
int getVertexCount(int submesh) const;
int getTriangleVertexIndex(int submesh, int index) const;
KRVector3 getVertexPosition(int index) const;
KRVector3 getVertexNormal(int index) const;
KRVector3 getVertexTangent(int index) const;
@@ -182,7 +182,9 @@ public:
static int GetLODCoverage(const std::string &name);
private:
bool rayCast(const KRVector3 &line_v0, const KRVector3 &dir, int tri_index0, int tri_index1, int tri_index2, KRHitInfo &hitinfo) const;
void getSubmeshes();
// bool rayCast(const KRVector3 &line_v0, const KRVector3 &dir, int tri_index0, int tri_index1, int tri_index2, KRHitInfo &hitinfo) const;
static bool rayCast(const KRVector3 &line_v0, const KRVector3 &dir, const KRVector3 &tri_v0, const KRVector3 &tri_v1, const KRVector3 &tri_v2, const KRVector3 &tri_n0, const KRVector3 &tri_n1, const KRVector3 &tri_n2, KRHitInfo &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)
@@ -207,7 +209,8 @@ private:
int32_t bone_count;
float minx, miny, minz, maxx, maxy, maxz; // Axis aligned bounding box, in model's coordinate space
int32_t index_count;
unsigned char reserved[448]; // Pad out to 512 bytes
int32_t index_base_count;
unsigned char reserved[444]; // Pad out to 512 bytes
} pack_header;
vector<Submesh *> m_submeshes;
@@ -227,8 +230,12 @@ private:
unsigned char *getVertexData() const;
unsigned char *getVertexData(int index) const;
__uint16_t *getIndexData() const;
__uint32_t *getIndexBaseData() const;
pack_header *getHeader() const;
pack_bone *getBone(int index);
void getIndexedRange(int submesh, int submesh_index_group, int &start_index_offset, int &start_vertex_offset, int &index_count, int &vertex_count) const;
};

View File

@@ -67,7 +67,10 @@ KRMeshCube::KRMeshCube(KRContext &context) : KRMesh(context, "__cube")
submesh_lengths.push_back(vertices.size());
material_names.push_back("");
LoadData(vertices, uva, uvb, normals, tangents, submesh_starts, submesh_lengths, material_names, bone_names, bone_indexes, bone_weights, KRENGINE_MODEL_FORMAT_STRIP);
std::vector<__uint16_t> vertex_indexes;
std::vector<std::pair<int, int> > vertex_index_bases;
LoadData(vertex_indexes, vertex_index_bases, vertices, uva, uvb, normals, tangents, submesh_starts, submesh_lengths, material_names, bone_names, bone_indexes, bone_weights, KRENGINE_MODEL_FORMAT_STRIP, true, true);
}
KRMeshCube::~KRMeshCube()

View File

@@ -148,6 +148,7 @@ void KRMeshManager::releaseVBO(GLvoid *data)
void KRMeshManager::bindVBO(GLvoid *data, GLsizeiptr size, GLvoid *index_data, GLsizeiptr index_data_size, bool enable_vertex, bool enable_normal, bool enable_tangent, bool enable_uva, bool enable_uvb, bool enable_bone_indexes, bool enable_bone_weights, bool static_vbo) {
if(m_currentVBO.data != data || m_currentVBO.size != size) {
if(m_vbosActive.find(data) != m_vbosActive.end()) {
@@ -157,6 +158,11 @@ void KRMeshManager::bindVBO(GLvoid *data, GLsizeiptr size, GLvoid *index_data, G
#else
GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, m_currentVBO.vbo_handle));
configureAttribs(enable_vertex, enable_normal, enable_tangent, enable_uva, enable_uvb, enable_bone_indexes, enable_bone_weights);
if(m_currentVBO.vbo_handle_indexes == -1) {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_currentVBO.vbo_handle_indexes));
}
#endif
} else if(m_vbosPool.find(data) != m_vbosPool.end()) {
m_currentVBO = m_vbosPool[data];
@@ -167,11 +173,16 @@ void KRMeshManager::bindVBO(GLvoid *data, GLsizeiptr size, GLvoid *index_data, G
#else
GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, m_currentVBO.vbo_handle));
configureAttribs(enable_vertex, enable_normal, enable_tangent, enable_uva, enable_uvb, enable_bone_indexes, enable_bone_weights);
if(m_currentVBO.vbo_handle_indexes == -1) {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_currentVBO.vbo_handle_indexes));
}
#endif
} else {
while(m_vbosPool.size() + m_vbosActive.size() + 1 >= KRContext::KRENGINE_MAX_VBO_HANDLES || m_vboMemUsed + size >= KRContext::KRENGINE_MAX_VBO_MEM) {
while(m_vbosPool.size() + m_vbosActive.size() + 1 >= KRContext::KRENGINE_MAX_VBO_HANDLES || m_vboMemUsed + size + index_data_size >= KRContext::KRENGINE_MAX_VBO_MEM) {
if(m_vbosPool.empty()) {
fprintf(stderr, "flushBuffers due to VBO exhaustion...\n");
m_pContext->rotateBuffers(false);
@@ -194,6 +205,10 @@ void KRMeshManager::bindVBO(GLvoid *data, GLsizeiptr size, GLvoid *index_data, G
m_currentVBO.vbo_handle = -1;
m_currentVBO.vbo_handle_indexes = -1;
GLDEBUG(glGenBuffers(1, &m_currentVBO.vbo_handle));
if(index_data != NULL) {
GLDEBUG(glGenBuffers(1, &m_currentVBO.vbo_handle_indexes));
}
#if GL_OES_vertex_array_object
GLDEBUG(glGenVertexArraysOES(1, &m_currentVBO.vao_handle));
GLDEBUG(glBindVertexArrayOES(m_currentVBO.vao_handle));
@@ -208,6 +223,16 @@ void KRMeshManager::bindVBO(GLvoid *data, GLsizeiptr size, GLvoid *index_data, G
m_currentVBO.size = size;
m_currentVBO.data = data;
if(index_data == NULL) {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_currentVBO.vbo_handle_indexes));
GLDEBUG(glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_data_size, index_data, static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
m_memoryTransferredThisFrame += index_data_size;
m_vboMemUsed += index_data_size;
m_currentVBO.size += index_data_size;
}
m_vbosActive[data] = m_currentVBO;
}
}
@@ -370,7 +395,7 @@ KRMeshManager::RandomParticleVertexData *KRMeshManager::getRandomParticles()
// Generate vertices for randomly placed equilateral triangles with a side length of 1 and an origin point centered so that an inscribed circle can be efficiently rendered without wasting fill
float equilateral_triangle_height = sqrt(3.0f) / 2.0f;
float equilateral_triangle_height = sqrt(3.0f) * 0.5f;
float inscribed_circle_radius = 1.0f / (2.0f * sqrt(3.0f));
int iVertex=0;

View File

@@ -134,7 +134,10 @@ KRMeshSphere::KRMeshSphere(KRContext &context) : KRMesh(context, "__sphere")
submesh_lengths.push_back(vertices.size());
material_names.push_back("");
LoadData(vertices, uva, uvb, normals, tangents, submesh_starts, submesh_lengths, material_names, bone_names, bone_indexes, bone_weights, KRENGINE_MODEL_FORMAT_TRIANGLES);
std::vector<__uint16_t> vertex_indexes;
std::vector<std::pair<int, int> > vertex_index_bases;
LoadData(vertex_indexes, vertex_index_bases, vertices, uva, uvb, normals, tangents, submesh_starts, submesh_lengths, material_names, bone_names, bone_indexes, bone_weights, KRENGINE_MODEL_FORMAT_TRIANGLES, true, true);
}
KRMeshSphere::~KRMeshSphere()

View File

@@ -101,11 +101,16 @@ void KRModel::render(KRCamera *pCamera, std::vector<KRLight *> &lights, const KR
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) {
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
float lod_coverage = 0.0f;
if(m_models.size() > 1) {
lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
} else if(viewport.visible(getBounds())) {
lod_coverage = 1.0f;
}
float lod_coverage = getBounds().coverage(viewport.getViewProjectionMatrix(), viewport.getSize()); // This also checks the view frustrum culling
if(lod_coverage > m_min_lod_coverage) {
// ---===--- Select the best LOD model based on screen coverage ---===---
@@ -122,7 +127,7 @@ void KRModel::render(KRCamera *pCamera, std::vector<KRLight *> &lights, const KR
}
if(m_pLightMap == NULL && m_lightMap.size()) {
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap.c_str());
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
}
if(m_pLightMap && pCamera->settings.bEnableLightMap && renderPass != RENDER_PASS_SHADOWMAP && renderPass != RENDER_PASS_GENERATE_SHADOWMAPS) {

View File

@@ -60,8 +60,7 @@ void KRParticleSystemNewtonian::render(KRCamera *pCamera, std::vector<KRLight *>
KRNode::render(pCamera, lights, viewport, renderPass);
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
float lod_coverage = getBounds().coverage(viewport.getViewProjectionMatrix(), viewport.getSize()); // This also checks the view frustrum culling
if(lod_coverage > 0.0f) {
if(viewport.visible(getBounds())) {
// Enable z-buffer test

View File

@@ -62,9 +62,7 @@ void KRPointLight::render(KRCamera *pCamera, std::vector<KRLight *> &lights, con
sphereModelMatrix.scale(influence_radius);
sphereModelMatrix.translate(light_position.x, light_position.y, light_position.z);
float lod_coverage = getBounds().coverage(viewport.getViewProjectionMatrix(), viewport.getSize()); // This also checks the view frustrum culling
if(lod_coverage > 0) { // Cull out any lights not within the view frustrum
if(viewport.visible(getBounds())) { // Cull out any lights not within the view frustrum
KRVector3 view_light_position = KRMat4::Dot(viewport.getViewMatrix(), light_position);

View File

@@ -81,10 +81,17 @@ KRQuaternion::~KRQuaternion() {
void KRQuaternion::setEulerZYX(const KRVector3 &euler) {
// ZYX Order!
m_val[0] = cos(euler[0] / 2.0) * cos(euler[1] / 2.0) * cos(euler[2] / 2.0) + sin(euler[0] / 2.0) * sin(euler[1] / 2.0) * sin(euler[2] / 2.0);
m_val[1] = sin(euler[0] / 2.0) * cos(euler[1] / 2.0) * cos(euler[2] / 2.0) - cos(euler[0] / 2.0) * sin(euler[1] / 2.0) * sin(euler[2] / 2.0);
m_val[2] = cos(euler[0] / 2.0) * sin(euler[1] / 2.0) * cos(euler[2] / 2.0) + sin(euler[0] / 2.0) * cos(euler[1] / 2.0) * sin(euler[2] / 2.0);
m_val[3] = cos(euler[0] / 2.0) * cos(euler[1] / 2.0) * sin(euler[2] / 2.0) - sin(euler[0] / 2.0) * sin(euler[1] / 2.0) * cos(euler[2] / 2.0);
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);
m_val[0] = c1 * c2 * c3 + s1 * s2 * s3;
m_val[1] = s1 * c2 * c3 - c1 * s2 * s3;
m_val[2] = c1 * s2 * c3 + s1 * c2 * s3;
m_val[3] = c1 * c2 * s3 - s1 * s2 * c3;
}
float KRQuaternion::operator [](unsigned i) const {
@@ -100,13 +107,13 @@ KRVector3 KRQuaternion::eulerXYZ() const {
if(a2 <= -0.99999) {
return KRVector3(
2.0 * atan2(m_val[1], m_val[0]),
-PI / 2.0,
-PI * 0.5f,
0
);
} else if(a2 >= 0.99999) {
return KRVector3(
2.0 * atan2(m_val[1], m_val[0]),
PI / 2.0,
PI * 0.5f,
0
);
} else {

View File

@@ -1292,7 +1292,9 @@ void LoadMesh(KRContext &context, std::vector<KRResource *> &resources, FbxGeome
delete control_point_weights;
KRMesh *new_mesh = new KRMesh(context, pSourceMesh->GetNode()->GetName());
new_mesh->LoadData(vertices, uva, uvb, normals, tangents, submesh_starts, submesh_lengths, material_names, bone_names, bone_indexes, bone_weights,KRMesh::KRENGINE_MODEL_FORMAT_TRIANGLES);
std::vector<__uint16_t> vertex_indexes;
std::vector<std::pair<int, int> > vertex_index_bases;
new_mesh->LoadData(vertex_indexes, vertex_index_bases, vertices, uva, uvb, normals, tangents, submesh_starts, submesh_lengths, material_names, bone_names, bone_indexes, bone_weights,KRMesh::KRENGINE_MODEL_FORMAT_TRIANGLES, true, false); // FINDME, HACK! "false" set for importing tangents so that we can merge more vertices in the index buffer. This should be configurable by the end-user so if normal maps are required and no tangents are included in the model, they can be calculated
context.getModelManager()->addModel(new_mesh);
}

View File

@@ -330,7 +330,10 @@ std::vector<KRResource *> KRResource::LoadObj(KRContext &context, const std::str
std::vector<std::vector<int> > bone_indexes;
std::vector<std::vector<float> > bone_weights;
new_mesh->LoadData(vertices, uva, uvb, normals, tangents, submesh_starts, submesh_lengths, material_names, bone_names, bone_indexes, bone_weights, KRMesh::KRENGINE_MODEL_FORMAT_TRIANGLES);
std::vector<__uint16_t> vertex_indexes;
std::vector<std::pair<int, int> > vertex_index_bases;
new_mesh->LoadData(vertex_indexes, vertex_index_bases, vertices, uva, uvb, normals, tangents, submesh_starts, submesh_lengths, material_names, bone_names, bone_indexes, bone_weights, KRMesh::KRENGINE_MODEL_FORMAT_TRIANGLES, true, false);
}
if(pFaces) {

View File

@@ -199,10 +199,7 @@ void KRScene::render(KROctreeNode *pOctreeNode, std::map<KRAABB, int> &visibleBo
}
} else {
float min_coverage = 0.0f;
float lod_coverage = pOctreeNode->getBounds().coverage(viewport.getViewProjectionMatrix(), viewport.getSize()); // Cull against the view frustrum
if(lod_coverage > min_coverage) {
if(viewport.visible(pOctreeNode->getBounds())) {
// ----====---- Rendering and occlusion test pass ----====----
bool bVisible = false;
@@ -264,7 +261,7 @@ void KRScene::render(KROctreeNode *pOctreeNode, std::map<KRAABB, int> &visibleBo
KRMat4 matModel = KRMat4();
matModel.scale(octreeBounds.size() / 2.0f);
matModel.scale(octreeBounds.size() * 0.5f);
matModel.translate(octreeBounds.center());
KRMat4 mvpmatrix = matModel * viewport.getViewProjectionMatrix();

View File

@@ -50,13 +50,6 @@ KRShaderManager::~KRShaderManager() {
KRShader *KRShaderManager::getShader(const std::string &shader_name, KRCamera *pCamera, const std::vector<KRLight *> &lights, int bone_count, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass) {
std::string platform_shader_name = shader_name;
#if TARGET_OS_IPHONE
platform_shader_name = shader_name;
#else
platform_shader_name = shader_name + "_osx";
#endif
int iShadowQuality = 0; // FINDME - HACK - Placeholder code, need to iterate through lights and dynamically build shader
@@ -81,21 +74,69 @@ KRShader *KRShaderManager::getShader(const std::string &shader_name, KRCamera *p
if(iShadowQuality > pCamera->settings.m_cShadowBuffers) {
iShadowQuality = pCamera->settings.m_cShadowBuffers;
}
/*
char szKey[256];
sprintf(szKey, "%i_%i_%i_%i_%i_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%i_%s_%i_%d_%d_%f_%f_%f_%f_%f_%f_%f", light_directional_count, light_point_count, light_spot_count, bone_count, pCamera->settings.fog_type, pCamera->settings.bEnablePerPixel,bAlphaTest, bAlphaBlend, bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, pCamera->settings.bDebugPSSM, iShadowQuality, pCamera->settings.bEnableAmbient, pCamera->settings.bEnableDiffuse, pCamera->settings.bEnableSpecular, bLightMap, bDiffuseMapScale, bSpecMapScale, bReflectionMapScale, bNormalMapScale, bDiffuseMapOffset, bSpecMapOffset, bReflectionMapOffset, bNormalMapOffset,pCamera->settings.volumetric_environment_enable && pCamera->settings.volumetric_environment_downsample != 0, renderPass, platform_shader_name.c_str(),pCamera->settings.dof_quality,pCamera->settings.bEnableFlash,pCamera->settings.bEnableVignette,pCamera->settings.dof_depth,pCamera->settings.dof_falloff,pCamera->settings.flash_depth,pCamera->settings.flash_falloff,pCamera->settings.flash_intensity,pCamera->settings.vignette_radius,pCamera->settings.vignette_falloff);
KRShader *pShader = m_shaders[szKey];
*/
std::pair<std::string, std::vector<int> > key;
key.first = shader_name;
key.second.push_back(light_directional_count);
key.second.push_back(bSpecMap);
key.second.push_back(bReflectionMap);
key.second.push_back(bReflectionCubeMap);
key.second.push_back(pCamera->settings.bDebugPSSM);
key.second.push_back(iShadowQuality);
key.second.push_back(pCamera->settings.bEnableAmbient);
key.second.push_back(pCamera->settings.bEnableDiffuse);
key.second.push_back(pCamera->settings.bEnableSpecular);
key.second.push_back(bLightMap);
key.second.push_back(bDiffuseMapScale);
key.second.push_back(bSpecMapScale);
key.second.push_back(bReflectionMapScale);
key.second.push_back(bNormalMapScale);
key.second.push_back(bDiffuseMapOffset);
key.second.push_back(bSpecMapOffset);
key.second.push_back(bReflectionMapOffset);
key.second.push_back(bNormalMapOffset);
key.second.push_back(pCamera->settings.volumetric_environment_enable);
key.second.push_back(pCamera->settings.volumetric_environment_downsample != 0);
key.second.push_back(renderPass);
key.second.push_back(pCamera->settings.dof_quality);
key.second.push_back(pCamera->settings.bEnableFlash);
key.second.push_back(pCamera->settings.bEnableVignette);
key.second.push_back(pCamera->settings.dof_depth * 1000.0f);
key.second.push_back(pCamera->settings.dof_falloff * 1000.0f);
key.second.push_back(pCamera->settings.flash_depth * 1000.0f);
key.second.push_back(pCamera->settings.flash_falloff * 1000.0f);
key.second.push_back(pCamera->settings.flash_intensity * 1000.0f);
key.second.push_back(pCamera->settings.vignette_radius * 1000.0f);
key.second.push_back(pCamera->settings.vignette_falloff * 1000.0f);
KRShader *pShader = m_shaders[key];
if(pShader == NULL) {
if(m_shaders.size() > KRContext::KRENGINE_MAX_SHADER_HANDLES) {
// Keep the size of the shader cache reasonable
std::map<std::string, KRShader *>::iterator itr = m_shaders.begin();
std::map<std::pair<std::string, std::vector<int> > , KRShader *>::iterator itr = m_shaders.begin();
delete (*itr).second;
m_shaders.erase(itr);
fprintf(stderr, "Swapping shaders...\n");
}
std::string platform_shader_name = shader_name;
#if TARGET_OS_IPHONE
platform_shader_name = shader_name;
#else
platform_shader_name = shader_name + "_osx";
#endif
stringstream stream;
stream.precision(std::numeric_limits<long double>::digits10);
@@ -188,9 +229,12 @@ KRShader *KRShaderManager::getShader(const std::string &shader_name, KRCamera *p
fprintf(stderr, "ERROR: Fragment Shader Missing: %s\n", platform_shader_name.c_str());
}
char szKey[256];
sprintf(szKey, "%i_%i_%i_%i_%i_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%i_%s_%i_%d_%d_%f_%f_%f_%f_%f_%f_%f", light_directional_count, light_point_count, light_spot_count, bone_count, pCamera->settings.fog_type, pCamera->settings.bEnablePerPixel,bAlphaTest, bAlphaBlend, bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, pCamera->settings.bDebugPSSM, iShadowQuality, pCamera->settings.bEnableAmbient, pCamera->settings.bEnableDiffuse, pCamera->settings.bEnableSpecular, bLightMap, bDiffuseMapScale, bSpecMapScale, bReflectionMapScale, bNormalMapScale, bDiffuseMapOffset, bSpecMapOffset, bReflectionMapOffset, bNormalMapOffset,pCamera->settings.volumetric_environment_enable && pCamera->settings.volumetric_environment_downsample != 0, renderPass, shader_name.c_str(),pCamera->settings.dof_quality,pCamera->settings.bEnableFlash,pCamera->settings.bEnableVignette,pCamera->settings.dof_depth,pCamera->settings.dof_falloff,pCamera->settings.flash_depth,pCamera->settings.flash_falloff,pCamera->settings.flash_intensity,pCamera->settings.vignette_radius,pCamera->settings.vignette_falloff);
pShader = new KRShader(getContext(), szKey, options, vertShaderSource, fragShaderSource);
m_shaders[szKey] = pShader;\
m_shaders[key] = pShader;
}
return pShader;
}

View File

@@ -67,7 +67,8 @@ public:
long getShaderHandlesUsed();
private:
std::map<std::string, KRShader *> m_shaders;
//std::map<std::string, KRShader *> m_shaders;
std::map<std::pair<std::string, std::vector<int> >, KRShader *> m_shaders;
std::map<std::string, std::string> m_fragShaderSource;
std::map<std::string, std::string> m_vertShaderSource;

View File

@@ -72,7 +72,7 @@ std::string KRTextureAnimated::textureNameForFrame(int frame)
KRTexture2D *KRTextureAnimated::textureForFrame(int frame)
{
return (KRTexture2D *)getContext().getTextureManager()->getTexture(textureNameForFrame(frame).c_str());
return (KRTexture2D *)getContext().getTextureManager()->getTexture(textureNameForFrame(frame));
}
KRTextureAnimated::~KRTextureAnimated()

View File

@@ -41,7 +41,7 @@ KRTextureCube::KRTextureCube(KRContext &context, std::string name) : KRTexture(c
for(int i=0; i<6; i++) {
std::string faceName = getName() + SUFFIXES[i];
KRTexture2D *faceTexture = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName.c_str());
KRTexture2D *faceTexture = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName);
if(faceTexture) {
if(faceTexture->getMaxMipMap() < m_max_lod_max_dim) m_max_lod_max_dim = faceTexture->getMaxMipMap();
if(faceTexture->getMinMipMap() > m_min_lod_max_dim) m_min_lod_max_dim = faceTexture->getMinMipMap();
@@ -67,7 +67,7 @@ bool KRTextureCube::createGLTexture(int lod_max_dim)
for(int i=0; i<6; i++) {
std::string faceName = getName() + SUFFIXES[i];
KRTexture2D *faceTexture = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName.c_str());
KRTexture2D *faceTexture = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName);
if(faceTexture) {
if(faceTexture->hasMipmaps()) bMipMaps = true;
faceTexture->uploadTexture(TARGETS[i], lod_max_dim, m_current_lod_max_dim, m_textureMemUsed);
@@ -92,7 +92,7 @@ long KRTextureCube::getMemRequiredForSize(int max_dim)
long memoryRequired = 0;
for(int i=0; i<6; i++) {
std::string faceName = getName() + SUFFIXES[i];
KRTexture2D *faceTexture = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName.c_str());
KRTexture2D *faceTexture = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName);
if(faceTexture) {
memoryRequired += faceTexture->getMemRequiredForSize(target_dim);
}
@@ -106,7 +106,7 @@ void KRTextureCube::resetPoolExpiry()
KRTexture::resetPoolExpiry();
for(int i=0; i<6; i++) {
std::string faceName = getName() + SUFFIXES[i];
KRTexture2D *faceTexture = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName.c_str());
KRTexture2D *faceTexture = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName);
if(faceTexture) {
faceTexture->resetPoolExpiry(); // Ensure that side of cube maps do not expire from the texture pool prematurely, as they are referenced indirectly
}

View File

@@ -94,14 +94,16 @@ KRTexture *KRTextureManager::getTextureCube(const char *szName) {
}
}
KRTexture *KRTextureManager::getTexture(const char *szName) {
std::string lowerName = szName;
KRTexture *KRTextureManager::getTexture(const std::string &name) {
std::string lowerName = name;
std::transform(lowerName.begin(), lowerName.end(),
lowerName.begin(), ::tolower);
map<std::string, KRTexture *>::iterator itr = m_textures.find(lowerName);
if(itr == m_textures.end()) {
if(lowerName.substr(8).compare("animate:") == 0) {
if(lowerName.length() <= 8) {
return NULL;
} else if(lowerName.substr(8).compare("animate:") == 0) {
// This is an animated texture, create KRTextureAnimated's on-demand
KRTextureAnimated *pTexture = new KRTextureAnimated(getContext(), lowerName);
m_textures[lowerName] = pTexture;

View File

@@ -49,7 +49,7 @@ public:
KRTexture *loadTexture(const char *szName, const char *szExtension, KRDataBlock *data);
KRTexture *getTextureCube(const char *szName);
KRTexture *getTexture(const char *szFile);
KRTexture *getTexture(const std::string &name);
long getMemUsed();
long getMemActive();

View File

@@ -0,0 +1,295 @@
//
// KRVector4.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRVector4.h"
//default constructor
KRVector4::KRVector4()
{
x = 0.0f;
y = 0.0f;
z = 0.0f;
w = 0.0f;
}
KRVector4::KRVector4(const KRVector4 &v) {
x = v.x;
y = v.y;
z = v.z;
w = v.w;
}
KRVector4::KRVector4(float *v) {
x = v[0];
y = v[1];
z = v[2];
w = v[3];
}
KRVector4 KRVector4::Min() {
return KRVector4(-std::numeric_limits<float>::max());
}
KRVector4 KRVector4::Max() {
return KRVector4(std::numeric_limits<float>::max());
}
KRVector4 KRVector4::Zero() {
return KRVector4(0.0f, 0.0f, 0.0f, 0.0f);
}
KRVector4 KRVector4::One() {
return KRVector4(1.0f, 1.0f, 1.0f, 1.0f);
}
KRVector4 KRVector4::Forward() {
return KRVector4(0.0f, 0.0f, 1.0f, 1.0f);
}
KRVector4 KRVector4::Backward() {
return KRVector4(0.0f, 0.0f, -1.0f, 1.0f);
}
KRVector4 KRVector4::Up() {
return KRVector4(0.0f, 1.0f, 0.0f, 1.0f);
}
KRVector4 KRVector4::Down() {
return KRVector4(0.0f, -1.0f, 0.0f, 1.0f);
}
KRVector4 KRVector4::Left() {
return KRVector4(-1.0f, 0.0f, 0.0f, 1.0f);
}
KRVector4 KRVector4::Right() {
return KRVector4(1.0f, 0.0f, 0.0f, 1.0f);
}
KRVector4 KRVector4::Lerp(const KRVector4 &v1, const KRVector4 &v2, float d) {
return v1 + (v2 - v1) * d;
}
KRVector4 KRVector4::Slerp(const KRVector4 &v1, const KRVector4 &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 = KRVector4::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;
KRVector4 RelativeVec = v2 - v1*dot;
RelativeVec.normalize(); // Orthonormal basis
// The final result.
return ((v1*cos(theta)) + (RelativeVec*sin(theta)));
}
void KRVector4::OrthoNormalize(KRVector4 &normal, KRVector4 &tangent) {
// Gram-Schmidt Orthonormalization
normal.normalize();
KRVector4 proj = normal * Dot(tangent, normal);
tangent = tangent - proj;
tangent.normalize();
}
KRVector4::KRVector4(float v) {
x = v;
y = v;
z = v;
w = v;
}
KRVector4::KRVector4(float X, float Y, float Z, float W)
{
x = X;
y = Y;
z = Z;
w = W;
}
KRVector4::~KRVector4()
{
}
KRVector4& KRVector4::operator =(const KRVector4& b) {
x = b.x;
y = b.y;
z = b.z;
w = b.w;
return *this;
}
KRVector4 KRVector4::operator +(const KRVector4& b) const {
return KRVector4(x + b.x, y + b.y, z + b.z, w + b.w);
}
KRVector4 KRVector4::operator -(const KRVector4& b) const {
return KRVector4(x - b.x, y - b.y, z - b.z, w - b.w);
}
KRVector4 KRVector4::operator +() const {
return *this;
}
KRVector4 KRVector4::operator -() const {
return KRVector4(-x, -y, -z, -w);
}
KRVector4 KRVector4::operator *(const float v) const {
return KRVector4(x * v, y * v, z * v, w * v);
}
KRVector4 KRVector4::operator /(const float v) const {
return KRVector4(x / v, y / v, z / v, w/ v);
}
KRVector4& KRVector4::operator +=(const KRVector4& b) {
x += b.x;
y += b.y;
z += b.z;
w += b.w;
return *this;
}
KRVector4& KRVector4::operator -=(const KRVector4& b) {
x -= b.x;
y -= b.y;
z -= b.z;
w -= b.w;
return *this;
}
KRVector4& KRVector4::operator *=(const float v) {
x *= v;
y *= v;
z *= v;
w *= v;
return *this;
}
KRVector4& KRVector4::operator /=(const float v) {
x /= v;
y /= v;
z /= v;
w /= v;
return *this;
}
bool KRVector4::operator ==(const KRVector4& b) const {
return x == b.x && y == b.y && z == b.z && w == b.w;
}
bool KRVector4::operator !=(const KRVector4& b) const {
return x != b.x || y != b.y || z != b.z || w != b.w;
}
float& KRVector4::operator[](unsigned i) {
switch(i) {
case 0:
return x;
case 1:
return y;
case 2:
return z;
default:
case 3:
return w;
}
}
float KRVector4::operator[](unsigned i) const {
switch(i) {
case 0:
return x;
case 1:
return y;
case 2:
return z;
default:
case 3:
return w;
}
}
float KRVector4::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 KRVector4::magnitude() const {
return sqrtf(x * x + y * y + z * z + w * w);
}
void KRVector4::normalize() {
float magnitude = sqrtf(x * x + y * y + z * z + w * w);
x /= magnitude;
y /= magnitude;
z /= magnitude;
w /= magnitude;
}
KRVector4 KRVector4::Normalize(const KRVector4 &v) {
float magnitude = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w);
return KRVector4(v.x / magnitude, v.y / magnitude, v.z / magnitude, v.w / magnitude);
}
float KRVector4::Dot(const KRVector4 &v1, const KRVector4 &v2) {
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
}
bool KRVector4::operator >(const KRVector4& 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 KRVector4::operator <(const KRVector4& 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;
}
void KRVector4::setUniform(GLint location) const
{
if(location != -1) GLDEBUG(glUniform4f(location, x, y, z, w));
}

View File

@@ -0,0 +1,98 @@
//
// KRVector4.h
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#ifndef KRVECTOR4_H
#define KRVECTOR4_H
#include "KREngine-common.h"
class KRVector4 {
public:
float x, y, z, w;
KRVector4();
KRVector4(float X, float Y, float Z, float W);
KRVector4(float v);
KRVector4(float *v);
KRVector4(const KRVector4 &v);
~KRVector4();
KRVector4& operator =(const KRVector4& b);
KRVector4 operator +(const KRVector4& b) const;
KRVector4 operator -(const KRVector4& b) const;
KRVector4 operator +() const;
KRVector4 operator -() const;
KRVector4 operator *(const float v) const;
KRVector4 operator /(const float v) const;
KRVector4& operator +=(const KRVector4& b);
KRVector4& operator -=(const KRVector4& b);
KRVector4& operator *=(const float v);
KRVector4& operator /=(const float v);
bool operator ==(const KRVector4& b) const;
bool operator !=(const KRVector4& b) const;
// Comparison operators are implemented to allow insertion into sorted containers such as std::set
bool operator >(const KRVector4& b) const;
bool operator <(const KRVector4& 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 KRVector4 Normalize(const KRVector4 &v);
static float Dot(const KRVector4 &v1, const KRVector4 &v2);
static KRVector4 Min();
static KRVector4 Max();
static KRVector4 Zero();
static KRVector4 One();
static KRVector4 Forward();
static KRVector4 Backward();
static KRVector4 Up();
static KRVector4 Down();
static KRVector4 Left();
static KRVector4 Right();
static KRVector4 Lerp(const KRVector4 &v1, const KRVector4 &v2, float d);
static KRVector4 Slerp(const KRVector4 &v1, const KRVector4 &v2, float d);
static void OrthoNormalize(KRVector4 &normal, KRVector4 &tangent); // Gram-Schmidt Orthonormalization
void setUniform(GLint location) const;
};
#endif

View File

@@ -171,3 +171,81 @@ void KRViewport::setLODBias(float lod_bias)
m_lodBias = lod_bias;
}
float KRViewport::coverage(const KRAABB &b) const
{
if(!visible(b)) {
return 0.0f; // Culled out by view frustrum
} else {
KRVector2 screen_min;
KRVector2 screen_max;
// Loop through all corners and transform them to screen space
for(int i=0; i<8; i++) {
KRVector3 screen_pos = KRMat4::DotWDiv(m_matViewProjection, KRVector3(i & 1 ? b.min.x : b.max.x, i & 2 ? b.min.y : b.max.y, i & 4 ? b.min.z : b.max.z));
if(i==0) {
screen_min.x = screen_pos.x;
screen_min.y = screen_pos.y;
screen_max.x = screen_pos.x;
screen_max.y = screen_pos.y;
} else {
if(screen_pos.x < screen_min.x) screen_min.x = screen_pos.x;
if(screen_pos.y < screen_min.y) screen_min.y = screen_pos.y;
if(screen_pos.x > screen_max.x) screen_max.x = screen_pos.x;
if(screen_pos.y > screen_max.y) screen_max.y = screen_pos.y;
}
}
return (screen_max.x - screen_min.x) * (screen_max.y - screen_min.y);
}
}
bool KRViewport::visible(const KRAABB &b) const
{
// test if bounding box would be within the visible range of the clip space transformed by matViewProjection
// This is used for view frustrum culling
int outside_count[6] = {0, 0, 0, 0, 0, 0};
for(int iCorner=0; iCorner<8; iCorner++) {
KRVector3 sourceCornerVertex = KRVector3(
(iCorner & 1) == 0 ? b.min.x : b.max.x,
(iCorner & 2) == 0 ? b.min.y : b.max.y,
(iCorner & 4) == 0 ? b.min.z : b.max.z);
KRVector3 cornerVertex = KRMat4::Dot(m_matViewProjection, sourceCornerVertex);
float cornerVertexW = KRMat4::DotW(m_matViewProjection, sourceCornerVertex);
if(cornerVertex.x < -cornerVertexW) {
outside_count[0]++;
}
if(cornerVertex.y < -cornerVertexW) {
outside_count[1]++;
}
if(cornerVertex.z < -cornerVertexW) {
outside_count[2]++;
}
if(cornerVertex.x > cornerVertexW) {
outside_count[3]++;
}
if(cornerVertex.y > cornerVertexW) {
outside_count[4]++;
}
if(cornerVertex.z > cornerVertexW) {
outside_count[5]++;
}
}
bool is_visible = true;
for(int iFace=0; iFace < 6; iFace++) {
if(outside_count[iFace] == 8) {
is_visible = false;
}
}
return is_visible;
}

View File

@@ -46,6 +46,9 @@ public:
const std::set<KRLight *> &getVisibleLights();
void setVisibleLights(const std::set<KRLight *> visibleLights);
bool visible(const KRAABB &b) const;
float coverage(const KRAABB &b) const;
private:
KRVector2 m_size;
KRMat4 m_matView;
@@ -66,6 +69,8 @@ private:
void calculateDerivedValues();
std::map<KRAABB, int> m_visibleBounds; // AABB's that output fragments in the last frame
};
#endif