2021SC@SDUSC
Snapshot
1.Snapshot.h
class Snapshot
{
public:
std::map<QString, QString> canvas;
std::map<QString, std::map<QString, QString>> nodes;
std::map<QString, std::map<QString, QString>> edges;
std::map<QString, std::map<QString, QString>> parts;
std::map<QString, std::map<QString, QString>> components;
std::map<QString, QString> rootComponent;
std::map<QString, std::map<QString, QString>> motions;
std::vector<std::pair<std::map<QString, QString>, std::vector<std::pair<std::map<QString, QString>, std::vector<std::map<QString, QString>>>>>> materials; // std::pair<Material attributes, layers> layer: std::pair<Layer attributes, maps>
void resolveBoundingBox(QRectF *mainProfile, QRectF *sideProfile, const QString &partId=QString()) const;
};
Snapshot类中包含8个公有变量,一个公有函数。snapshot表示一张快照,Dust3d需要从快照中提取出信息,在三维空间中进行还原。
2.Snapshot.cpp
Snapshot.cpp实现的是通过快照中每个节点的位置信息和半径,来形成包围盒足以在三维世界中容纳快照中的物体。
快照中需要包含每个节点的位置信息和大小信息(半径)
void Snapshot::resolveBoundingBox(QRectF *mainProfile, QRectF *sideProfile, const QString &partId) const
{
float left = 0;
bool leftFirstTime = true;
float right = 0;
bool rightFirstTime = true;
float top = 0;
bool topFirstTime = true;
float bottom = 0;
bool bottomFirstTime = true;
float zLeft = 0;
bool zLeftFirstTime = true;
float zRight = 0;
bool zRightFirstTime = true;
//nodes:map中的节点
for (const auto &nodeIt: nodes) {
if (!partId.isEmpty() && partId != valueOfKeyInMapOrEmpty(nodeIt.second, "partId"))
//如果partId为空或不在快照中
continue;
float radius = valueOfKeyInMapOrEmpty(nodeIt.second, "radius").toFloat();
float x = valueOfKeyInMapOrEmpty(nodeIt.second, "x").toFloat();
float y = valueOfKeyInMapOrEmpty(nodeIt.second, "y").toFloat();
float z = valueOfKeyInMapOrEmpty(nodeIt.second, "z").toFloat();
/*util.cpp
QString valueOfKeyInMapOrEmpty(const std::map<QString, QString> &map, const QString &key)
{
auto it = map.find(key);
if (it == map.end())
return QString();
return it->second;
}
*/
if (leftFirstTime || x - radius < left) {
//第一次向左或者x-radius出了left的边界
//把左边界进行拓展
left = x - radius;
leftFirstTime = false;
}
if (topFirstTime || y - radius < top) {
//同理拓展上边界
top = y - radius;
topFirstTime = false;
}
if (rightFirstTime || x + radius > right) {
//拓展右边界
right = x + radius;
rightFirstTime = false;
}
if (bottomFirstTime || y + radius > bottom) {
//拓展下边界
bottom = y + radius;
bottomFirstTime = false;
}
if (zLeftFirstTime || z - radius < zLeft) {
//拓展前边界
zLeft = z - radius;
zLeftFirstTime = false;
}
if (zRightFirstTime || z + radius > zRight) {
//拓展后边界
zRight = z + radius;
zRightFirstTime = false;
}
}
*mainProfile = QRectF(QPointF(left, top), QPointF(right, bottom));
*sideProfile = QRectF(QPointF(zLeft, top), QPointF(zRight, bottom));
//还原包围盒的大小,能够容纳快照中的节点
}
Material 材质
1.material.h
material.h中包含:
(1)结构体MaterialTextures,结构体中含有QImage类的指针
(2)函数initializeMaterialTexturesFromSnapshot,在material.cpp中进行详细说明
struct MaterialTextures
{
const QImage *textureImages[(int)TextureType::Count - 1] = {nullptr};
};
void initializeMaterialTexturesFromSnapshot(const Snapshot &snapshot,
const QUuid &materialId,
MaterialTextures &materialTextures,
float &tileScale);
#endif
2.material.cpp
主要介绍了函数 initializeMaterialTexturesFromSnapshot
输入 | 结果 |
快照snapshot | 函数无返回值,函数运行结束后可以使 materialTextures.textureImages中的image与imageId一一对应 |
材质的序号materialId | |
纹理materialTextures | |
材质块的大小tileScale |
void initializeMaterialTexturesFromSnapshot(const Snapshot &snapshot,
const QUuid &materialId,
MaterialTextures &materialTextures,
float &tileScale)
{
QString materialIdString = materialId.toString();
for (const auto &materialItem: snapshot.materials) {
if (materialIdString != valueOfKeyInMapOrEmpty(materialItem.first, "id"))
continue;
//找到materialId所对应的material
for (const auto &layer: materialItem.second)
{
//FIXME: Only support one layer currently
auto findTileScale = layer.first.find("tileScale");
if (findTileScale != layer.first.end())
//如果找到了tileScale
tileScale = findTileScale->second.toFloat();
for (const auto &mapItem: layer.second)
{
auto textureType = TextureTypeFromString(valueOfKeyInMapOrEmpty(mapItem, "for").toUtf8().constData());
if (textureType != TextureType::None)
{
int index = (int)textureType - 1;
if (index >= 0 && index < (int)TextureType::Count - 1)
{
if ("imageId" == valueOfKeyInMapOrEmpty(mapItem, "linkDataType"))
{
auto imageIdString = valueOfKeyInMapOrEmpty(mapItem, "linkData");
materialTextures.textureImages[index] = ImageForever::get(QUuid(imageIdString));
//得到所对应的image
}
}
}
}
break;
}
break;
}
}
函数内部涉及的ImageForever::get函数:通过id找到对应的image
const QImage *ImageForever::get(const QUuid &id)
{
QMutexLocker locker(&g_mapMutex);
auto findResult = g_foreverMap.find(id);
if (findResult == g_foreverMap.end())
return nullptr;
return findResult->second.image;
}