LoaderDFF::GeometryList LoaderDFF::readGeometryList(const RWBStream &stream) { auto listStream = stream.getInnerStream(); auto listStructID = listStream.getNextChunk(); if (listStructID != CHUNK_STRUCT) { throw DFFLoaderException("Geometry List missing struct chunk"); } char *headerPtr = listStream.getCursor(); unsigned int numGeometries = *(std::uint32_t *)headerPtr; headerPtr += sizeof(std::uint32_t); std::vector<GeometryPtr> geometrylist; geometrylist.reserve(numGeometries); for (auto chunkID = listStream.getNextChunk(); chunkID != 0; chunkID = listStream.getNextChunk()) { switch (chunkID) { case CHUNK_GEOMETRY: { geometrylist.push_back(readGeometry(listStream)); } break; default: break; } } return geometrylist; }
void LoaderDFF::readTexture(Geometry::Material &material, const RWBStream &stream) { auto texStream = stream.getInnerStream(); auto texStructID = texStream.getNextChunk(); if (texStructID != CHUNK_STRUCT) { throw DFFLoaderException("Texture missing struct chunk"); } // There's some data in the Texture's struct, but we don't know what it is. /// @todo improve how these strings are read. std::string name, alpha; texStream.getNextChunk(); name = texStream.getCursor(); texStream.getNextChunk(); alpha = texStream.getCursor(); std::transform(name.begin(), name.end(), name.begin(), ::tolower); std::transform(alpha.begin(), alpha.end(), alpha.begin(), ::tolower); TextureData::Handle textureinst = texturelookup ? texturelookup(name, alpha) : nullptr; material.textures.push_back({name, alpha, textureinst}); }
AtomicPtr LoaderDFF::readAtomic(FrameList &framelist, GeometryList &geometrylist, const RWBStream &stream) { auto atomicStream = stream.getInnerStream(); auto atomicStructID = atomicStream.getNextChunk(); if (atomicStructID != CHUNK_STRUCT) { throw DFFLoaderException("Atomic missing struct chunk"); } auto data = atomicStream.getCursor(); auto frame = *(std::uint32_t *)data; data += sizeof(std::uint32_t); auto geometry = *(std::uint32_t *)data; data += sizeof(std::uint32_t); auto flags = *(std::uint32_t *) data; // Verify the atomic's particulars RW_CHECK(frame < framelist.size(), "atomic frame " << frame << " out of bounds"); RW_CHECK(geometry < geometrylist.size(), "atomic geometry " << geometry << " out of bounds"); auto atomic = std::make_shared<Atomic>(); if (geometry < geometrylist.size()) { atomic->setGeometry(geometrylist[geometry]); } if (frame < framelist.size()) { atomic->setFrame(framelist[frame]); } atomic->setFlags(flags); return atomic; }
void SampleReader::init(const unsigned chunkSize) { this->chunkSize = chunkSize; timeFile.open("Time_1.dat", std::ios::in | std::ios::binary); channel0Buffer = new float[chunkSize]; channel1Buffer = new float[chunkSize]; getNextChunk(); /* We don't have a start time of the first chunk. Hence we have to skip them to get a proper time. As an implication, we should assure to start the experiment at least one chunk after the measurement! */ getNextChunk(); examinedSoFar = bufferBegin; }
void PCMMusicPlayer::play() { if (_curChunk) return; if (_scriptNum == -1) return; _end = false; getNextChunk(); }
void LoaderDFF::readMaterial(GeometryPtr &geom, const RWBStream &stream) { auto materialStream = stream.getInnerStream(); auto matStructID = materialStream.getNextChunk(); if (matStructID != CHUNK_STRUCT) { throw DFFLoaderException("Material missing struct chunk"); } char *matData = materialStream.getCursor(); Geometry::Material material; // Unkown matData += sizeof(std::uint32_t); material.colour = *(glm::u8vec4 *)matData; matData += sizeof(std::uint32_t); // Unkown matData += sizeof(std::uint32_t); /*bool usesTexture = *(std::uint32_t*)matData;*/ matData += sizeof(std::uint32_t); material.ambientIntensity = *(float *)matData; matData += sizeof(float); /*float specular = *(float*)matData;*/ matData += sizeof(float); material.diffuseIntensity = *(float *)matData; matData += sizeof(float); material.flags = 0; RWBStream::ChunkID chunkID; while ((chunkID = materialStream.getNextChunk())) { switch (chunkID) { case CHUNK_TEXTURE: readTexture(material, materialStream); break; default: break; } } geom->materials.push_back(material); }
//--------------------------------------------------------------------------- void CFunction::Format(CExportContext& ctx, const SFString& fmtIn, void *data) const { if (!isShowing()) return; SFString fmt = (fmtIn.IsEmpty() ? defaultFormat() : fmtIn); //.Substitute("\n","\t"); if (handleCustomFormat(ctx, fmt, data)) return; CFunctionNotify dn(this); while (!fmt.IsEmpty()) ctx << getNextChunk(fmt, nextFunctionChunk, &dn); }
void LoaderDFF::readMaterialList(GeometryPtr &geom, const RWBStream &stream) { auto listStream = stream.getInnerStream(); auto listStructID = listStream.getNextChunk(); if (listStructID != CHUNK_STRUCT) { throw DFFLoaderException("MaterialList missing struct chunk"); } unsigned int numMaterials = *(std::uint32_t *)listStream.getCursor(); geom->materials.reserve(numMaterials); RWBStream::ChunkID chunkID; while ((chunkID = listStream.getNextChunk())) { switch (chunkID) { case CHUNK_MATERIAL: readMaterial(geom, listStream); break; default: break; } } }
void LoaderDFF::readGeometryExtension(GeometryPtr &geom, const RWBStream &stream) { auto extStream = stream.getInnerStream(); RWBStream::ChunkID chunkID; while ((chunkID = extStream.getNextChunk())) { switch (chunkID) { case CHUNK_BINMESHPLG: readBinMeshPLG(geom, extStream); break; default: break; } } }
double SampleReader::getEnergy(timespec intervalEnd) { // TODO: use interval arithmetic to account for offset of clocks? double energy = 0.0; timespec begin, end; unsigned firstSample, lastSample; double lackingFirstSampleFraction, lackingLastSampleFraction; if ( !(intervalEnd >= examinedSoFar) ) { std::cerr << "Warning: Timestamp detected which is prior to previous one, exiting! Assure to wait for at least 1s before starting your code after the measurement begins!" << std::endl; std::cerr << " intervalEnd = " << intervalEnd.tv_sec << "." << std::setfill('0') << std::setw(9) << intervalEnd.tv_nsec << std::endl; std::cerr << " examinedSoFar = " << examinedSoFar.tv_sec << "." << std::setfill('0') << std::setw(9) << examinedSoFar.tv_nsec << std::endl; std::cerr << std::endl; exit(EXIT_FAILURE); } while (intervalEnd > examinedSoFar) { if (examinedSoFar >= bufferEnd) { getNextChunk(); examinedSoFar = bufferBegin; } begin = examinedSoFar; end = ( intervalEnd > bufferEnd ? bufferEnd : intervalEnd ); firstSample = enclosingSample(begin); lastSample = enclosingSample(end); // account for missing part of (partial) first sample lackingFirstSampleFraction = ( (begin - startTimeOfEnclosingSample(begin)) / sampleWidth ); energy += getEnergyOfSample(firstSample, -lackingFirstSampleFraction); // account for boundary and (full) inner samples for (unsigned currentSample = firstSample; currentSample <= lastSample; currentSample++) { energy += getEnergyOfSample(currentSample, 1); } // account for missing part of (partial) last sample lackingLastSampleFraction = ( (endTimeOfEnclosingSample(end) - end) / sampleWidth ); energy += getEnergyOfSample(lastSample, -lackingLastSampleFraction); examinedSoFar = end; } return energy; }
int PCMMusicPlayer::readBuffer(int16 *buffer, const int numSamples) { Common::StackLock slock(_mutex); if (!_curChunk && ((_state == S_IDLE) || (_state == S_STOP))) return 0; int samplesLeft = numSamples; while (samplesLeft > 0) { if (_silenceSamples > 0) { int n = MIN(_silenceSamples, samplesLeft); memset(buffer, 0, n); buffer += n; _silenceSamples -= n; samplesLeft -= n; } else if (_curChunk && ((_state == S_MID) || (_state == S_NEXT) || (_state == S_NEW))) { int n = _curChunk->readBuffer(buffer, samplesLeft); buffer += n; samplesLeft -= n; if (_curChunk->endOfData()) { _state = S_END1; delete _curChunk; _curChunk = 0; } } else { if (!getNextChunk()) break; } } return (numSamples - samplesLeft); }
// // Loop for ever, and wait for new jobs. // The general principle used is repeating (starting with locked mutex): // wait(condition) // pop a job from the job queue // unlock(mutex) // Do the job. // lock(mutex) // put result in outgoing queue. // // This means that the actual job is done with no locked semaphores. Because of that, it is important that no data is // manipulated that can also be accessed from the main process. void ChunkProcess::Task(void) { std::unique_lock<std::mutex> lock(fMutex); // This will lock the mutex // The condition variable will not have any effect if not waiting for it. And that may happen // as the mutex is unlocked in the loop now and then. bool waitForCondition = true; // Stay in a loop forever, waiting for new messages to play while(1) { if (waitForCondition) fCondLock.wait(lock); waitForCondition = true; // Wait for condition next iteration if (fTerminate) { // Used to request that the child thread terminates. fMutex.unlock(); break; } if (!fComputeObjectsInput.empty()) { // Take out the chunk from the fifo chunk *ch = getNextChunk(fComputeObjectsInput); if (ch == 0) continue; if (ch->fScheduledForLoading) { ch->fScheduledForComputation = false; continue; // Ignore a recomputation, as the chunk will be loaded by new data anyway, later followed by a new computation } fMutex.unlock(); // Unlock the mutex while doing some heavy work // printf("ChunkProcess phase 1, size %d, chunk %d,%d,%d\n", fComputeObjectsInput.size()+1, ch->cc.x, ch->cc.y, ch->cc.z); auto co = ChunkObject::Make(ch, false, 0, 0, 0); co->FindSpecialObjects(ch); // This will find light sources, and should be done before FindTriangles(). fMutex.lock(); ASSERT(ch->fScheduledForComputation); co->fChunk = ch; fComputedObjectsOutput.insert(std::move(co)); // Add it to the list of recomputed chunks waitForCondition = false; // Try another iteration } if (!fNewChunksInput.empty()) { auto nc = getNextChunkBlock(fNewChunksInput); chunk *pc = nc->fChunk; // It may be that this chunk was also scheduled for recomputation. If so, the Uncompress() below that calls SetDirty() will not // schedule a new recomputation again. ASSERT(pc->fScheduledForLoading); fMutex.unlock(); // Unlock the mutex while doing some work // printf("ChunkProcess phase 2, size %d\n", fNewChunksInput.size()+1); nc->Uncompress(); // Save chunk in cache ChunkCache::cachunk chunkdata; chunkdata.cc = pc->cc; chunkdata.flag = nc->flag; chunkdata.fCheckSum = nc->fChecksum; chunkdata.fOwner = nc->fOwner; chunkdata.compressSize = nc->compressSize; chunkdata.compressedChunk = nc->fCompressedChunk.get(); ChunkCache::fgChunkCache.SaveChunkInCache(&chunkdata); // TODO: Use a ChunkProcess::ChunkBlocks as argument instead fMutex.lock(); ASSERT(nc->fChunk == pc); fNewChunksOutput.insert(nc); // Add it to the list of loaded chunks waitForCondition = false; // Try another iteration } } }
LoaderDFF::FrameList LoaderDFF::readFrameList(const RWBStream &stream) { auto listStream = stream.getInnerStream(); auto listStructID = listStream.getNextChunk(); if (listStructID != CHUNK_STRUCT) { throw DFFLoaderException("Frame List missing struct chunk"); } char *headerPtr = listStream.getCursor(); unsigned int numFrames = *(std::uint32_t *)headerPtr; headerPtr += sizeof(std::uint32_t); FrameList framelist; framelist.reserve(numFrames); for (size_t f = 0; f < numFrames; ++f) { auto data = (RWBSFrame *)headerPtr; headerPtr += sizeof(RWBSFrame); auto frame = std::make_shared<ModelFrame>(f, data->rotation, data->position); RW_CHECK(data->index < int(framelist.size()), "Frame parent out of bounds"); if (data->index != -1 && data->index < int(framelist.size())) { framelist[data->index]->addChild(frame); } framelist.push_back(frame); } size_t namedFrames = 0; /// @todo perhaps flatten this out a little for (auto chunkID = listStream.getNextChunk(); chunkID != 0; chunkID = listStream.getNextChunk()) { switch (chunkID) { case CHUNK_EXTENSION: { auto extStream = listStream.getInnerStream(); for (auto chunkID = extStream.getNextChunk(); chunkID != 0; chunkID = extStream.getNextChunk()) { switch (chunkID) { case CHUNK_NODENAME: { std::string fname(extStream.getCursor(), extStream.getCurrentChunkSize()); std::transform(fname.begin(), fname.end(), fname.begin(), ::tolower); if (namedFrames < framelist.size()) { framelist[namedFrames++]->setName(fname); } } break; default: break; } } } break; default: break; } } return framelist; }
GeometryPtr LoaderDFF::readGeometry(const RWBStream &stream) { auto geomStream = stream.getInnerStream(); auto geomStructID = geomStream.getNextChunk(); if (geomStructID != CHUNK_STRUCT) { throw DFFLoaderException("Geometry missing struct chunk"); } auto geom = std::make_shared<Geometry>(); char *headerPtr = geomStream.getCursor(); geom->flags = *(std::uint16_t *)headerPtr; headerPtr += sizeof(std::uint16_t); /*unsigned short numUVs = *(std::uint8_t*)headerPtr;*/ headerPtr += sizeof(std::uint8_t); /*unsigned short moreFlags = *(std::uint8_t*)headerPtr;*/ headerPtr += sizeof(std::uint8_t); unsigned int numTris = *(std::uint32_t *)headerPtr; headerPtr += sizeof(std::uint32_t); unsigned int numVerts = *(std::uint32_t *)headerPtr; headerPtr += sizeof(std::uint32_t); /*unsigned int numFrames = *(std::uint32_t*)headerPtr;*/ headerPtr += sizeof(std::uint32_t); std::vector<GeometryVertex> verts; verts.resize(numVerts); if (geomStream.getChunkVersion() < 0x1003FFFF) { headerPtr += sizeof(RW::BSGeometryColor); } /// @todo extract magic numbers. if ((geom->flags & 8) == 8) { for (size_t v = 0; v < numVerts; ++v) { verts[v].colour = *(glm::u8vec4 *)headerPtr; headerPtr += sizeof(glm::u8vec4); } } else { for (size_t v = 0; v < numVerts; ++v) { verts[v].colour = {255, 255, 255, 255}; } } if ((geom->flags & 4) == 4 || (geom->flags & 128) == 128) { for (size_t v = 0; v < numVerts; ++v) { verts[v].texcoord = *(glm::vec2 *)headerPtr; headerPtr += sizeof(glm::vec2); } } // Grab indicies data to generate normals (if applicable). RW::BSGeometryTriangle *triangles = (RW::BSGeometryTriangle *)headerPtr; headerPtr += sizeof(RW::BSGeometryTriangle) * numTris; geom->geometryBounds = *(RW::BSGeometryBounds *)headerPtr; geom->geometryBounds.radius = std::abs(geom->geometryBounds.radius); headerPtr += sizeof(RW::BSGeometryBounds); for (size_t v = 0; v < numVerts; ++v) { verts[v].position = *(glm::vec3 *)headerPtr; headerPtr += sizeof(glm::vec3); } if ((geom->flags & 16) == 16) { for (size_t v = 0; v < numVerts; ++v) { verts[v].normal = *(glm::vec3 *)headerPtr; headerPtr += sizeof(glm::vec3); } } else { // Use triangle data to calculate normals for each vert. for (size_t t = 0; t < numTris; ++t) { auto &triangle = triangles[t]; auto &A = verts[triangle.first]; auto &B = verts[triangle.second]; auto &C = verts[triangle.third]; auto normal = glm::normalize( glm::cross(C.position - A.position, B.position - A.position)); A.normal = normal; B.normal = normal; C.normal = normal; } } // Process the geometry child sections for (auto chunkID = geomStream.getNextChunk(); chunkID != 0; chunkID = geomStream.getNextChunk()) { switch (chunkID) { case CHUNK_MATERIALLIST: readMaterialList(geom, geomStream); break; case CHUNK_EXTENSION: readGeometryExtension(geom, geomStream); break; default: break; } } geom->dbuff.setFaceType(geom->facetype == Geometry::Triangles ? GL_TRIANGLES : GL_TRIANGLE_STRIP); geom->gbuff.uploadVertices(verts); geom->dbuff.addGeometry(&geom->gbuff); glGenBuffers(1, &geom->EBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geom->EBO); size_t icount = std::accumulate( geom->subgeom.begin(), geom->subgeom.end(), 0u, [](size_t a, const SubGeometry &b) { return a + b.numIndices; }); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32_t) * icount, 0, GL_STATIC_DRAW); for (auto &sg : geom->subgeom) { glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, sg.start * sizeof(uint32_t), sizeof(uint32_t) * sg.numIndices, sg.indices.data()); } return geom; }