3D PDF: Refactoring

This commit is contained in:
Jakub Melka
2022-10-08 17:15:10 +02:00
parent c30c06fa6f
commit 04565aaf93
3 changed files with 374 additions and 114 deletions

View File

@ -27,8 +27,9 @@ namespace pdf
namespace u3d namespace u3d
{ {
PDF3D_U3D_DataReader::PDF3D_U3D_DataReader(QByteArray data, bool isCompressed) : PDF3D_U3D_DataReader::PDF3D_U3D_DataReader(QByteArray data, bool isCompressed, PDF3D_U3D_ContextManager* contextManager) :
m_data(std::move(data)), m_data(std::move(data)),
m_contextManager(contextManager),
m_high(0x0000FFFF), m_high(0x0000FFFF),
m_low(0), m_low(0),
m_underflow(0), m_underflow(0),
@ -106,7 +107,7 @@ double PDF3D_U3D_DataReader::readF64()
uint8_t PDF3D_U3D_DataReader::readCompressedU8(uint32_t context) uint8_t PDF3D_U3D_DataReader::readCompressedU8(uint32_t context)
{ {
if (m_isCompressed && m_contextManager.isContextCompressed(context)) if (m_isCompressed && m_contextManager->isContextCompressed(context))
{ {
const uint32_t symbol = readSymbol(context); const uint32_t symbol = readSymbol(context);
if (symbol != 0) if (symbol != 0)
@ -118,7 +119,7 @@ uint8_t PDF3D_U3D_DataReader::readCompressedU8(uint32_t context)
{ {
// New symbol // New symbol
const uint32_t value = readU8(); const uint32_t value = readU8();
m_contextManager.addSymbol(context, value + 1); m_contextManager->addSymbol(context, value + 1);
return value; return value;
} }
} }
@ -128,7 +129,7 @@ uint8_t PDF3D_U3D_DataReader::readCompressedU8(uint32_t context)
uint16_t PDF3D_U3D_DataReader::readCompressedU16(uint32_t context) uint16_t PDF3D_U3D_DataReader::readCompressedU16(uint32_t context)
{ {
if (m_isCompressed && m_contextManager.isContextCompressed(context)) if (m_isCompressed && m_contextManager->isContextCompressed(context))
{ {
const uint32_t symbol = readSymbol(context); const uint32_t symbol = readSymbol(context);
if (symbol != 0) if (symbol != 0)
@ -140,7 +141,7 @@ uint16_t PDF3D_U3D_DataReader::readCompressedU16(uint32_t context)
{ {
// New symbol // New symbol
const uint32_t value = readU16(); const uint32_t value = readU16();
m_contextManager.addSymbol(context, value + 1); m_contextManager->addSymbol(context, value + 1);
return value; return value;
} }
} }
@ -150,7 +151,7 @@ uint16_t PDF3D_U3D_DataReader::readCompressedU16(uint32_t context)
uint32_t PDF3D_U3D_DataReader::readCompressedU32(uint32_t context) uint32_t PDF3D_U3D_DataReader::readCompressedU32(uint32_t context)
{ {
if (m_isCompressed && m_contextManager.isContextCompressed(context)) if (m_isCompressed && m_contextManager->isContextCompressed(context))
{ {
const uint32_t symbol = readSymbol(context); const uint32_t symbol = readSymbol(context);
if (symbol != 0) if (symbol != 0)
@ -162,7 +163,7 @@ uint32_t PDF3D_U3D_DataReader::readCompressedU32(uint32_t context)
{ {
// New symbol // New symbol
const uint32_t value = readU32(); const uint32_t value = readU32();
m_contextManager.addSymbol(context, value + 1); m_contextManager->addSymbol(context, value + 1);
return value; return value;
} }
} }
@ -312,19 +313,19 @@ uint32_t PDF3D_U3D_DataReader::readSymbol(uint32_t context)
m_code = (m_code << 15) | read15Bits(); m_code = (m_code << 15) | read15Bits();
m_position = position; m_position = position;
const uint32_t totalCumFreq = m_contextManager.getTotalSymbolFrequency(context); const uint32_t totalCumFreq = m_contextManager->getTotalSymbolFrequency(context);
const uint32_t range = (m_high + 1) - m_low; const uint32_t range = (m_high + 1) - m_low;
const uint32_t codeCumFreq = ((totalCumFreq) * (1 + m_code - m_low) - 1) / range; const uint32_t codeCumFreq = ((totalCumFreq) * (1 + m_code - m_low) - 1) / range;
const uint32_t value = m_contextManager.getSymbolFromFrequency(context, codeCumFreq); const uint32_t value = m_contextManager->getSymbolFromFrequency(context, codeCumFreq);
const uint32_t valueCumFreq = m_contextManager.getCumulativeSymbolFrequency(context, value); const uint32_t valueCumFreq = m_contextManager->getCumulativeSymbolFrequency(context, value);
const uint32_t valueFreq = m_contextManager.getSymbolFrequency(context, value); const uint32_t valueFreq = m_contextManager->getSymbolFrequency(context, value);
uint32_t low = m_low; uint32_t low = m_low;
uint32_t high = m_high; uint32_t high = m_high;
high = low - 1 + range * (valueCumFreq + valueFreq) / totalCumFreq; high = low - 1 + range * (valueCumFreq + valueFreq) / totalCumFreq;
low = low + range * valueCumFreq / totalCumFreq; low = low + range * valueCumFreq / totalCumFreq;
m_contextManager.addSymbol(context, value); m_contextManager->addSymbol(context, value);
constexpr std::array S_BIT_COUNTS = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; constexpr std::array S_BIT_COUNTS = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
uint32_t bitCount = S_BIT_COUNTS[((low >> 12) ^ (high >> 12)) & 0x0000000F]; uint32_t bitCount = S_BIT_COUNTS[((low >> 12) ^ (high >> 12)) & 0x0000000F];
@ -619,22 +620,136 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D::parseBlockWithDeclaration(PDF3D_U3D_DataRe
return block; return block;
} }
PDF3D_U3D_Block_Data PDF3D_U3D::readBlockData(PDF3D_U3D_DataReader& reader)
{
PDF3D_U3D_Block_Data data;
// Read block
uint32_t blockType = reader.readU32();
uint32_t dataSize = reader.readU32();
uint32_t metaDataSize = reader.readU32();
//qDebug() << QString("BT: %1, data size = %2").arg(QString::number(blockType, 16), QString::number(dataSize));
// Read block data
QByteArray blockData = reader.readByteArray(dataSize);
reader.skipBytes(getBlockPadding(dataSize));
// Read block metadata
QByteArray metaData = reader.readByteArray(metaDataSize);
reader.skipBytes(getBlockPadding(metaDataSize));
data.blockType = blockType;
data.blockData = std::move(blockData);
data.metaData = std::move(metaData);
return data;
}
PDF3D_U3D PDF3D_U3D::parse(QByteArray data) PDF3D_U3D PDF3D_U3D::parse(QByteArray data)
{ {
PDF3D_U3D object; PDF3D_U3D object;
PDF3D_U3D_DataReader reader(data, true);
// Why to use shared ptr and weak ptr in the object?
// In case exception is thrown in the parser, context
// manager will be automatically released.
std::shared_ptr<PDF3D_U3D_ContextManager> contextManager = std::make_shared<PDF3D_U3D_ContextManager>();
object.setContextManager(contextManager);
PDF3D_U3D_DataReader reader(data, true, contextManager.get());
object.m_priority = 0;
QStringList errors;
PDF3D_U3D_DecoderLists decoderLists;
while (!reader.isAtEnd()) while (!reader.isAtEnd())
{ {
if (auto block = object.parseBlockWithDeclaration(reader)) PDF3D_U3D_Block_Data blockData = readBlockData(reader);
{ processBlock(blockData, decoderLists, errors);
object.m_blocks.emplace_back(std::move(block));
}
} }
return object; return object;
} }
void PDF3D_U3D::processBlock(PDF3D_U3D& object,
const PDF3D_U3D_Block_Data& blockData,
PDF3D_U3D_DecoderLists& decoderLists,
QStringList& errors,
PDF3D_U3D_DecoderLists::EPalette palette)
{
switch (blockData.blockType)
{
case PDF3D_U3D_FileBlock::ID:
{
// Parse file block
object.m_fileBlock = object.parseBlock(blockData);
break;
}
case PDF3D_U3D_PriorityUpdateBlock::ID:
{
// Parse priority update block
auto block = object.parseBlock(blockData);
const PDF3D_U3D_PriorityUpdateBlock* priorityUpdateBlock = dynamic_cast<const PDF3D_U3D_PriorityUpdateBlock*>(block.get());
object.m_priority = priorityUpdateBlock->getNewPriority();
break;
}
case PDF3D_U3D_NewObjectTypeBlock::ID:
case PDF3D_U3D_FileReferenceBlock::ID:
// Skip this block, we do not handle these type of blocks,
// just read it... to check errors.
object.parseBlock(blockData);
break;
case PDF3D_U3D_ModifierChainBlock::ID:
{
// Add decoder list for modifier chain block
auto block = object.parseBlock(blockData);
const PDF3D_U3D_ModifierChainBlock* chainBlock = dynamic_cast<const PDF3D_U3D_ModifierChainBlock*>(block.get());
PDF3D_U3D_DecoderList decoderList;
decoderList.setName(chainBlock->getModifierChainName());
for (const auto& block : chainBlock->getModifierDeclarationBlocks())
{
decoderList.createChain(block);
}
decoderLists.addDecoderList(std::move(decoderList));
break;
}
default:
{
PDF3D_U3D_DataReader blockReader(blockData.blockData, object.isCompressed(), object.getContextManager());
QString blockName = blockReader.readString(object.getTextCodec());
if (isContinuationBlock(blockData.blockType))
{
uint32_t chainIndex = 0;
if (blockData.blockType != 0xFFFFFF5C)
{
chainIndex = blockReader.readU32();
}
if (!decoderLists.addContinuationBlock(blockName, chainIndex, blockData))
{
errors << QString("Failed to add continuation block '%1'").arg(blockName);
}
}
else
{
PDF3D_U3D_DecoderList decoderList;
decoderList.createChain(blockData);
decoderLists.addDecoderList(std::move(decoderList));
}
break;
}
}
}
template<typename T> template<typename T>
const T* PDF3D_U3D::getBlock(const QString& name) const const T* PDF3D_U3D::getBlock(const QString& name) const
{ {
@ -678,7 +793,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D::parseBlock(uint32_t blockType,
if (const PDF3D_U3D_FileBlock* fileBlock = dynamic_cast<const PDF3D_U3D_FileBlock*>(fileBlockPtr.get())) if (const PDF3D_U3D_FileBlock* fileBlock = dynamic_cast<const PDF3D_U3D_FileBlock*>(fileBlockPtr.get()))
{ {
m_fileBlock = fileBlock; m_fileBlock = fileBlockPtr;
m_textCodec = QTextCodec::codecForMib(fileBlock->getCharacterEncoding()); m_textCodec = QTextCodec::codecForMib(fileBlock->getCharacterEncoding());
m_isCompressed = !fileBlock->isNoCompressionMode(); m_isCompressed = !fileBlock->isNoCompressionMode();
} }
@ -736,6 +851,11 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D::parseBlock(uint32_t blockType,
return PDF3D_U3D_AbstractBlockPtr(); return PDF3D_U3D_AbstractBlockPtr();
} }
PDF3D_U3D_AbstractBlockPtr PDF3D_U3D::parseBlock(const PDF3D_U3D_Block_Data& data)
{
return parseBlock(data.blockType, data.blockData, data.metaData);
}
uint32_t PDF3D_U3D::getBlockPadding(uint32_t blockSize) uint32_t PDF3D_U3D::getBlockPadding(uint32_t blockSize)
{ {
uint32_t extraBytes = blockSize % 4; uint32_t extraBytes = blockSize % 4;
@ -748,12 +868,30 @@ uint32_t PDF3D_U3D::getBlockPadding(uint32_t blockSize)
return 0; return 0;
} }
bool PDF3D_U3D::isContinuationBlock(uint32_t blockType)
{
switch (blockType)
{
case 0xFFFFFF3B:
case 0xFFFFFF3C:
case 0xFFFFFF3E:
case 0xFFFFFF3F:
case 0xFFFFFF5C:
return true;
default:
break;
}
return false;
}
PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_FileBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object) PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_FileBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object)
{ {
PDF3D_U3D_FileBlock* block = new PDF3D_U3D_FileBlock(); PDF3D_U3D_FileBlock* block = new PDF3D_U3D_FileBlock();
PDF3D_U3D_AbstractBlockPtr pointer(block); PDF3D_U3D_AbstractBlockPtr pointer(block);
PDF3D_U3D_DataReader reader(data, object->isCompressed()); PDF3D_U3D_DataReader reader(data, object->isCompressed(), object->getContextManager());
// Read the data // Read the data
block->m_majorVersion = reader.readI16(); block->m_majorVersion = reader.readI16();
@ -815,7 +953,7 @@ void PDF3D_U3D_AbstractBlock::parseMetadata(QByteArray metaData, PDF3D_U3D* obje
return; return;
} }
PDF3D_U3D_DataReader reader(metaData, object->isCompressed()); PDF3D_U3D_DataReader reader(metaData, object->isCompressed(), object->getContextManager());
const uint32_t itemCount = reader.readU32(); const uint32_t itemCount = reader.readU32();
for (uint32_t i = 0; i < itemCount; ++i) for (uint32_t i = 0; i < itemCount; ++i)
@ -866,7 +1004,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_FileReferenceBlock::parse(QByteArray data,
PDF3D_U3D_FileReferenceBlock* block = new PDF3D_U3D_FileReferenceBlock(); PDF3D_U3D_FileReferenceBlock* block = new PDF3D_U3D_FileReferenceBlock();
PDF3D_U3D_AbstractBlockPtr pointer(block); PDF3D_U3D_AbstractBlockPtr pointer(block);
PDF3D_U3D_DataReader reader(data, object->isCompressed()); PDF3D_U3D_DataReader reader(data, object->isCompressed(), object->getContextManager());
// Read the data // Read the data
block->m_scopeName = reader.readString(object->getTextCodec()); block->m_scopeName = reader.readString(object->getTextCodec());
@ -968,7 +1106,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_ModifierChainBlock::parse(QByteArray data,
PDF3D_U3D_ModifierChainBlock* block = new PDF3D_U3D_ModifierChainBlock(); PDF3D_U3D_ModifierChainBlock* block = new PDF3D_U3D_ModifierChainBlock();
PDF3D_U3D_AbstractBlockPtr pointer(block); PDF3D_U3D_AbstractBlockPtr pointer(block);
PDF3D_U3D_DataReader reader(data, object->isCompressed()); PDF3D_U3D_DataReader reader(data, object->isCompressed(), object->getContextManager());
// Read the data // Read the data
block->m_modifierChainName = reader.readString(object->getTextCodec()); block->m_modifierChainName = reader.readString(object->getTextCodec());
@ -987,10 +1125,8 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_ModifierChainBlock::parse(QByteArray data,
const uint32_t modifierCount = reader.readU32(); const uint32_t modifierCount = reader.readU32();
for (uint32_t i = 0; i < modifierCount; ++i) for (uint32_t i = 0; i < modifierCount; ++i)
{ {
if (auto parsedBlock = object->parseBlockWithDeclaration(reader)) PDF3D_U3D_Block_Data blockData = object->readBlockData(reader);
{ block->m_modifierDeclarationBlocks.emplace_back(std::move(blockData));
block->m_modifierDeclarationBlocks.emplace_back(std::move(parsedBlock));
}
} }
block->parseMetadata(metaData, object); block->parseMetadata(metaData, object);
@ -1027,7 +1163,7 @@ uint32_t PDF3D_U3D_ModifierChainBlock::getModifierCount() const
return m_modifierCount; return m_modifierCount;
} }
const std::vector<PDF3D_U3D_AbstractBlockPtr>& PDF3D_U3D_ModifierChainBlock::getModifierDeclarationBlocks() const const std::vector<PDF3D_U3D_Block_Data>& PDF3D_U3D_ModifierChainBlock::getModifierDeclarationBlocks() const
{ {
return m_modifierDeclarationBlocks; return m_modifierDeclarationBlocks;
} }
@ -1037,7 +1173,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_PriorityUpdateBlock::parse(QByteArray data,
PDF3D_U3D_PriorityUpdateBlock* block = new PDF3D_U3D_PriorityUpdateBlock(); PDF3D_U3D_PriorityUpdateBlock* block = new PDF3D_U3D_PriorityUpdateBlock();
PDF3D_U3D_AbstractBlockPtr pointer(block); PDF3D_U3D_AbstractBlockPtr pointer(block);
PDF3D_U3D_DataReader reader(data, object->isCompressed()); PDF3D_U3D_DataReader reader(data, object->isCompressed(), object->getContextManager());
// Read the data // Read the data
block->m_newPriority = reader.readU32(); block->m_newPriority = reader.readU32();
@ -1056,7 +1192,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_NewObjectTypeBlock::parse(QByteArray data,
PDF3D_U3D_NewObjectTypeBlock* block = new PDF3D_U3D_NewObjectTypeBlock(); PDF3D_U3D_NewObjectTypeBlock* block = new PDF3D_U3D_NewObjectTypeBlock();
PDF3D_U3D_AbstractBlockPtr pointer(block); PDF3D_U3D_AbstractBlockPtr pointer(block);
PDF3D_U3D_DataReader reader(data, object->isCompressed()); PDF3D_U3D_DataReader reader(data, object->isCompressed(), object->getContextManager());
// Read the data // Read the data
block->m_newObjectTypeName = reader.readString(object->getTextCodec()); block->m_newObjectTypeName = reader.readString(object->getTextCodec());
@ -1134,7 +1270,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_NewObjectBlock::parse(QByteArray data, QByt
PDF3D_U3D_NewObjectBlock* block = new PDF3D_U3D_NewObjectBlock(); PDF3D_U3D_NewObjectBlock* block = new PDF3D_U3D_NewObjectBlock();
PDF3D_U3D_AbstractBlockPtr pointer(block); PDF3D_U3D_AbstractBlockPtr pointer(block);
PDF3D_U3D_DataReader reader(data, object->isCompressed()); PDF3D_U3D_DataReader reader(data, object->isCompressed(), object->getContextManager());
// Read the data // Read the data
block->m_objectName = reader.readString(object->getTextCodec()); block->m_objectName = reader.readString(object->getTextCodec());
@ -1165,7 +1301,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_GroupNodeBlock::parse(QByteArray data, QByt
PDF3D_U3D_GroupNodeBlock* block = new PDF3D_U3D_GroupNodeBlock(); PDF3D_U3D_GroupNodeBlock* block = new PDF3D_U3D_GroupNodeBlock();
PDF3D_U3D_AbstractBlockPtr pointer(block); PDF3D_U3D_AbstractBlockPtr pointer(block);
PDF3D_U3D_DataReader reader(data, object->isCompressed()); PDF3D_U3D_DataReader reader(data, object->isCompressed(), object->getContextManager());
// Read the data // Read the data
block->m_groupNodeName = reader.readString(object->getTextCodec()); block->m_groupNodeName = reader.readString(object->getTextCodec());
@ -1190,7 +1326,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_ModelNodeBlock::parse(QByteArray data, QByt
PDF3D_U3D_ModelNodeBlock* block = new PDF3D_U3D_ModelNodeBlock(); PDF3D_U3D_ModelNodeBlock* block = new PDF3D_U3D_ModelNodeBlock();
PDF3D_U3D_AbstractBlockPtr pointer(block); PDF3D_U3D_AbstractBlockPtr pointer(block);
PDF3D_U3D_DataReader reader(data, object->isCompressed()); PDF3D_U3D_DataReader reader(data, object->isCompressed(), object->getContextManager());
// Read the data // Read the data
block->m_modelNodeName = reader.readString(object->getTextCodec()); block->m_modelNodeName = reader.readString(object->getTextCodec());
@ -1227,7 +1363,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_LightNodeBlock::parse(QByteArray data, QByt
PDF3D_U3D_LightNodeBlock* block = new PDF3D_U3D_LightNodeBlock(); PDF3D_U3D_LightNodeBlock* block = new PDF3D_U3D_LightNodeBlock();
PDF3D_U3D_AbstractBlockPtr pointer(block); PDF3D_U3D_AbstractBlockPtr pointer(block);
PDF3D_U3D_DataReader reader(data, object->isCompressed()); PDF3D_U3D_DataReader reader(data, object->isCompressed(), object->getContextManager());
// Read the data // Read the data
block->m_lightNodeName = reader.readString(object->getTextCodec()); block->m_lightNodeName = reader.readString(object->getTextCodec());
@ -1258,7 +1394,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_ViewNodeBlock::parse(QByteArray data, QByte
PDF3D_U3D_ViewNodeBlock* block = new PDF3D_U3D_ViewNodeBlock(); PDF3D_U3D_ViewNodeBlock* block = new PDF3D_U3D_ViewNodeBlock();
PDF3D_U3D_AbstractBlockPtr pointer(block); PDF3D_U3D_AbstractBlockPtr pointer(block);
PDF3D_U3D_DataReader reader(data, object->isCompressed()); PDF3D_U3D_DataReader reader(data, object->isCompressed(), object->getContextManager());
// Read the data // Read the data
block->m_viewNodeName = reader.readString(object->getTextCodec()); block->m_viewNodeName = reader.readString(object->getTextCodec());
@ -1404,7 +1540,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_CLODMeshDeclarationBlock::parse(QByteArray
PDF3D_U3D_CLODMeshDeclarationBlock* block = new PDF3D_U3D_CLODMeshDeclarationBlock(); PDF3D_U3D_CLODMeshDeclarationBlock* block = new PDF3D_U3D_CLODMeshDeclarationBlock();
PDF3D_U3D_AbstractBlockPtr pointer(block); PDF3D_U3D_AbstractBlockPtr pointer(block);
PDF3D_U3D_DataReader reader(data, object->isCompressed()); PDF3D_U3D_DataReader reader(data, object->isCompressed(), object->getContextManager());
// Read the data // Read the data
block->m_meshName = reader.readString(object->getTextCodec()); block->m_meshName = reader.readString(object->getTextCodec());
@ -1613,7 +1749,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_CLODBaseMeshContinuationBlock::parse(QByteA
PDF3D_U3D_CLODBaseMeshContinuationBlock* block = new PDF3D_U3D_CLODBaseMeshContinuationBlock(); PDF3D_U3D_CLODBaseMeshContinuationBlock* block = new PDF3D_U3D_CLODBaseMeshContinuationBlock();
PDF3D_U3D_AbstractBlockPtr pointer(block); PDF3D_U3D_AbstractBlockPtr pointer(block);
PDF3D_U3D_DataReader reader(data, object->isCompressed()); PDF3D_U3D_DataReader reader(data, object->isCompressed(), object->getContextManager());
// Read the data // Read the data
block->m_meshName = reader.readString(object->getTextCodec()); block->m_meshName = reader.readString(object->getTextCodec());
@ -1751,10 +1887,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_CLODProgressiveMeshContinuationBlock::parse
PDF3D_U3D_CLODProgressiveMeshContinuationBlock* block = new PDF3D_U3D_CLODProgressiveMeshContinuationBlock(); PDF3D_U3D_CLODProgressiveMeshContinuationBlock* block = new PDF3D_U3D_CLODProgressiveMeshContinuationBlock();
PDF3D_U3D_AbstractBlockPtr pointer(block); PDF3D_U3D_AbstractBlockPtr pointer(block);
PDF3D_U3D_DataReader reader(data, object->isCompressed()); PDF3D_U3D_DataReader reader(data, object->isCompressed(), object->getContextManager());
// TODO: finish this block
return nullptr;
// Read the data // Read the data
block->m_meshName = reader.readString(object->getTextCodec()); block->m_meshName = reader.readString(object->getTextCodec());
@ -1770,12 +1903,10 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_CLODProgressiveMeshContinuationBlock::parse
} }
block->m_resolutionUpdateCount = block->m_endResolution - block->m_startResolution; block->m_resolutionUpdateCount = block->m_endResolution - block->m_startResolution;
uint32_t rCurrentPositionCount = block->m_startResolution;
for (uint32_t i = 0; i < block->m_resolutionUpdateCount; ++i) for (uint32_t i = block->m_startResolution; i < block->m_endResolution; ++i)
{ {
ResolutionUpdate updateItem; ResolutionUpdate updateItem;
++rCurrentPositionCount;
if (i == 0) if (i == 0)
{ {
@ -1837,7 +1968,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_CLODProgressiveMeshContinuationBlock::parse
} }
else else
{ {
facePositionInfo.globalThirdPositionIndex = reader.readCompressedU32(reader.getRangeContext(rCurrentPositionCount)); facePositionInfo.globalThirdPositionIndex = reader.readCompressedU32(reader.getRangeContext(i));
} }
updateItem.newFaces.emplace_back(std::move(facePositionInfo)); updateItem.newFaces.emplace_back(std::move(facePositionInfo));
@ -1855,7 +1986,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_LineSetDeclarationBlock::parse(QByteArray d
PDF3D_U3D_LineSetDeclarationBlock* block = new PDF3D_U3D_LineSetDeclarationBlock(); PDF3D_U3D_LineSetDeclarationBlock* block = new PDF3D_U3D_LineSetDeclarationBlock();
PDF3D_U3D_AbstractBlockPtr pointer(block); PDF3D_U3D_AbstractBlockPtr pointer(block);
PDF3D_U3D_DataReader reader(data, object->isCompressed()); PDF3D_U3D_DataReader reader(data, object->isCompressed(), object->getContextManager());
// Read the data // Read the data
block->m_lineSetName = reader.readString(object->getTextCodec()); block->m_lineSetName = reader.readString(object->getTextCodec());
@ -1968,7 +2099,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_LineSetContinuationBlock::parse(QByteArray
PDF3D_U3D_LineSetContinuationBlock* block = new PDF3D_U3D_LineSetContinuationBlock(); PDF3D_U3D_LineSetContinuationBlock* block = new PDF3D_U3D_LineSetContinuationBlock();
PDF3D_U3D_AbstractBlockPtr pointer(block); PDF3D_U3D_AbstractBlockPtr pointer(block);
PDF3D_U3D_DataReader reader(data, object->isCompressed()); PDF3D_U3D_DataReader reader(data, object->isCompressed(), object->getContextManager());
// Read the data // Read the data
block->m_lineSetName = reader.readString(object->getTextCodec()); block->m_lineSetName = reader.readString(object->getTextCodec());
@ -1982,7 +2113,16 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_LineSetContinuationBlock::parse(QByteArray
for (uint32_t i = block->m_startResolution; i < block->m_endResolution; ++i) for (uint32_t i = block->m_startResolution; i < block->m_endResolution; ++i)
{ {
UpdateItem item; UpdateItem item;
item.splitPositionIndex = reader.readCompressedU32(reader.getRangeContext(qMax(i, 1u)));
if (i > 0)
{
item.splitPositionIndex = reader.readCompressedU32(reader.getRangeContext(i));
}
else
{
item.splitPositionIndex = reader.readCompressedU32(reader.getRangeContext(i + 1));
}
item.newPositionInfo = reader.readQuantizedVec3(reader.getStaticContext(cPosDiffSign), item.newPositionInfo = reader.readQuantizedVec3(reader.getStaticContext(cPosDiffSign),
reader.getStaticContext(cPosDiffX), reader.getStaticContext(cPosDiffX),
reader.getStaticContext(cPosDiffY), reader.getStaticContext(cPosDiffY),
@ -2076,11 +2216,75 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_LineSetContinuationBlock::parse(QByteArray
return pointer; return pointer;
} }
const std::vector<UpdateItem>& PDF3D_U3D_LineSetContinuationBlock::updateItems() const const std::vector<PDF3D_U3D_LineSetContinuationBlock::UpdateItem>& PDF3D_U3D_LineSetContinuationBlock::getUpdateItems() const
{ {
return m_updateItems; return m_updateItems;
} }
const QString& PDF3D_U3D_DecoderList::getName() const
{
return m_name;
}
void PDF3D_U3D_DecoderList::setName(const QString& newName)
{
m_name = newName;
}
const std::vector<PDF3D_U3D_DecorderList_ChainItem>& PDF3D_U3D_DecoderList::getChains() const
{
return m_chains;
}
void PDF3D_U3D_DecoderList::setChains(const std::vector<PDF3D_U3D_DecorderList_ChainItem>& newChains)
{
m_chains = newChains;
}
PDF3D_U3D_DecorderList_ChainItem* PDF3D_U3D_DecoderList::getChain(size_t index)
{
if (index < m_chains.size())
{
return &m_chains[index];
}
return nullptr;
}
void PDF3D_U3D_DecoderList::createChain(const PDF3D_U3D_Block_Data& data)
{
PDF3D_U3D_DecorderList_ChainItem item;
item.blocks = { data };
m_chains.emplace_back(std::move(item));
}
PDF3D_U3D_DecoderList* PDF3D_U3D_DecoderLists::getDecoderList(QString name)
{
for (PDF3D_U3D_DecoderList& decoderList : m_decoderLists)
{
if (decoderList.getName() == name)
{
return &decoderList;
}
}
return nullptr;
}
bool PDF3D_U3D_DecoderLists::addContinuationBlock(QString name, uint32_t chainIndex, const PDF3D_U3D_Block_Data& data)
{
if (PDF3D_U3D_DecoderList* decoderList = getDecoderList(name))
{
if (PDF3D_U3D_DecorderList_ChainItem* chain = decoderList->getChain(chainIndex))
{
chain->blocks.push_back(data);
return true;
}
}
return false;
}
} // namespace u3d } // namespace u3d
} // namespace pdf } // namespace pdf

View File

@ -35,8 +35,49 @@ namespace pdf
namespace u3d namespace u3d
{ {
enum Context
{
cPosDiffSign = 1,
cPosDiffX,
cPosDiffY,
cPosDiffZ,
cNormlCnt,
cDiffNormalSign,
cDiffNormalX,
cDiffNormalY,
cDiffNormalZ,
cLineCnt,
cShading,
cNormlIdx,
cDiffDup,
cDiffuseColorSign,
cColorDiffR,
cColorDiffG,
cColorDiffB,
cColorDiffA,
cSpecDup,
cSpecularColorSign,
cTexCDup,
cTexCoordSign,
cTexCDiffU,
cTexCDiffV,
cTexCDiffS,
cTexCDiffT,
cZero,
cDiffuseCount,
cSpecularCount,
cTexCoordCount,
cFaceCnt,
cFaceOrnt,
cLocal3rdPos,
cThrdPosType
};
class PDF3D_U3D; class PDF3D_U3D;
class PDF3D_U3D_DataReader; class PDF3D_U3D_DataReader;
class PDF3D_U3D_ContextManager;
struct PDF3D_U3D_Block_Data;
class PDF3D_U3D_AbstractBlock; class PDF3D_U3D_AbstractBlock;
using PDF3D_U3D_AbstractBlockPtr = QSharedPointer<PDF3D_U3D_AbstractBlock>; using PDF3D_U3D_AbstractBlockPtr = QSharedPointer<PDF3D_U3D_AbstractBlock>;
@ -61,6 +102,14 @@ struct PDF3D_U3D_QuantizedVec3
uint32_t diff3; uint32_t diff3;
}; };
struct PDF3D_U3D_Block_Data
{
uint32_t blockType = 0;
QByteArray blockData;
QByteArray metaData;
};
struct PDF3D_U3D_ShadingDescription struct PDF3D_U3D_ShadingDescription
{ {
uint32_t shadingAttributes = 0; uint32_t shadingAttributes = 0;
@ -202,7 +251,7 @@ public:
const PDF3D_U3D_BoundingSphere& getBoundingSphere() const; const PDF3D_U3D_BoundingSphere& getBoundingSphere() const;
const PDF3D_U3D_AxisAlignedBoundingBox& getBoundingBox() const; const PDF3D_U3D_AxisAlignedBoundingBox& getBoundingBox() const;
uint32_t getModifierCount() const; uint32_t getModifierCount() const;
const std::vector<PDF3D_U3D_AbstractBlockPtr>& getModifierDeclarationBlocks() const; const std::vector<PDF3D_U3D_Block_Data>& getModifierDeclarationBlocks() const;
private: private:
QString m_modifierChainName; QString m_modifierChainName;
@ -212,7 +261,7 @@ private:
PDF3D_U3D_AxisAlignedBoundingBox m_boundingBox = PDF3D_U3D_AxisAlignedBoundingBox(); PDF3D_U3D_AxisAlignedBoundingBox m_boundingBox = PDF3D_U3D_AxisAlignedBoundingBox();
// Padding 0-3 bytes // Padding 0-3 bytes
uint32_t m_modifierCount = 0; uint32_t m_modifierCount = 0;
std::vector<PDF3D_U3D_AbstractBlockPtr> m_modifierDeclarationBlocks; std::vector<PDF3D_U3D_Block_Data> m_modifierDeclarationBlocks;
}; };
class PDF3D_U3D_PriorityUpdateBlock : public PDF3D_U3D_AbstractBlock class PDF3D_U3D_PriorityUpdateBlock : public PDF3D_U3D_AbstractBlock
@ -559,11 +608,6 @@ public:
const std::vector<BaseFace>& getBaseFaces() const; const std::vector<BaseFace>& getBaseFaces() const;
private: private:
enum Context
{
cShading = 1
};
QString m_meshName; QString m_meshName;
uint32_t m_chainIndex = 0; uint32_t m_chainIndex = 0;
@ -610,30 +654,6 @@ public:
}; };
private: private:
enum Context
{
cZero = 1,
cDiffuseCount,
cDiffuseColorSign,
cColorDiffR,
cColorDiffG,
cColorDiffB,
cColorDiffA,
cSpecularCount,
cSpecularColorSign,
cTexCoordCount,
cTexCoordSign,
cTexCDiffU,
cTexCDiffV,
cTexCDiffS,
cTexCDiffT,
cFaceCnt,
cShading,
cFaceOrnt,
cLocal3rdPos,
cThrdPosType
};
QString m_meshName; QString m_meshName;
uint32_t m_chainIndex = 0; uint32_t m_chainIndex = 0;
@ -737,40 +757,9 @@ public:
const QString& getName() const { return m_lineSetName; } const QString& getName() const { return m_lineSetName; }
const std::vector<UpdateItem>& updateItems() const; const std::vector<UpdateItem>& getUpdateItems() const;
private: private:
enum Context
{
cPosDiffSign = 1,
cPosDiffX,
cPosDiffY,
cPosDiffZ,
cNormlCnt,
cDiffNormalSign,
cDiffNormalX,
cDiffNormalY,
cDiffNormalZ,
cLineCnt,
cShading,
cNormlIdx,
cDiffDup,
cDiffuseColorSign,
cColorDiffR,
cColorDiffG,
cColorDiffB,
cColorDiffA,
cSpecDup,
cSpecularColorSign,
cTexCDup,
cTexCoordSign,
cTexCDiffU,
cTexCDiffV,
cTexCDiffS,
cTexCDiffT
};
QString m_lineSetName; QString m_lineSetName;
uint32_t m_chainIndex = 0; uint32_t m_chainIndex = 0;
@ -794,6 +783,12 @@ public:
static PDF3D_U3D parse(QByteArray data); static PDF3D_U3D parse(QByteArray data);
static void processBlock(PDF3D_U3D& object,
const PDF3D_U3D_Block_Data& blockData,
PDF3D_U3D_DecoderLists& decoderLists,
QStringList& errors,
PDF3D_U3D_DecoderLists::EPalette palette);
const PDF3D_U3D_CLODMeshDeclarationBlock* getCLODMeshDeclarationBlock(const QString& meshName) const; const PDF3D_U3D_CLODMeshDeclarationBlock* getCLODMeshDeclarationBlock(const QString& meshName) const;
const PDF3D_U3D_LineSetDeclarationBlock* getLineSetDeclarationBlock(const QString& lineSetName) const; const PDF3D_U3D_LineSetDeclarationBlock* getLineSetDeclarationBlock(const QString& lineSetName) const;
@ -801,10 +796,16 @@ public:
const T* getBlock(const QString& name) const; const T* getBlock(const QString& name) const;
PDF3D_U3D_AbstractBlockPtr parseBlockWithDeclaration(PDF3D_U3D_DataReader& reader); PDF3D_U3D_AbstractBlockPtr parseBlockWithDeclaration(PDF3D_U3D_DataReader& reader);
PDF3D_U3D_ContextManager* getContextManager() { return m_contextManager.lock().get(); }
void setContextManager(std::weak_ptr<PDF3D_U3D_ContextManager> contextManager) { m_contextManager = std::move(contextManager); }
static PDF3D_U3D_Block_Data readBlockData(PDF3D_U3D_DataReader& reader);
private: private:
PDF3D_U3D_AbstractBlockPtr parseBlock(uint32_t blockType, const QByteArray& data, const QByteArray& metaData); PDF3D_U3D_AbstractBlockPtr parseBlock(uint32_t blockType, const QByteArray& data, const QByteArray& metaData);
PDF3D_U3D_AbstractBlockPtr parseBlock(const PDF3D_U3D_Block_Data& data);
static uint32_t getBlockPadding(uint32_t blockSize); static uint32_t getBlockPadding(uint32_t blockSize);
static bool isContinuationBlock(uint32_t blockType);
struct LoadBlockInfo struct LoadBlockInfo
{ {
@ -816,11 +817,13 @@ private:
PDF3D_U3D_AbstractBlockPtr block; PDF3D_U3D_AbstractBlockPtr block;
}; };
PDF3D_U3D_AbstractBlockPtr m_fileBlock;
std::vector<PDF3D_U3D_AbstractBlockPtr> m_blocks; std::vector<PDF3D_U3D_AbstractBlockPtr> m_blocks;
std::vector<LoadBlockInfo> m_allBlocks; std::vector<LoadBlockInfo> m_allBlocks;
const PDF3D_U3D_FileBlock* m_fileBlock = nullptr;
QTextCodec* m_textCodec = nullptr; QTextCodec* m_textCodec = nullptr;
bool m_isCompressed = true; bool m_isCompressed = true;
uint32_t m_priority = 0;
std::weak_ptr<PDF3D_U3D_ContextManager> m_contextManager;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -877,10 +880,55 @@ public:
static constexpr uint32_t S_MAXIMUM_SYMBOL_IN_HISTOGRAM = 0x0000FFFF; static constexpr uint32_t S_MAXIMUM_SYMBOL_IN_HISTOGRAM = 0x0000FFFF;
}; };
struct PDF3D_U3D_DecorderList_ChainItem
{
std::vector<PDF3D_U3D_Block_Data> blocks;
};
class PDF3D_U3D_DecoderList
{
public:
PDF3D_U3D_DecoderList() = default;
const QString& getName() const;
void setName(const QString& newName);
const std::vector<PDF3D_U3D_DecorderList_ChainItem>& getChains() const;
void setChains(const std::vector<PDF3D_U3D_DecorderList_ChainItem>& newChains);
PDF3D_U3D_DecorderList_ChainItem* getChain(size_t index);
void createChain(const PDF3D_U3D_Block_Data& data);
private:
QString m_name;
std::vector<PDF3D_U3D_DecorderList_ChainItem> m_chains;
};
class PDF3D_U3D_DecoderLists
{
public:
enum EPalette
{
Node,
View,
Light,
LastPalette
};
PDF3D_U3D_DecoderList* getDecoderList(QString name);
bool addContinuationBlock(QString name, uint32_t chainIndex, const PDF3D_U3D_Block_Data& data);
void addDecoderList(PDF3D_U3D_DecoderList&& list) { m_decoderLists.emplace_back(std::move(list)); }
private:
std::vector<PDF3D_U3D_DecoderList> m_decoderLists;
};
class PDF3D_U3D_DataReader class PDF3D_U3D_DataReader
{ {
public: public:
PDF3D_U3D_DataReader(QByteArray data, bool isCompressed); PDF3D_U3D_DataReader(QByteArray data, bool isCompressed, PDF3D_U3D_ContextManager* contextManager);
~PDF3D_U3D_DataReader(); ~PDF3D_U3D_DataReader();
void setData(QByteArray data); void setData(QByteArray data);
@ -957,7 +1005,7 @@ private:
uint32_t read15Bits(); uint32_t read15Bits();
QByteArray m_data; QByteArray m_data;
PDF3D_U3D_ContextManager m_contextManager; PDF3D_U3D_ContextManager* m_contextManager;
uint32_t m_high; uint32_t m_high;
uint32_t m_low; uint32_t m_low;

View File

@ -198,6 +198,14 @@ void PDFMediaViewerDialog::initFrom3DAnnotation(const pdf::PDFDocument* document
{ {
case pdf::PDF3DStream::Type::U3D: case pdf::PDF3DStream::Type::U3D:
{ {
QString file = "K:\\Programming\\PDF\\PDF_For_Qt\\U3D_parser\\u3d-tools\\src\\test.u3d";
QFile f(file);
if (f.open(QFile::WriteOnly | QFile::Truncate))
{
f.write(data);
f.close();
}
pdf::u3d::PDF3D_U3D u3d = pdf::u3d::PDF3D_U3D::parse(data); pdf::u3d::PDF3D_U3D u3d = pdf::u3d::PDF3D_U3D::parse(data);
break; break;
} }