2014-12-04 209 views
1

因此,我的目标是创建一个自包含文件,其中包含要加载到3D场景中的所有资源。例如,将会有一个文本文件详细说明模型的所有位置,旋转,比例等,然后是内置模型和纹理的文件夹。这在文件夹中并不难,但为了简单起见,我想将它全部放到一个文件中,避免压缩并解压缩。我不想压缩和解压缩它的原因是为了加快加载时间,因为这是针对游戏的。将文件夹变为单个文件而不压缩它?

是否有任何可能的方式来做到这一点?或者我将不得不咬住子弹并将其制成拉链。

谢谢。

+4

a)Zip不需要压缩。 b)Zip,7z,Tar,Bzip2等等。有很多这样的格式。 c)你总是可以制作自己的二进制文件格式。 d)除了在b中提到的一般存档格式之外,还有一些已建立的专用3D模型文件格式(以及用于保存/加载它们的库)... – deviantfan 2014-12-04 00:30:38

+0

无论您使用什么,如果您将按需加载资源,你想要一个有索引的档案格式。 Zip确实;焦油不。这意味着你必须寻找所有的地方才能发现你拥有的资源和位置。 – cdhowie 2014-12-04 00:41:55

+0

@cdhowie基于大家都说过的话,我想我会用低压缩zip。 – BlueSpud 2014-12-04 00:42:55

回答

3

您可以使用ZIP无压缩或TAR。但是这里有一个更好的主意:压缩它。 CPU时间很便宜。磁盘传输需要永久。大多数情况下,加载压缩数据并解压缩比加载未压缩数据更快。

+0

所以你说加载压缩文件,然后解压缩它会比保持压缩更快? – BlueSpud 2014-12-04 00:34:18

+1

是的,使用某些快速算法,特别是具有非常高压缩比的3D模型。 – 2014-12-04 00:36:12

+1

@BlueSpud根据您的硬盘和CPU,可能(和AdrianMaire所说的压缩算法一样)。较慢的硬盘和较快的CPU会增加效益。另一方面,固态硬盘和Raspi ... – deviantfan 2014-12-04 00:36:26

1

您可以创建一个没有压缩的ZIP文件。 (“存储”模式)。还有类似的包装归档器,可用于从多个文件创建单个归档。 * nix系统上的TAR文件非常受欢迎,并且还有许多其他文件。

此外,平衡,将是花解压缩对抗将用于从磁盘装载的(未压缩)文件的时间量的时间量。很多时候,未压缩文件的磁盘读取时间比加载压缩文件并将其解压缩到内存中的时间要长。

+1

你的回答是正确的,但是据我了解这个问题,BlueSpud似乎需要更像文件格式的东西。 – 2014-12-04 00:34:14

+1

同意。我的观点是,继续前进并使用压缩ZIP文件 - 可能会因为磁盘I/O减少而节省时间。 – jwismar 2014-12-04 00:35:36

+0

@AdrianMaire如果将它解压缩为一个文件夹一样快,它将适合我的需要就好。 – BlueSpud 2014-12-04 00:35:40

1

如果这是一个Windows应用程序,你可以使用用户定义的资源语句在.rc文件为您的EXE或DLL包含(一个或多个),将来自外部文件作为二进制资源插入数据。如果您只想分发一个依赖其他文件中包含的数据的EXE文件,或者不想让您的应用程序可以通过以下方式进行存档和发布的文件,那么这对于您的应用程序可访问/可修改(无需工作)最终用户。

这是非常简单的 - 语法只是

nameID typeID filename 

的资源文件。您可以使用::FindResource()::LoadResource().访问数据用户定义资源的MS文档位于http://msdn.microsoft.com/en-us/library/windows/desktop/aa381054(v=vs.85).aspx

+0

不幸的是,这是在Linux Mac和Windows,所以我有一个项目,不想让3个项目改变它们。 – BlueSpud 2014-12-04 01:04:52

0

原始质询的定时可以是偶然的。事实证明,将来我所建议的查找/加载资源方法对我们来说也不会是我们的选择(我以前使用它的代码是跨平台的),所以我想出了一个解决方案,它也可能为你工作。尽管你可以很快做出一个你自己的快速版本,但完整的代码可以作为一个SO回答发布(但请参阅我的后续评论)。

基本上,我写了一个工具,只是需要一个基本名称为输出文件为argv[1](“输出基本名”),并argv[2...(argc-1)]输入文件。我打开output-base-name.cppoutput-base-name.h进行书写(如果它们存在,将覆盖)。

对于每个输入文件中,生成器实用程序执行此:

1:基于所述文件名的变量名友好标识符(“ generated_name”)
2:读取输入文件
3:转储到下列output-base-name.cpp

static uint8_t generated_name[] = { 
    // Initialize with contents of input file as a bunch of 0xNN, 0xNN... values. 
}; 

并进入output-base-name.h,相应

static const unsigned IDR_generated_name = N; // start at 0, see below re:range check 

4:最后输入文件后,完成了output-base-name.cpp喜欢的东西

static struct { 
    unsigned  ID; 
    unsigned  size; // I assume you aren't trying to embed files >4GB! 
    const uint8_t* data; 
} 
fileData[] = { 
    // one array element for each input file 
    { IDR_generated_name, sizeof(generated_name), generated_name }, 
    ... 
}; 

const uint8_t* getResourceData(unsigned ID){ 
    // a real version would do a safer lookup/range check of some sort based on ID 
    return fileData[ID].data; 
} 

unsigned getResourceSize(unsigned ID){ 
    // a real version would do a safer lookup/range check of some sort based on ID 
    return fileData[ID].size; 
} 

5:饰面output-base-name.h与原型无论你的 “获取” 功能的模样,例如

extern const uint8_t* getResourceData(unsigned ID); 
extern unsigned getResourceSize(unsigned ID); 

只需使用output-base-name.h你需要的地方访问数据,并添加output-base-name.cpp到你的makefile或项目(使其依赖于二进制输入文件,使用构建规则的生成工具和make会自动生成它的你必要时)。如果你想让它们处于某种动态库中,只需将适当的导出属性添加到你的“get”函数中即可。

有发电机包裹你的输出在一个命名空间,如果你想基于类的接口拼凑到它(或产生一个,而不是如“获取”功能),你应该是好的。

这种方法比使用未压缩的压缩文件(甚至我建议为Windows目标嵌入的资源的方法)几个优点:

  1. 这是一个简单得多,处理在应用程序代码 - 不读书zip目录,提取文件数据等是必需的。
  2. 无添加另一个第三方lib中查找/提取文件数据的依赖(假设你没有推出自己的压缩库,这将是更多的工作)
  3. 所有决议和查找工作是做你 - 每个字节数组的地址将已经被链接器,如果数据扎进静态库或可执行的二进制解决,或由操作系统加载器,如果共享库或DLL
  4. 你知道数据将存在或无法运行(不是使用zip lib方法的情况,甚至是Windows上的Find/LoadResource)
  5. 与用户相比,Joe用户更难访问数据(因此更安全),与zip文件相比
  6. 应该比任何的zip或Windows资源的方法更快,因为数据地址的预解析过程中应用程序的加载过程
  7. 它也可以用于任何形式的相对静态的数据要与出货(或使其可用)您的应用程序 - 只需使用生成器将文件打包到共享/动态库中,并使用生成的导出存取器函数即可。您甚至可以稍后(在编译/装运时间后)创建更新的或全新的数据包,并使用配置选项在运行时加载。
  8. 它将在年龄较大的C++编译器的工作,如果必要(或,SANS生成任何命名空间或类包装,即使普通老式-C)

这仅是我所使用的方法的一个例子,但它涵盖了所有的基础知识,所以如果一个解决方案尽快而不是迟一点(再次看到评论)对你更好,这可能就足够了(你想要在“get”函数中进行范围检查 - 至少在调试版本中,也许使用某种类型的容器而不是使用c-style结构数组等)。

+0

在回答(第1部分)中引用的后续评论: 虽然完整的源代码不会在回复中发布(对于长度+在meta post中讨论的其他原因[此处](http://meta.stackoverflow.com/questions/278616/提供后续链接为答案)),我几乎完成了一个将作为开源发布的完整实现。我将在城外待上几天,但我会清理,完成并为我的快速肮脏/概念验证版本添加更多功能,并在我返回时发布到我的博客上。 – frasnian 2014-12-07 08:00:37

+0

后续第2部分(太长时间只有一个): 当我发布它时,我将删除这些评论并在答案中添加一个链接到源位置,因此如果任何人对全部源感兴趣,只需“最喜欢的“当我发布链接时(可能距离现在一周左右),您的个人资料中的原始问题和您的收藏夹标签将会突出显示。 – frasnian 2014-12-07 08:01:26

相关问题