diff options
author | Jason Sams <rjsams@android.com> | 2009-07-08 18:01:53 -0700 |
---|---|---|
committer | Jason Sams <rjsams@android.com> | 2009-07-10 17:32:59 -0700 |
commit | a5597fcd411badad50c1345b3eca26453da45bbb (patch) | |
tree | fcd27a1f068ed55094bd9a314707325ed6978d6c /rsFileA3D.cpp | |
parent | 185d826565e46dee75498d73a1541add9e3bb9d3 (diff) | |
download | rs-a5597fcd411badad50c1345b3eca26453da45bbb.tar.gz |
1st cut of a3d file loader.
Diffstat (limited to 'rsFileA3D.cpp')
-rw-r--r-- | rsFileA3D.cpp | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/rsFileA3D.cpp b/rsFileA3D.cpp new file mode 100644 index 00000000..f669417d --- /dev/null +++ b/rsFileA3D.cpp @@ -0,0 +1,356 @@ + +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "rsContext.h" + + +#include <utils/String8.h> +#include "rsFileA3D.h" + +#include "rsMesh.h" + +using namespace android; +using namespace android::renderscript; + + + +FileA3D::FileA3D() +{ + mRsc = NULL; +} + +FileA3D::~FileA3D() +{ +} + +bool FileA3D::load(Context *rsc, FILE *f) +{ + char magicString[12]; + size_t len; + + LOGE("file open 1"); + len = fread(magicString, 1, 12, f); + if ((len != 12) || + memcmp(magicString, "Android3D_ff", 12)) { + return false; + } + + LOGE("file open 2"); + len = fread(&mMajorVersion, 1, sizeof(mMajorVersion), f); + if (len != sizeof(mMajorVersion)) { + return false; + } + + LOGE("file open 3"); + len = fread(&mMinorVersion, 1, sizeof(mMinorVersion), f); + if (len != sizeof(mMinorVersion)) { + return false; + } + + LOGE("file open 4"); + uint32_t flags; + len = fread(&flags, 1, sizeof(flags), f); + if (len != sizeof(flags)) { + return false; + } + mUse64BitOffsets = (flags & 1) != 0; + + LOGE("file open 64bit = %i", mUse64BitOffsets); + + if (mUse64BitOffsets) { + len = fread(&mDataSize, 1, sizeof(mDataSize), f); + if (len != sizeof(mDataSize)) { + return false; + } + } else { + uint32_t tmp; + len = fread(&tmp, 1, sizeof(tmp), f); + if (len != sizeof(tmp)) { + return false; + } + mDataSize = tmp; + } + + LOGE("file open size = %lli", mDataSize); + + // We should know enough to read the file in at this point. + fseek(f, SEEK_SET, 0); + mAlloc= malloc(mDataSize); + if (!mAlloc) { + return false; + } + mData = (uint8_t *)mAlloc; + len = fread(mAlloc, 1, mDataSize, f); + if (len != mDataSize) { + return false; + } + + LOGE("file start processing"); + return process(rsc); +} + +bool FileA3D::processIndex(Context *rsc, A3DIndexEntry *ie) +{ + bool ret = false; + IO io(mData + ie->mOffset, mUse64BitOffsets); + + LOGE("process index, type %i", ie->mType); + + switch(ie->mType) { + case CHUNK_ELEMENT: + processChunk_Element(rsc, &io, ie); + break; + case CHUNK_ELEMENT_SOURCE: + processChunk_ElementSource(rsc, &io, ie); + break; + case CHUNK_VERTICIES: + processChunk_Verticies(rsc, &io, ie); + break; + case CHUNK_MESH: + processChunk_Mesh(rsc, &io, ie); + break; + case CHUNK_PRIMITIVE: + processChunk_Primitive(rsc, &io, ie); + break; + default: + LOGE("FileA3D Unknown chunk type"); + break; + } + return (ie->mRsObj != NULL); +} + +bool FileA3D::process(Context *rsc) +{ + LOGE("process"); + IO io(mData + 12, mUse64BitOffsets); + bool ret = true; + + // Build the index first + LOGE("process 1"); + io.loadU32(); // major version, already loaded + io.loadU32(); // minor version, already loaded + LOGE("process 2"); + + io.loadU32(); // flags + io.loadOffset(); // filesize, already loaded. + LOGE("process 4"); + uint64_t mIndexOffset = io.loadOffset(); + uint64_t mStringOffset = io.loadOffset(); + + LOGE("process mIndexOffset= 0x%016llx", mIndexOffset); + LOGE("process mStringOffset= 0x%016llx", mStringOffset); + + IO index(mData + mIndexOffset, mUse64BitOffsets); + IO stringTable(mData + mStringOffset, mUse64BitOffsets); + + uint32_t stringEntryCount = stringTable.loadU32(); + LOGE("stringEntryCount %i", stringEntryCount); + mStrings.setCapacity(stringEntryCount); + mStringIndexValues.setCapacity(stringEntryCount); + if (stringEntryCount) { + uint32_t stringType = stringTable.loadU32(); + LOGE("stringType %i", stringType); + rsAssert(stringType==0); + for (uint32_t ct = 0; ct < stringEntryCount; ct++) { + uint64_t offset = stringTable.loadOffset(); + LOGE("string offset 0x%016llx", offset); + IO tmp(mData + offset, mUse64BitOffsets); + String8 s; + tmp.loadString(&s); + LOGE("string %s", s.string()); + mStrings.push(s); + } + } + + LOGE("strings done"); + uint32_t indexEntryCount = index.loadU32(); + LOGE("index count %i", indexEntryCount); + mIndex.setCapacity(indexEntryCount); + for (uint32_t ct = 0; ct < indexEntryCount; ct++) { + A3DIndexEntry e; + uint32_t stringIndex = index.loadU32(); + LOGE("index %i", ct); + LOGE(" string index %i", stringIndex); + e.mType = (A3DChunkType)index.loadU32(); + LOGE(" type %i", e.mType); + e.mOffset = index.loadOffset(); + LOGE(" offset 0x%016llx", e.mOffset); + + if (stringIndex && (stringIndex < mStrings.size())) { + e.mID = mStrings[stringIndex]; + mStringIndexValues.editItemAt(stringIndex) = ct; + LOGE(" id %s", e.mID.string()); + } + + mIndex.push(e); + } + LOGE("index done"); + + // At this point the index should be fully populated. + // We can now walk though it and load all the objects. + for (uint32_t ct = 0; ct < indexEntryCount; ct++) { + LOGE("processing index entry %i", ct); + processIndex(rsc, &mIndex.editItemAt(ct)); + } + + return ret; +} + + +FileA3D::IO::IO(const uint8_t *buf, bool use64) +{ + mData = buf; + mPos = 0; + mUse64 = use64; +} + +uint64_t FileA3D::IO::loadOffset() +{ + uint64_t tmp; + if (mUse64) { + mPos = (mPos + 7) & (~7); + tmp = reinterpret_cast<const uint64_t *>(&mData[mPos])[0]; + mPos += sizeof(uint64_t); + return tmp; + } + return loadU32(); +} + +void FileA3D::IO::loadString(String8 *s) +{ + LOGE("loadString"); + uint32_t len = loadU32(); + LOGE("loadString len %i", len); + s->setTo((const char *)&mData[mPos], len); + mPos += len; +} + + +void FileA3D::processChunk_Mesh(Context *rsc, IO *io, A3DIndexEntry *ie) +{ + Mesh * m = new Mesh; + + m->mPrimitivesCount = io->loadU32(); + m->mPrimitives = new Mesh::Primitive_t *[m->mPrimitivesCount]; + + for (uint32_t ct = 0; ct < m->mPrimitivesCount; ct++) { + uint32_t index = io->loadU32(); + + m->mPrimitives[ct] = (Mesh::Primitive_t *)mIndex[index].mRsObj; + } + ie->mRsObj = m; +} + +void FileA3D::processChunk_Primitive(Context *rsc, IO *io, A3DIndexEntry *ie) +{ + Mesh::Primitive_t * p = new Mesh::Primitive_t; + + p->mIndexCount = io->loadU32(); + uint32_t vertIdx = io->loadU32(); + uint32_t bits = io->loadU8(); + p->mType = (RsPrimitive)io->loadU8(); + + p->mVerticies = (Mesh::Verticies_t *)mIndex[vertIdx].mRsObj; + + p->mIndicies = new uint16_t[p->mIndexCount]; + for (uint32_t ct = 0; ct < p->mIndexCount; ct++) { + switch(bits) { + case 8: + p->mIndicies[ct] = io->loadU8(); + break; + case 16: + p->mIndicies[ct] = io->loadU16(); + break; + case 32: + p->mIndicies[ct] = io->loadU32(); + break; + } + } + + ie->mRsObj = p; +} + +void FileA3D::processChunk_Verticies(Context *rsc, IO *io, A3DIndexEntry *ie) +{ + Mesh::Verticies_t *cv = new Mesh::Verticies_t; + cv->mAllocationCount = io->loadU32(); + cv->mAllocations = new Allocation *[cv->mAllocationCount]; + for (uint32_t ct = 0; ct < cv->mAllocationCount; ct++) { + uint32_t i = io->loadU32(); + cv->mAllocations[ct] = (Allocation *)mIndex[i].mRsObj; + } + ie->mRsObj = cv; +} + +void FileA3D::processChunk_Element(Context *rsc, IO *io, A3DIndexEntry *ie) +{ + LOGE("processChunk_Element ie %p", ie); + rsi_ElementBegin(rsc); + + uint32_t count = io->loadU32(); + LOGE("processChunk_Element count %i", count); + while (count--) { + RsDataKind dk = (RsDataKind)io->loadU8(); + RsDataType dt = (RsDataType)io->loadU8(); + uint32_t bits = io->loadU8(); + bool isNorm = io->loadU8() != 0; + LOGE(" %i %i %i %i", dk, dt, bits, isNorm); + rsi_ElementAdd(rsc, dk, dt, isNorm, bits); + } + LOGE("processChunk_Element create"); + ie->mRsObj = rsi_ElementCreate(rsc); +} + +void FileA3D::processChunk_ElementSource(Context *rsc, IO *io, A3DIndexEntry *ie) +{ + uint32_t index = io->loadU32(); + uint32_t count = io->loadU32(); + + RsElement e = (RsElement)mIndex[index].mRsObj; + + RsAllocation a = rsi_AllocationCreateSized(rsc, e, count); + Allocation * alloc = static_cast<Allocation *>(a); + + float * data = (float *)alloc->getPtr(); + while(count--) { + *data = io->loadF(); + data++; + } + ie->mRsObj = alloc; +} + +namespace android { +namespace renderscript { + + +RsFile rsi_FileOpen(Context *rsc, char const *path, unsigned int len) +{ + FileA3D *fa3d = new FileA3D; + + FILE *f = fopen("/sdcard/test.a3d", "rb"); + if (f) { + fa3d->load(rsc, f); + fclose(f); + return fa3d; + } + delete fa3d; + return NULL; +} + + +} +} |