Asynchronous streaming and memory management improvements in progress.

Note: This branch is unstable

--HG--
branch : async_streaming
This commit is contained in:
2013-10-06 18:56:23 -07:00
parent de324ff279
commit 4dddec7f85
20 changed files with 488 additions and 199 deletions

View File

@@ -109,6 +109,10 @@
E461A176152E5C5600F2044A /* KRPointLight.h in Headers */ = {isa = PBXBuildFile; fileRef = E461A157152E555400F2044A /* KRPointLight.h */; settings = {ATTRIBUTES = (Public, ); }; };
E461A177152E5C6600F2044A /* KRMat4.h in Headers */ = {isa = PBXBuildFile; fileRef = E491017613C99BDC0098455B /* KRMat4.h */; settings = {ATTRIBUTES = (Public, ); }; };
E461A17A152E5C9100F2044A /* KRMat4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E491017713C99BDC0098455B /* KRMat4.cpp */; };
E468447F17FFDF51001F1FA1 /* KRLocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E468447D17FFDF51001F1FA1 /* KRLocator.cpp */; };
E468448017FFDF51001F1FA1 /* KRLocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E468447D17FFDF51001F1FA1 /* KRLocator.cpp */; };
E468448117FFDF51001F1FA1 /* KRLocator.h in Headers */ = {isa = PBXBuildFile; fileRef = E468447E17FFDF51001F1FA1 /* KRLocator.h */; };
E468448217FFDF51001F1FA1 /* KRLocator.h in Headers */ = {isa = PBXBuildFile; fileRef = E468447E17FFDF51001F1FA1 /* KRLocator.h */; };
E46A6B6D1559E97D000DBD37 /* KRResource+blend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E46A6B6C1559E97D000DBD37 /* KRResource+blend.cpp */; };
E46A6B701559EF0A000DBD37 /* KRResource+blend.h in Headers */ = {isa = PBXBuildFile; fileRef = E46A6B6F1559EF0A000DBD37 /* KRResource+blend.h */; settings = {ATTRIBUTES = (Public, ); }; };
E46C214515364BC8009CABF3 /* tinyxml2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E46C214215364BC8009CABF3 /* tinyxml2.cpp */; };
@@ -438,6 +442,8 @@
E461A15E152E565700F2044A /* KRDirectionalLight.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = KRDirectionalLight.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
E461A164152E56C000F2044A /* KRSpotLight.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KRSpotLight.cpp; sourceTree = "<group>"; };
E461A167152E570500F2044A /* KRSpotLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = KRSpotLight.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
E468447D17FFDF51001F1FA1 /* KRLocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KRLocator.cpp; sourceTree = "<group>"; };
E468447E17FFDF51001F1FA1 /* KRLocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRLocator.h; sourceTree = "<group>"; };
E46A6B6C1559E97D000DBD37 /* KRResource+blend.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "KRResource+blend.cpp"; sourceTree = "<group>"; };
E46A6B6F1559EF0A000DBD37 /* KRResource+blend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "KRResource+blend.h"; sourceTree = "<group>"; };
E46C214115364BC8009CABF3 /* tinyxml2_readme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tinyxml2_readme.txt; sourceTree = "<group>"; };
@@ -971,6 +977,8 @@
E480BE6B1671C653004EC8AD /* KRBone.cpp */,
E4AE635B1704FB0A00B460CD /* KRLODGroup.cpp */,
E4AE635C1704FB0A00B460CD /* KRLODGroup.h */,
E468447D17FFDF51001F1FA1 /* KRLocator.cpp */,
E468447E17FFDF51001F1FA1 /* KRLocator.h */,
);
name = "Scene Graph Nodes";
sourceTree = "<group>";
@@ -1198,6 +1206,7 @@
E461A152152E54B500F2044A /* KRLight.h in Headers */,
E461A15C152E563100F2044A /* KRDirectionalLight.h in Headers */,
E461A168152E570700F2044A /* KRSpotLight.h in Headers */,
E468448117FFDF51001F1FA1 /* KRLocator.h in Headers */,
E4F975321536220900FD60B2 /* KRNode.h in Headers */,
E46C214715364BC8009CABF3 /* tinyxml2.h in Headers */,
E48C696F15374F5B00232E28 /* KRContext.h in Headers */,
@@ -1257,6 +1266,7 @@
E497B948151BB89D00D3DC67 /* KRVector2.h in Headers */,
E4D0683F1512A790005FFBEB /* KRVector3.h in Headers */,
E461A177152E5C6600F2044A /* KRMat4.h in Headers */,
E468448217FFDF51001F1FA1 /* KRLocator.h in Headers */,
E4F975461536327C00FD60B2 /* KRMeshManager.h in Headers */,
E497B94B151BCEE900D3DC67 /* KRResource.h in Headers */,
E43B0AD915DDCA0F00A5CB9F /* KRContextObject.h in Headers */,
@@ -1544,6 +1554,7 @@
E497B950151BD2CE00D3DC67 /* KRResource+obj.cpp in Sources */,
E461A156152E54F800F2044A /* KRLight.cpp in Sources */,
E461A159152E557E00F2044A /* KRPointLight.cpp in Sources */,
E468447F17FFDF51001F1FA1 /* KRLocator.cpp in Sources */,
E461A15F152E565700F2044A /* KRDirectionalLight.cpp in Sources */,
E461A165152E56C000F2044A /* KRSpotLight.cpp in Sources */,
E4F975361536221C00FD60B2 /* KRNode.cpp in Sources */,
@@ -1607,6 +1618,7 @@
E4BBBBA71512A6DC00F43B5B /* KRVector3.cpp in Sources */,
E4B2A43B1523B02E004CB0EC /* KRMaterial.cpp in Sources */,
E4BBBB8E1512A40300F43B5B /* krengine_osx.mm in Sources */,
E468448017FFDF51001F1FA1 /* KRLocator.cpp in Sources */,
E497B947151BA99500D3DC67 /* KRVector2.cpp in Sources */,
E497B94E151BCF2500D3DC67 /* KRResource.cpp in Sources */,
E497B951151BD2CE00D3DC67 /* KRResource+obj.cpp in Sources */,

View File

@@ -85,9 +85,10 @@ bool KRAnimation::save(KRDataBlock &data) {
KRAnimation *KRAnimation::Load(KRContext &context, const std::string &name, KRDataBlock *data)
{
data->append((void *)"\0", 1); // Ensure data is null terminated, to read as a string safely
std::string xml_string = data->getString();
tinyxml2::XMLDocument doc;
doc.Parse((char *)data->getStart());
doc.Parse(xml_string.c_str());
KRAnimation *new_animation = new KRAnimation(context, name);
tinyxml2::XMLElement *animation_node = doc.RootElement();

View File

@@ -37,11 +37,13 @@ KRAnimationCurve::KRAnimationCurve(KRContext &context, const std::string &name)
{
m_pData = new KRDataBlock();
m_pData->expand(sizeof(animation_curve_header));
m_pData->lock();
animation_curve_header *header = (animation_curve_header *)m_pData->getStart();
strcpy(header->szTag, "KRCURVE1.0 ");
header->frame_rate = 30.0f;
header->frame_start = 0;
header->frame_count = 0;
m_pData->unlock();
}
KRAnimationCurve::~KRAnimationCurve()
@@ -84,11 +86,16 @@ KRAnimationCurve *KRAnimationCurve::Load(KRContext &context, const std::string &
int KRAnimationCurve::getFrameCount()
{
return ((animation_curve_header *)m_pData->getStart())->frame_count;
m_pData->lock();
int frame_count = ((animation_curve_header *)m_pData->getStart())->frame_count;
m_pData->unlock();
return frame_count;
}
void KRAnimationCurve::setFrameCount(int frame_count)
{
m_pData->lock();
int prev_frame_count = getFrameCount();
if(frame_count != prev_frame_count) {
float fill_value = 0.0f;
@@ -102,30 +109,42 @@ void KRAnimationCurve::setFrameCount(int frame_count)
}
((animation_curve_header *)m_pData->getStart())->frame_count = frame_count;
}
m_pData->unlock();
}
float KRAnimationCurve::getFrameRate()
{
return ((animation_curve_header *)m_pData->getStart())->frame_rate;
m_pData->lock();
float frame_rate =((animation_curve_header *)m_pData->getStart())->frame_rate;
m_pData->unlock();
return frame_rate;
}
void KRAnimationCurve::setFrameRate(float frame_rate)
{
m_pData->lock();
((animation_curve_header *)m_pData->getStart())->frame_rate = frame_rate;
m_pData->unlock();
}
int KRAnimationCurve::getFrameStart()
{
return ((animation_curve_header *)m_pData->getStart())->frame_start;
m_pData->lock();
int frame_start = ((animation_curve_header *)m_pData->getStart())->frame_start;
m_pData->unlock();
return frame_start;
}
void KRAnimationCurve::setFrameStart(int frame_number)
{
m_pData->lock();
((animation_curve_header *)m_pData->getStart())->frame_start = frame_number;
m_pData->unlock();
}
float KRAnimationCurve::getValue(int frame_number)
{
m_pData->lock();
//printf("frame_number: %i\n", frame_number);
int clamped_frame = frame_number - getFrameStart();
if(clamped_frame < 0) {
@@ -134,43 +153,56 @@ float KRAnimationCurve::getValue(int frame_number)
clamped_frame = getFrameCount()-1;
}
float *frame_data = (float *)((char *)m_pData->getStart() + sizeof(animation_curve_header));
return frame_data[clamped_frame];
float v = frame_data[clamped_frame];
m_pData->unlock();
return v;
}
void KRAnimationCurve::setValue(int frame_number, float value)
{
m_pData->lock();
int clamped_frame = frame_number - getFrameStart();
if(clamped_frame >= 0 && clamped_frame < getFrameCount()) {
float *frame_data = (float *)((char *)m_pData->getStart() + sizeof(animation_curve_header));
frame_data[clamped_frame] = value;
}
m_pData->unlock();
}
float KRAnimationCurve::getValue(float local_time)
{
// TODO - Need to add interpolation for time values between frames.
// Must consider looping animations when determining which two frames to interpolate between.
return getValue((int)(local_time * getFrameRate()));
m_pData->lock();
float v = getValue((int)(local_time * getFrameRate()));
m_pData->unlock();
return v;
}
bool KRAnimationCurve::valueChanges(float start_time, float duration)
{
return valueChanges((int)(start_time * getFrameRate()), (int)(duration * getFrameRate()));
m_pData->lock();
bool c = valueChanges((int)(start_time * getFrameRate()), (int)(duration * getFrameRate()));
m_pData->unlock();
return c;
}
bool KRAnimationCurve::valueChanges(int start_frame, int frame_count)
{
m_pData->lock();
float first_value = getValue(start_frame);
bool change_found = false;
// Range of frames is not inclusive of last frame
for(int frame_number = start_frame + 1; frame_number < start_frame + frame_count; frame_number++) {
for(int frame_number = start_frame + 1; frame_number < start_frame + frame_count && !change_found; frame_number++) {
if(getValue(frame_number) != first_value) {
return true;
change_found = true;
}
}
return false;
m_pData->unlock();
return change_found;
}
KRAnimationCurve *KRAnimationCurve::split(const std::string &name, float start_time, float duration)
@@ -185,11 +217,13 @@ KRAnimationCurve *KRAnimationCurve::split(const std::string &name, int start_fra
new_curve->setFrameRate(getFrameRate());
new_curve->setFrameStart(start_frame);
new_curve->setFrameCount(frame_count);
new_curve->m_pData->lock();
// Range of frames is not inclusive of last frame
for(int frame_number = start_frame; frame_number < start_frame + frame_count; frame_number++) {
new_curve->setValue(frame_number, getValue(frame_number)); // TODO - MEMCPY here?
}
new_curve->m_pData->unlock();
getContext().getAnimationCurveManager()->addAnimationCurve(new_curve);
return new_curve;

View File

@@ -214,8 +214,8 @@ void KRAudioManager::renderAudio(UInt32 inNumberFrames, AudioBufferList *ioData)
uint64_t end_time = mach_absolute_time();
uint64_t duration = (end_time - start_time) * m_timebase_info.numer / m_timebase_info.denom; // Nanoseconds
uint64_t max_duration = (uint64_t)inNumberFrames * 1000000000 / 44100;
// uint64_t duration = (end_time - start_time) * m_timebase_info.numer / m_timebase_info.denom; // Nanoseconds
// uint64_t max_duration = (uint64_t)inNumberFrames * 1000000000 / 44100;
// fprintf(stderr, "audio load: %5.1f%% hrtf channels: %li\n", (float)(duration * 1000 / max_duration) / 10.0f, m_mapped_sources.size());
}
@@ -1364,14 +1364,14 @@ KRDataBlock *KRAudioManager::getBufferData(int size)
data = new KRDataBlock();
data->expand(size);
}
data->lock();
return data;
}
void KRAudioManager::recycleBufferData(KRDataBlock *data)
{
if(data != NULL) {
data->unlock();
if(data->getSize() == KRENGINE_AUDIO_MAX_BUFFER_SIZE && m_bufferPoolIdle.size() < KRENGINE_AUDIO_MAX_POOL_SIZE) {
m_bufferPoolIdle.push_back(data);
} else {

View File

@@ -40,6 +40,7 @@
KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string extension) : KRResource(context, name)
{
m_pData = new KRDataBlock();
m_pData->lock();
m_extension = extension;
m_audio_file_id = 0;
@@ -55,6 +56,7 @@ KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string e
KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string extension, KRDataBlock *data) : KRResource(context, name)
{
m_pData = data;
m_pData->lock();
m_extension = extension;
m_audio_file_id = 0;
@@ -71,6 +73,7 @@ KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string e
KRAudioSample::~KRAudioSample()
{
closeFile();
m_pData->unlock();
delete m_pData;
}
@@ -198,7 +201,8 @@ OSStatus KRAudioSample::ReadProc( // AudioFile_ReadProc
KRAudioSample *sound = (KRAudioSample *)inClientData;
UInt32 max_count = sound->m_pData->getSize() - inPosition;
*actualCount = requestCount < max_count ? requestCount : max_count;
memcpy(buffer, (unsigned char *)sound->m_pData->getStart() + inPosition, *actualCount);
sound->m_pData->copy(buffer, inPosition, *actualCount);
//memcpy(buffer, (unsigned char *)sound->m_pData->getStart() + inPosition, *actualCount);
return noErr;
}
@@ -231,6 +235,7 @@ void KRAudioSample::openFile()
{
// AudioFileInitializeWithCallbacks
if(m_fileRef == NULL) {
// Temp variables
UInt32 propertySize;

View File

@@ -53,35 +53,18 @@ KRBundle::KRBundle(KRContext &context, std::string name, KRDataBlock *pData) : K
{
m_pData = pData;
unsigned char *pFile = (unsigned char *)m_pData->getStart();
while(pFile < m_pData->getEnd() ) {
tar_header_type *file_header = (tar_header_type *)pFile;
size_t file_size = strtol(file_header->file_size, NULL, 8);
pFile += 512; // Skip past the header to the file contents
if(file_header->file_name[0] != '\0' && file_header->file_name[0] != '.') {
__int64_t file_pos = 0;
while(file_pos < m_pData->getSize()) {
tar_header_type file_header;
m_pData->copy(&file_header, file_pos, sizeof(file_header));
size_t file_size = strtol(file_header.file_size, NULL, 8);
file_pos += 512; // Skip past the header to the file contents
if(file_header.file_name[0] != '\0' && file_header.file_name[0] != '.') {
// We ignore the last two records in the tar file, which are zero'ed out tar_header structures
KRDataBlock *pFileData = new KRDataBlock();
if(pFileData->load(pFile, file_size)) {
context.loadResource(file_header->file_name, pFileData);
} else {
delete pFileData;
assert(false);
}
KRDataBlock *pFileData = pData->getSubBlock(file_pos, file_size);
context.loadResource(file_header.file_name, pFileData);
}
// Advance past the end of the file
/*
if((file_size & 0x01ff) == 0) {
// file size is a multiple of 512 bytes, we can just add it
pFile += file_size;
} else {
// We would not be on a 512 byte boundary, round up to the next one
pFile += (file_size + 0x0200) - (file_size & 0x1ff);
}
*/
pFile += RoundUpSize(file_size);
file_pos += RoundUpSize(file_size);
}
}
@@ -90,7 +73,9 @@ KRBundle::KRBundle(KRContext &context, std::string name) : KRResource(context, n
// Create an empty krbundle (tar) file, initialized with two zero-ed out file headers, which terminate it.
m_pData = new KRDataBlock();
m_pData->expand(KRENGINE_KRBUNDLE_HEADER_SIZE * 2);
m_pData->lock();
memset(m_pData->getStart(), 0, m_pData->getSize());
m_pData->unlock();
}
size_t KRBundle::RoundUpSize(size_t s)
@@ -142,6 +127,8 @@ void KRBundle::append(KRResource &resource)
m_pData->expand(KRENGINE_KRBUNDLE_HEADER_SIZE + resource_data.getSize() + padding_size - KRENGINE_KRBUNDLE_HEADER_SIZE * 2); // We will overwrite the existing zero-ed out file headers that marked the end of the archive, so we don't have to include their size here
m_pData->lock();
// Get location of file header
tar_header_type *file_header = (tar_header_type *)((unsigned char *)m_pData->getEnd() - padding_size - resource_data.getSize() - KRENGINE_KRBUNDLE_HEADER_SIZE);
@@ -149,7 +136,9 @@ void KRBundle::append(KRResource &resource)
memset(file_header, 0, KRENGINE_KRBUNDLE_HEADER_SIZE);
// Copy resource data
resource_data.lock();
memcpy((unsigned char *)m_pData->getEnd() - padding_size - resource_data.getSize(), resource_data.getStart(), resource_data.getSize());
resource_data.unlock();
// Zero out alignment padding and terminating set of file header blocks
memset((unsigned char *)m_pData->getEnd() - padding_size, 0, padding_size);
@@ -172,4 +161,6 @@ void KRBundle::append(KRResource &resource)
check_sum += byte_ptr[i];
}
sprintf(file_header->checksum, "%07o", check_sum);
m_pData->unlock();
}

View File

@@ -30,12 +30,18 @@
//
#include "KRDataBlock.h"
#include "KREngine-common.h"
KRDataBlock::KRDataBlock() {
m_data = NULL;
m_data_size = 0;
m_data_offset = 0;
m_fdPackFile = 0;
m_mmapData = NULL;
m_fileOwnerDataBlock = NULL;
m_bMalloced = false;
m_lockCount = 0;
m_bReadOnly = false;
}
KRDataBlock::~KRDataBlock() {
@@ -45,10 +51,13 @@ KRDataBlock::~KRDataBlock() {
// Unload a file, releasing any mmap'ed file handles or malloc'ed ram that was in use
void KRDataBlock::unload()
{
assert(m_lockCount == 0);
if(m_fdPackFile) {
// Memory mapped file
munmap(m_data, m_data_size);
close(m_fdPackFile);
if(m_fileOwnerDataBlock == this) {
close(m_fdPackFile);
}
} else if(m_data != NULL && m_bMalloced) {
// Malloc'ed data
free(m_data);
@@ -57,7 +66,11 @@ void KRDataBlock::unload()
m_bMalloced = false;
m_data = NULL;
m_data_size = 0;
m_data_offset = 0;
m_fdPackFile = 0;
m_mmapData = NULL;
m_fileOwnerDataBlock = NULL;
m_bReadOnly = false;
}
// Encapsulate a pointer. Note - The pointer will not be free'ed
@@ -66,6 +79,8 @@ bool KRDataBlock::load(void *data, size_t size)
unload();
m_data = data;
m_data_size = size;
m_data_offset = 0;
m_bReadOnly = false;
return true;
}
@@ -76,14 +91,14 @@ bool KRDataBlock::load(const std::string &path)
unload();
struct stat statbuf;
m_bReadOnly = true;
m_fdPackFile = open(path.c_str(), O_RDONLY);
if(m_fdPackFile >= 0) {
m_fileOwnerDataBlock = this;
if(fstat(m_fdPackFile, &statbuf) >= 0) {
if ((m_data = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, m_fdPackFile, 0)) == (caddr_t) -1) {
} else {
m_data_size = statbuf.st_size;
success = true;
}
m_data_size = statbuf.st_size;
m_data_offset = 0;
success = true;
}
}
if(!success) {
@@ -93,13 +108,32 @@ bool KRDataBlock::load(const std::string &path)
return success;
}
// Create a KRDataBlock encapsulating a sub-region of this block. The caller is responsible to free the object.
KRDataBlock *KRDataBlock::getSubBlock(int start, int length)
{
KRDataBlock *new_block = new KRDataBlock();
new_block->m_data_size = length;
if(m_fdPackFile) {
new_block->m_fdPackFile = m_fdPackFile;
new_block->m_fileOwnerDataBlock = m_fileOwnerDataBlock;
new_block->m_data_offset = start;
} else if(m_bMalloced) {
new_block->m_data = (unsigned char *)m_data + start;
}
new_block->m_bReadOnly = true;
return new_block;
}
// Return a pointer to the start of the data block
void *KRDataBlock::getStart() {
assertLocked();
return m_data;
}
// Return a pointer to the byte after the end of the data block
void *KRDataBlock::getEnd() {
assertLocked();
return (unsigned char *)m_data + m_data_size;
}
@@ -111,28 +145,33 @@ size_t KRDataBlock::getSize() const {
// Expand the data block, and switch it to read-write mode. Note - this may result in a mmap'ed file being copied to malloc'ed ram and then closed
void KRDataBlock::expand(size_t size)
{
if(m_data == NULL) {
if(m_data == NULL && m_fdPackFile == 0) {
// Starting with an empty data block; allocate memory on the heap
m_data = malloc(size);
assert(m_data != NULL);
m_data_size = size;
m_data_offset = 0;
m_bMalloced = true;
} else if(m_bMalloced) {
// Starting with a malloc'ed data block; realloc it expand
m_data = realloc(m_data, m_data_size + size);
m_data_size += size;
} else {
// Starting with a mmap'ed data block; copy it to ram before expanding to avoid updating the original file until save() is called
// Starting with a mmap'ed data block, an encapsulated pointer, or a sub-block; copy it to ram before expanding to avoid updating the original file until save() is called
// ... Or starting with a pointer reference, we must make our own copy and must not free the pointer
void *pNewData = malloc(m_data_size + size);
assert(pNewData != NULL);
memcpy((unsigned char *)pNewData, m_data, m_data_size); // Copy exising data
// Copy exising data
copy(pNewData);
// Unload existing data allocation, which is now redundant
size_t new_size = m_data_size + size; // We need to store this before unload() as unload() will reset it
unload();
m_bMalloced = true;
m_data = pNewData;
m_data_size = new_size;
m_data_offset = 0;
}
}
@@ -142,12 +181,31 @@ void KRDataBlock::append(void *data, size_t size) {
expand(size);
// Fill the new space with the data to append
lock();
memcpy((unsigned char *)m_data + m_data_size - size, data, size);
unlock();
}
// Copy the entire data block to the destination pointer
void KRDataBlock::copy(void *dest) {
lock();
memcpy((unsigned char *)dest, m_data, m_data_size);
unlock();
}
// Copy a range of data to the destination pointer
void KRDataBlock::copy(void *dest, int start, int count) {
lock();
memcpy((unsigned char *)dest, (unsigned char *)m_data + start, count);
unlock();
}
// Append data to the end of the block, increasing the size of the block and making it read-write.
void KRDataBlock::append(KRDataBlock &data) {
data.lock();
append(data.getStart(), data.getSize());
data.unlock();
}
// Append string to the end of the block, increasing the size of the block and making it read-write. The null terminating character is included
@@ -157,7 +215,7 @@ void KRDataBlock::append(const std::string &s)
append((void *)szText, strlen(szText)+1);
}
// Save the data to a file, and switch to read-only mode. The data pointer will be replaced with a mmap'ed address of the file; the malloc'ed data will be freed
// Save the data to a file.
bool KRDataBlock::save(const std::string& path) {
int fdNewFile = open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
if(fdNewFile == -1) {
@@ -173,20 +231,16 @@ bool KRDataBlock::save(const std::string& path) {
close(fdNewFile);
return false;
} else if(m_data != NULL) {
// Copy data to new file
memcpy(pNewData, m_data, m_data_size);
copy(pNewData);
// Unload existing data allocation, which is now redundant
size_t new_size = m_data_size; // We need to store this, as unload() will reset it
unload();
// Protect new mmap'ed memory
mprotect(pNewData, m_data_size, PROT_READ);
// Unmap the new file
munmap(pNewData, m_data_size);
// Switch pointer to use new mmap'ed memory
m_data_size = new_size;
m_fdPackFile = fdNewFile;
m_data = pNewData;
// Close the new file
close(fdNewFile);
}
return true;
}
@@ -195,8 +249,57 @@ bool KRDataBlock::save(const std::string& path) {
// Get contents as a string
std::string KRDataBlock::getString()
{
lock();
KRDataBlock b;
b.append(*this);
b.append((void *)"\0", 1); // Ensure data is null terminated, to read as a string safely
return std::string((char *)b.getStart());
b.lock();
std::string ret = std::string((char *)b.getStart());
b.unlock();
unlock();
return ret;
}
// Lock the memory, forcing it to be loaded into a contiguous block of address space
void KRDataBlock::lock()
{
m_lockCount++;
if(m_lockCount == 1) {
// Memory mapped file; ensure data is mapped to ram
if(m_fdPackFile) {
// Round m_data_offset down to the next memory page, as required by mmap
size_t alignment_offset = m_data_offset & (KRAKEN_MEM_PAGE_SIZE - 1);
if ((m_mmapData = mmap(0, m_data_size + alignment_offset, m_bReadOnly ? PROT_READ : PROT_WRITE, MAP_SHARED, m_fdPackFile, m_data_offset - alignment_offset)) == (caddr_t) -1) {
assert(false); // mmap() failed.
}
m_data = (unsigned char *)m_mmapData + alignment_offset;
}
}
}
// Unlock the memory, releasing the address space for use by other allocations
void KRDataBlock::unlock()
{
// We expect that the data block was previously locked
assertLocked();
m_lockCount--;
if(m_lockCount == 0) {
// Memory mapped file; ensure data is unmapped from ram
if(m_fdPackFile) {
munmap(m_mmapData, m_data_size);
m_data = NULL;
m_mmapData = NULL;
}
}
}
// Assert if not locked
void KRDataBlock::assertLocked()
{
assert(m_lockCount > 0);
}

View File

@@ -45,9 +45,12 @@ public:
// Load a file into memory using mmap. The data pointer will be protected as read-only until append() or expand() is called
bool load(const std::string &path);
// Save the data to a file, and switch to read-only mode. The data pointer will be replaced with a mmap'ed address of the file; the malloc'ed data will be freed
// Save the data to a file.
bool save(const std::string& path);
// Create a KRDataBlock encapsulating a sub-region of this block. The caller is responsible to free the object.
KRDataBlock *getSubBlock(int start, int length);
// Append data to the end of the block, increasing the size of the block and making it read-write.
void append(void *data, size_t size);
@@ -74,15 +77,40 @@ public:
// Get the contents as a string
std::string getString();
// Copy the entire data block to the destination pointer
void copy(void *dest);
// Copy a range of data to the destination pointer
void copy(void *dest, int start, int count);
// Lock the memory, forcing it to be loaded into a contiguous block of address space
void lock();
// Unlock the memory, releasing the address space for use by other allocations
void unlock();
private:
void *m_data;
size_t m_data_size;
size_t m_data_offset;
// For memory mapped objects:
int m_fdPackFile;
KRDataBlock *m_fileOwnerDataBlock;
void *m_mmapData;
// For malloc'ed objects:
bool m_bMalloced;
// Lock refcount
int m_lockCount;
// Read-only allocation
bool m_bReadOnly;
// Assert if not locked
void assertLocked();
};
#endif

View File

@@ -11,6 +11,8 @@
#ifndef KRENGINE_COMMON_H
#define KRENGINE_COMMON_H
#define KRAKEN_MEM_PAGE_SIZE 4096
#define KRAKEN_MEM_ROUND_DOWN_PAGE(x) (x & ~(KRAKEN_MEM_PAGE_SIZE - 1))
#define KRENGINE_MAX_TEXTURE_UNITS 8
float const PI = 3.141592653589793f;

View File

@@ -0,0 +1,35 @@
//
// KRLocator.cpp
// KREngine
//
// Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#include "KRLocator.h"
#include "KRContext.h"
KRLocator::KRLocator(KRScene &scene, std::string name) : KRNode(scene, name)
{
setScaleCompensation(true);
}
KRLocator::~KRLocator()
{
}
std::string KRLocator::getElementName() {
return "locator";
}
tinyxml2::XMLElement *KRLocator::saveXML( tinyxml2::XMLNode *parent)
{
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
return e;
}
void KRLocator::loadXML(tinyxml2::XMLElement *e)
{
KRNode::loadXML(e);
}

View File

@@ -0,0 +1,27 @@
//
// KRLocator
// KREngine
//
// Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#ifndef KRLOCATOR_H
#define KRLOCATOR_H
#include "KRResource.h"
#include "KRNode.h"
#include "KRTexture.h"
class KRLocator : public KRNode {
public:
KRLocator(KRScene &scene, std::string name);
virtual ~KRLocator();
virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
virtual void loadXML(tinyxml2::XMLElement *e);
};
#endif

View File

@@ -100,7 +100,7 @@ void KRMaterialManager::add(KRMaterial *new_material) {
bool KRMaterialManager::load(const char *szName, KRDataBlock *data) {
KRMaterial *pMaterial = NULL;
char szSymbol[16][256];
data->lock();
char *pScan = (char *)data->getStart();
char *pEnd = (char *)data->getEnd();
@@ -282,7 +282,7 @@ bool KRMaterialManager::load(const char *szName, KRDataBlock *data) {
}
}
data->unlock();
delete data;
return true;
}

View File

@@ -46,6 +46,7 @@ KRMesh::KRMesh(KRContext &context, std::string name) : KRResource(context, name)
m_materials.clear();
m_uniqueMaterials.clear();
m_pData = new KRDataBlock();
m_pData->lock();
setName(name);
}
@@ -54,6 +55,7 @@ KRMesh::KRMesh(KRContext &context, std::string name, KRDataBlock *data) : KRReso
m_materials.clear();
m_uniqueMaterials.clear();
m_pData = new KRDataBlock();
m_pData->lock();
setName(name);
loadPack(data);
@@ -104,6 +106,7 @@ int KRMesh::GetLODCoverage(const std::string &name)
KRMesh::~KRMesh() {
clearData();
m_pData->unlock();
if(m_pData) delete m_pData;
}
@@ -124,8 +127,10 @@ bool KRMesh::save(KRDataBlock &data) {
void KRMesh::loadPack(KRDataBlock *data) {
clearData();
m_pData->unlock();
delete m_pData;
m_pData = data;
m_pData->lock();
updateAttributeOffsets();
pack_header *pHeader = getHeader();
m_minPoint = KRVector3(pHeader->minx, pHeader->miny, pHeader->minz);
@@ -134,6 +139,8 @@ void KRMesh::loadPack(KRDataBlock *data) {
void KRMesh::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 KRMat4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const std::vector<KRBone *> &bones) {
m_pData->lock();
//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();
@@ -214,6 +221,8 @@ void KRMesh::render(const std::string &object_name, KRCamera *pCamera, std::vect
}
}
}
m_pData->unlock();
}
GLfloat KRMesh::getMaxDimension() {
@@ -429,8 +438,9 @@ void KRMesh::LoadData(/*std::vector<__uint16_t> vertex_indexes, std::vector<std:
size_t vertex_count = mi.vertices.size();
size_t bone_count = mi.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) + KRALIGN(8 * index_base_count) + vertex_size * vertex_count;
m_pData->unlock();
m_pData->expand(new_file_size);
m_pData->lock();
pack_header *pHeader = getHeader();
memset(pHeader, 0, sizeof(pack_header));
@@ -586,7 +596,9 @@ KRVector3 KRMesh::getMaxPoint() const {
}
void KRMesh::clearData() {
m_pData->unlock();
m_pData->unload();
m_pData->lock();
}
void KRMesh::clearBuffers() {
@@ -892,8 +904,11 @@ size_t KRMesh::AttributeOffset(__int32_t vertex_attrib, __int32_t vertex_attrib_
int KRMesh::getBoneCount()
{
m_pData->lock();
pack_header *header = getHeader();
return header->bone_count;
int bone_count = header->bone_count;
m_pData->unlock();
return bone_count;
}
char *KRMesh::getBoneName(int bone_index)
@@ -908,7 +923,10 @@ KRMat4 KRMesh::getBoneBindPose(int bone_index)
KRMesh::model_format_t KRMesh::getModelFormat() const
{
return (model_format_t)getHeader()->model_format;
m_pData->lock();
model_format_t f = (model_format_t)getHeader()->model_format;
m_pData->unlock();
return f;
}
bool KRMesh::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)
@@ -1055,7 +1073,7 @@ bool KRMesh::lineCast(const KRVector3 &v0, const KRVector3 &v1, KRHitInfo &hitin
void KRMesh::convertToIndexed()
{
m_pData->lock();
char *szKey = new char[m_vertex_size * 2 + 1];
// Convert model to indexed vertices, identying vertexes with identical attributes and optimizing order of trianges for best usage post-vertex-transform cache on GPU
@@ -1230,6 +1248,8 @@ void KRMesh::convertToIndexed()
mi.format = KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES;
m_pData->unlock();
LoadData(mi, false, false);
}
@@ -1284,85 +1304,89 @@ int KRMesh::getTriangleVertexIndex(int submesh, int index) const
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 index_group = getSubmesh(submesh_index)->index_group;
int index_group_offset = getSubmesh(submesh_index)->index_group_offset;
while(vertexes_remaining > 0) {
int start_index_offset, start_vertex_offset, index_count, vertex_count;
getIndexedRange(index_group++, start_index_offset, start_vertex_offset, index_count, vertex_count);
int vertexes_to_process = vertexes_remaining;
if(vertexes_to_process + index_group_offset > 0xffff) {
vertexes_to_process = 0xffff - index_group_offset;
}
__uint16_t *index_data_start = index_data + start_index_offset + index_group_offset;
// ----====---- Step 1: Optimize triangle drawing order to maximize use of the GPU's post-transform vertex cache ----====----
Forsyth::OptimizeFaces(index_data_start, vertexes_to_process, vertex_count, new_indices, 16); // FINDME, TODO - GPU post-transform vertex cache size of 16 should be configureable
memcpy(index_data_start, new_indices, vertexes_to_process * sizeof(__uint16_t));
vertexes_remaining -= vertexes_to_process;
/*
unsigned char * vertex_data_start = vertex_data + start_vertex_offset;
// ----====---- 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++;
m_pData->lock();
if(getModelFormat() == KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES) {
__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 index_group = getSubmesh(submesh_index)->index_group;
int index_group_offset = getSubmesh(submesh_index)->index_group_offset;
while(vertexes_remaining > 0) {
int start_index_offset, start_vertex_offset, index_count, vertex_count;
getIndexedRange(index_group++, start_index_offset, start_vertex_offset, index_count, vertex_count);
int vertexes_to_process = vertexes_remaining;
if(vertexes_to_process + index_group_offset > 0xffff) {
vertexes_to_process = 0xffff - index_group_offset;
}
__uint16_t *index_data_start = index_data + start_index_offset + index_group_offset;
// ----====---- Step 1: Optimize triangle drawing order to maximize use of the GPU's post-transform vertex cache ----====----
Forsyth::OptimizeFaces(index_data_start, vertexes_to_process, vertex_count, new_indices, 16); // FINDME, TODO - GPU post-transform vertex cache size of 16 should be configureable
memcpy(index_data_start, new_indices, vertexes_to_process * sizeof(__uint16_t));
vertexes_remaining -= vertexes_to_process;
/*
unsigned char * vertex_data_start = vertex_data + start_vertex_offset;
// ----====---- 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);
*/
index_group_offset = 0;
}
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);
*/
index_group_offset = 0;
}
}
free(new_indices);
free(vertex_mapping);
free(new_vertex_data);
} // if(getModelFormat() == KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES)
free(new_indices);
free(vertex_mapping);
free(new_vertex_data);
m_pData->unlock();
}

View File

@@ -20,6 +20,7 @@
#include "KRAABB.h"
#include "KRQuaternion.h"
#include "KRBone.h"
#include "KRLocator.h"
#include "KRAudioSource.h"
#include "KRAmbientZone.h"
#include "KRReverbZone.h"
@@ -421,6 +422,8 @@ KRNode *KRNode::LoadXML(KRScene &scene, tinyxml2::XMLElement *e) {
new_node = new KRCollider(scene, szName, e->Attribute("mesh"), 65535, 1.0f);
} else if(strcmp(szElementName, "bone") == 0) {
new_node = new KRBone(scene, szName);
} else if(strcmp(szElementName, "locator") == 0) {
new_node = new KRLocator(scene, szName);
} else if(strcmp(szElementName, "audio_source") == 0) {
new_node = new KRAudioSource(scene, szName);
} else if(strcmp(szElementName, "ambient_zone") == 0) {

View File

@@ -23,6 +23,7 @@
#include "KRScene.h"
#include "KRQuaternion.h"
#include "KRBone.h"
#include "KRLocator.h"
#include "KRBundle.h"
#include "KRModel.h"
#include "KRLODGroup.h"
@@ -46,6 +47,7 @@ void LoadMesh(KRContext &context, KFbxScene* pFbxScene, FbxGeometryConverter *pG
KRNode *LoadMesh(KRNode *parent_node, KFbxScene* pFbxScene, FbxGeometryConverter *pGeometryConverter, KFbxNode* pNode);
KRNode *LoadLight(KRNode *parent_node, KFbxNode* pNode);
KRNode *LoadSkeleton(KRNode *parent_node, FbxScene* pScene, KFbxNode* pNode);
KRNode *LoadLocator(KRNode *parent_node, FbxScene* pScene, KFbxNode* pNode);
KRNode *LoadCamera(KRNode *parent_node, KFbxNode* pNode);
std::string GetFbxObjectName(FbxObject *obj);
@@ -54,9 +56,25 @@ const float KRAKEN_FBX_ANIMATION_FRAMERATE = 30.0f; // FINDME - This should be c
std::string GetFbxObjectName(FbxObject *obj)
{
bool is_locator = false;
KFbxNode *node = FbxCast<KFbxNode>(obj);
if(node) {
KFbxNodeAttribute::EType attribute_type = (node->GetNodeAttribute()->GetAttributeType());
if(attribute_type == KFbxNodeAttribute::eNull) {
KFbxNull* pSourceNull = (KFbxNull*) node->GetNodeAttribute();
if(pSourceNull->Look.Get() == KFbxNull::eCross ) {
is_locator = true;
}
}
}
// Object names from FBX files are now concatenated with the FBX numerical ID to ensure that they are unique
// TODO - This should be updated to only add a prefix or suffix if needed to make the name unique
if(strcmp(obj->GetName(), "default_camera") == 0) {
if(is_locator) {
// We do not rename locators
return std::string(obj->GetName());
} else if(strcmp(obj->GetName(), "default_camera") == 0) {
// There is currently support for rendering from only one camera, "default_camera". We don't translate this node's name, so that animations can drive the camera
return "default_camera";
} else {
@@ -955,54 +973,40 @@ void LoadNode(KFbxScene* pFbxScene, KRNode *parent_node, FbxGeometryConverter *p
case KFbxNodeAttribute::eSkeleton:
new_node = LoadSkeleton(parent_node, pFbxScene, pNode);
break;
case KFbxNodeAttribute::eCamera:
new_node = LoadCamera(parent_node, pNode);
break;
default:
{
if(pNode->GetChildCount() > 0) {
// Create an empty node, for inheritence of transforms
std::string name = GetFbxObjectName(pNode);
float min_distance = 0.0f;
float max_distance = 0.0f;
typedef boost::tokenizer<boost::char_separator<char> > char_tokenizer;
int step = 0;
char_tokenizer name_components(name, boost::char_separator<char>("_"));
for(char_tokenizer::iterator itr=name_components.begin(); itr != name_components.end(); itr++) {
std::string component = *itr;
std::transform(component.begin(), component.end(),
component.begin(), ::tolower);
if(component.compare("lod") == 0) {
step = 1;
} else if(step == 1) {
min_distance = boost::lexical_cast<float>(component);
step++;
} else if(step == 2) {
max_distance = boost::lexical_cast<float>(component);
step++;
}
bool is_locator = false;
if(attribute_type == KFbxNodeAttribute::eNull) {
KFbxNull* pSourceNull = (KFbxNull*) pNode->GetNodeAttribute();
if(pSourceNull->Look.Get() == KFbxNull::eCross ) {
is_locator = true;
}
/*
if(min_distance == 0.0f && max_distance == 0.0f) {
// Regular node for grouping children together under one transform
new_node = new KRNode(parent_node->getScene(), name);
} else {
*/
// LOD Enabled group node
KRLODGroup *lod_group = new KRLODGroup(parent_node->getScene(), name);
lod_group->setMinDistance(min_distance);
lod_group->setMaxDistance(max_distance);
new_node = lod_group;
/*
}
if(is_locator) {
new_node = LoadLocator(parent_node, pFbxScene, pNode);
} else {
if(pNode->GetChildCount() > 0) {
// Create an empty node, for inheritence of transforms
std::string name = GetFbxObjectName(pNode);
/*
if(min_distance == 0.0f && max_distance == 0.0f) {
// Regular node for grouping children together under one transform
new_node = new KRNode(parent_node->getScene(), name);
} else {
*/
// LOD Enabled group node
KRLODGroup *lod_group = new KRLODGroup(parent_node->getScene(), name);
lod_group->setMinDistance(0.0f);
lod_group->setMaxDistance(0.0f);
new_node = lod_group;
}
*/
}
}
break;
@@ -1526,6 +1530,21 @@ KRNode *LoadSkeleton(KRNode *parent_node, FbxScene* pFbxScene, KFbxNode* pNode)
return new_bone;
}
KRNode *LoadLocator(KRNode *parent_node, FbxScene* pFbxScene, KFbxNode* pNode) {
std::string name = GetFbxObjectName(pNode);
KRLocator *new_locator = new KRLocator(parent_node->getScene(), name.c_str());
//static bool GetBindPoseContaining(FbxScene* pScene, FbxNode* pNode, PoseList& pPoseList, FbxArray<int>& pIndex);
// PoseList pose_list;
// FbxArray<int> pose_indices;
// if(FbxPose::GetBindPoseContaining(pFbxScene, pNode, pose_list, pose_indices)) {
// fprintf(stderr, "Found bind pose(s)!\n");
// }
return new_locator;
}
KRNode *LoadCamera(KRNode *parent_node, KFbxNode* pNode) {
FbxCamera *camera = (FbxCamera *)pNode->GetNodeAttribute();
const char *szName = pNode->GetName();

View File

@@ -406,7 +406,9 @@ KRScene *KRScene::Load(KRContext &context, const std::string &name, KRDataBlock
{
data->append((void *)"\0", 1); // Ensure data is null terminated, to read as a string safely
tinyxml2::XMLDocument doc;
data->lock();
doc.Parse((char *)data->getStart());
data->unlock();
KRScene *new_scene = new KRScene(context, name);
tinyxml2::XMLElement *scene_element = doc.RootElement();

View File

@@ -254,12 +254,12 @@ bool KRShaderManager::selectShader(KRCamera &camera, KRShader *pShader, const KR
}
void KRShaderManager::loadFragmentShader(const std::string &name, KRDataBlock *data) {
m_fragShaderSource[name] = string((char *)data->getStart(), data->getSize());
m_fragShaderSource[name] = data->getString();
delete data;
}
void KRShaderManager::loadVertexShader(const std::string &name, KRDataBlock *data) {
m_vertShaderSource[name] = string((char *)data->getStart(), data->getSize());
m_vertShaderSource[name] = data->getString();
delete data;
}

View File

@@ -36,9 +36,11 @@
KRTexture2D::KRTexture2D(KRContext &context, KRDataBlock *data, std::string name) : KRTexture(context, name) {
m_current_lod_max_dim = 0;
m_pData = data;
m_pData->lock();
}
KRTexture2D::~KRTexture2D() {
m_pData->unlock();
delete m_pData;
}

View File

@@ -64,6 +64,7 @@ typedef struct _PVRTexHeader
KRTexturePVR::KRTexturePVR(KRContext &context, KRDataBlock *data, std::string name) : KRTexture2D(context, data, name) {
#if TARGET_OS_IPHONE
m_pData->lock();
PVRTexHeader *header = (PVRTexHeader *)m_pData->getStart();
uint32_t formatFlags = header->flags & PVR_TEXTURE_FLAG_TYPE_MASK;
if (formatFlags == kPVRTextureFlagTypePVRTC_4) {
@@ -134,7 +135,7 @@ KRTexturePVR::KRTexturePVR(KRContext &context, KRDataBlock *data, std::string na
m_max_lod_max_dim = m_iWidth > m_iHeight ? m_iWidth : m_iHeight;
m_min_lod_max_dim = width > height ? width : height;
m_pData->unlock();
#endif
}
@@ -176,8 +177,6 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int &current_lo
int target_dim = lod_max_dim;
if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
GLenum err;
if(m_blocks.size() == 0) {
return false;
}

View File

@@ -28,10 +28,12 @@ typedef struct {
KRTextureTGA::KRTextureTGA(KRContext &context, KRDataBlock *data, std::string name) : KRTexture2D(context, data, name)
{
data->lock();
TGA_HEADER *pHeader = (TGA_HEADER *)data->getStart();
m_max_lod_max_dim = pHeader->width > pHeader->height ? pHeader->width : pHeader->height;
m_min_lod_max_dim = m_max_lod_max_dim; // Mipmaps not yet supported for TGA images
data->unlock();
}
KRTextureTGA::~KRTextureTGA()
@@ -73,7 +75,7 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int &current_lo
}
//#endif
glTexImage2D(target, 0, GL_RGBA, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image);
delete converted_image;
free(converted_image);
err = glGetError();
if (err != GL_NO_ERROR) {
return false;