void NDSFile::readNames(Common::SeekableReadStream &nds, uint32 offset, uint32 length) { if (!nds.seek(offset + 8)) throw Common::Exception(Common::kSeekError); uint32 index = 0; while (((uint32) nds.pos()) < (offset + length)) { Resource res; byte nameLength = nds.readByte(); Common::UString name; name.readFixedASCII(nds, nameLength); name.tolower(); res.name = setFileType(name, kFileTypeNone); res.type = getFileType(name); res.index = index++; _resources.push_back(res); } while (!_resources.empty() && _resources.back().name.empty()) _resources.pop_back(); }
Common::UString GFFStruct::readLabel(Common::SeekableReadStream &gff, uint32 index) const { gff.seek(_parent->_header.labelOffset + index * 16); Common::UString label; label.readFixedASCII(gff, 16); return label; }
bool NDSFile::isNDS(Common::SeekableReadStream &stream) { if (!stream.seek(0)) return false; Common::UString gameName; gameName.readFixedASCII(stream, 12); if (gameName != "SONICCHRON") // Should be the only game we will accept. return false; if (!stream.seek(0x40)) return false; return true; }
bool ModelNode_NWN2::loadSkin(Model_NWN2::ParserContext &ctx) { if (ctx.mdb->readUint32BE() != kSkinID) throw Common::Exception("Packet signatures do not match"); uint32 packetSize = ctx.mdb->readUint32LE(); _name.readFixedASCII(*ctx.mdb, 32); // Skipping lower level of detail models if (_name.endsWith("_L01") || _name.endsWith("_L02")) return false; Common::UString skeletonName; skeletonName.readFixedASCII(*ctx.mdb, 32); Common::UString diffuseMap, normalMap, tintMap, glowMap; diffuseMap.readFixedASCII(*ctx.mdb, 32); normalMap.readFixedASCII(*ctx.mdb, 32); tintMap.readFixedASCII(*ctx.mdb, 32); glowMap.readFixedASCII(*ctx.mdb, 32); _diffuse [0] = ctx.mdb->readIEEEFloatLE(); _diffuse [1] = ctx.mdb->readIEEEFloatLE(); _diffuse [2] = ctx.mdb->readIEEEFloatLE(); _specular[0] = ctx.mdb->readIEEEFloatLE(); _specular[1] = ctx.mdb->readIEEEFloatLE(); _specular[2] = ctx.mdb->readIEEEFloatLE(); float specularPower = ctx.mdb->readIEEEFloatLE(); float specularValue = ctx.mdb->readIEEEFloatLE(); uint32 textureFlags = ctx.mdb->readUint32LE(); uint32 vertexCount = ctx.mdb->readUint32LE(); uint32 faceCount = ctx.mdb->readUint32LE(); if ((vertexCount == 0) || (faceCount == 0)) return false; std::vector<Common::UString> textures; textures.push_back(diffuseMap); uint32 textureCount = textures.size(); loadTextures(textures); if (!createFaces(faceCount)) return false; // Read vertex coordinates std::vector<float> vX, vY, vZ; vX.resize(vertexCount); vY.resize(vertexCount); vZ.resize(vertexCount); std::vector<float> tX, tY, tZ; tX.resize(vertexCount); tY.resize(vertexCount); tZ.resize(vertexCount); for (uint32 i = 0; i < vertexCount; i++) { vX[i] = ctx.mdb->readIEEEFloatLE(); vY[i] = ctx.mdb->readIEEEFloatLE(); vZ[i] = ctx.mdb->readIEEEFloatLE(); ctx.mdb->skip(3 * 4); // Normals ctx.mdb->skip(4 * 4); // Bone weights ctx.mdb->skip(4 * 1); // Bone indices ctx.mdb->skip(3 * 4); // Tangents ctx.mdb->skip(3 * 4); // Binormals tX[i] = ctx.mdb->readIEEEFloatLE(); tY[i] = ctx.mdb->readIEEEFloatLE(); tZ[i] = ctx.mdb->readIEEEFloatLE(); ctx.mdb->skip(4); // Bone count } // Read faces for (uint32 i = 0; i < faceCount; i++) { const uint16 v1 = ctx.mdb->readUint16LE(); const uint16 v2 = ctx.mdb->readUint16LE(); const uint16 v3 = ctx.mdb->readUint16LE(); // Vertex coordinates _vX[3 * i + 0] = v1 < vX.size() ? vX[v1] : 0.0; _vY[3 * i + 0] = v1 < vY.size() ? vY[v1] : 0.0; _vZ[3 * i + 0] = v1 < vZ.size() ? vZ[v1] : 0.0; _boundBox.add(_vX[3 * i + 0], _vY[3 * i + 0], _vZ[3 * i + 0]); _vX[3 * i + 1] = v2 < vX.size() ? vX[v2] : 0.0; _vY[3 * i + 1] = v2 < vY.size() ? vY[v2] : 0.0; _vZ[3 * i + 1] = v2 < vZ.size() ? vZ[v2] : 0.0; _boundBox.add(_vX[3 * i + 1], _vY[3 * i + 1], _vZ[3 * i + 1]); _vX[3 * i + 2] = v3 < vX.size() ? vX[v3] : 0.0; _vY[3 * i + 2] = v3 < vY.size() ? vY[v3] : 0.0; _vZ[3 * i + 2] = v3 < vZ.size() ? vZ[v3] : 0.0; _boundBox.add(_vX[3 * i + 2], _vY[3 * i + 2], _vZ[3 * i + 2]); // Texture coordinates for (uint32 t = 0; t < textureCount; t++) { _tX[3 * textureCount * i + 3 * t + 0] = v1 < tX.size() ? tX[v1] : 0.0; _tY[3 * textureCount * i + 3 * t + 0] = v1 < tY.size() ? tY[v1] : 0.0; _tX[3 * textureCount * i + 3 * t + 1] = v2 < tX.size() ? tX[v2] : 0.0; _tY[3 * textureCount * i + 3 * t + 1] = v2 < tY.size() ? tY[v2] : 0.0; _tX[3 * textureCount * i + 3 * t + 2] = v3 < tX.size() ? tX[v3] : 0.0; _tY[3 * textureCount * i + 3 * t + 2] = v3 < tY.size() ? tY[v3] : 0.0; } } createCenter(); _render = true; return true; }
Common::UString GFFStruct::getString(const Common::UString &field, const Common::UString &def) const { load(); const Field *f = getField(field); if (!f) return def; if (f->type == kFieldTypeExoString) { Common::SeekableReadStream &data = getData(*f); uint32 length = data.readUint32LE(); Common::UString str; str.readFixedASCII(data, length); return str; } if (f->type == kFieldTypeResRef) { Common::SeekableReadStream &data = getData(*f); uint32 length = data.readByte(); Common::UString str; str.readFixedASCII(data, length); return str; } if ((f->type == kFieldTypeByte ) || (f->type == kFieldTypeUint16) || (f->type == kFieldTypeUint32) || (f->type == kFieldTypeUint64)) { return Common::UString::sprintf("%lu", getUint(field)); } if ((f->type == kFieldTypeChar ) || (f->type == kFieldTypeSint16) || (f->type == kFieldTypeSint32) || (f->type == kFieldTypeSint64)) { return Common::UString::sprintf("%ld", getSint(field)); } if ((f->type == kFieldTypeFloat) || (f->type == kFieldTypeDouble)) { return Common::UString::sprintf("%lf", getDouble(field)); } if (f->type == kFieldTypeVector) { float x, y, z; getVector(field, x, y, z); return Common::UString::sprintf("%f/%f/%f", x, y, z); } if (f->type == kFieldTypeOrientation) { float a, b, c, d; getOrientation(field, a, b, c, d); return Common::UString::sprintf("%f/%f/%f/%f", a, b, c, d); } throw Common::Exception("Field is not a string(able) type"); }
void Model_Witcher::load(ParserContext &ctx) { if (ctx.mdb->readByte() != 0) { ctx.mdb->seek(0); Common::UString type; type.readASCII(*ctx.mdb); if (type.beginsWith("binarycompositemodel")) throw Common::Exception("TODO: binarycompositemodel"); throw Common::Exception("Not a The Witcher MDB file"); } ctx.mdb->seek(4); ctx.fileVersion = ctx.mdb->readUint16LE(); ctx.mdb->skip(10); ctx.modelDataSize = ctx.mdb->readUint32LE(); ctx.mdb->skip(4); ctx.offModelData = 32; if (ctx.fileVersion == 133) { ctx.offRawData = ctx.mdb->readUint32LE() + ctx.offModelData; ctx.rawDataSize = ctx.mdb->readUint32LE(); ctx.offTexData = ctx.offModelData; ctx.texDatasize = 0; } else { ctx.offRawData = ctx.offModelData; ctx.rawDataSize = 0; ctx.offTexData = ctx.mdb->readUint32LE() + ctx.offModelData; ctx.texDatasize = ctx.mdb->readUint32LE(); } ctx.mdb->skip(8); _name.readFixedASCII(*ctx.mdb, 64); uint32 offsetRootNode = ctx.mdb->readUint32LE(); ctx.mdb->skip(32); byte type = ctx.mdb->readByte(); ctx.mdb->skip(3); ctx.mdb->skip(48); float firstLOD = ctx.mdb->readIEEEFloatLE(); float lastLOD = ctx.mdb->readIEEEFloatLE(); ctx.mdb->skip(16); Common::UString detailMap; detailMap.readFixedASCII(*ctx.mdb, 64); ctx.mdb->skip(4); float scale = ctx.mdb->readIEEEFloatLE(); Common::UString superModel; superModel.readFixedASCII(*ctx.mdb, 64); ctx.mdb->skip(16); newState(ctx); ModelNode_Witcher *rootNode = new ModelNode_Witcher(*this); ctx.nodes.push_back(rootNode); ctx.mdb->seek(ctx.offModelData + offsetRootNode); rootNode->load(ctx); addState(ctx); }