2014-12-04 1 views
1

Итак, моя цель - создать автономный файл, в который будут включены все активы для загрузки в 3D-сцену. Например, будет один текстовый файл, в котором будут подробно описаны все позиции, вращения, весы и т. Д. Моделей, а затем папки с моделями и текстурами внутри. Это не сложно сделать в папке, но для простоты я хочу, чтобы все это было в одном файле, избегая сжатия и разжатия. Причина, по которой я не хочу сжимать и распаковывать ее, - это ускорить время загрузки, потому что это для игры.Включение папки в один файл без его обрезки?

Есть ли способ для этого? Или мне придется укусить пулю и превратить ее в почтовый индекс.

Спасибо.

+4

a) Zip не требует сжатия. b) Zip, 7z, Tar, Bzip2 и т. д. Существует много таких форматов. c) Вы всегда можете создать свой собственный формат двоичного файла. d) Помимо обычных архивных форматов, как упомянуто в b, есть также некоторые специализированные форматы файлов 3D-моделей (и libs для их сохранения/загрузки) ... – deviantfan

+0

Что бы вы ни пошли, если вы будете загружать ресурсы по требованию, тогда вам нужен формат архива с индексом. Zip делает; смолы нет. Это означает, что с помощью tar вам придется искать повсюду, чтобы узнать, какие у вас есть ресурсы и где они находятся. – cdhowie

+0

@cdhowie Основываясь на том, что все сказали, я думаю, что я собираюсь пойти с низким сжатым почтовым индексом. – BlueSpud

ответ

3

Вы можете использовать ZIP без сжатия или TAR. Но вот лучшая идея: сжать ее. Время процессора дешево. Передачи дисков выполняются навсегда. Большую часть времени загрузка сжатых данных и их декомпрессия выполняется быстрее, чем загрузка несжатых данных.

+0

Значит, вы говорите, что загружаете в сжатый файл, а затем разжимаете его, это будет быстрее, чем оставить его несжатым? – BlueSpud

+1

Да, с некоторым быстрым алгоритмом, который является истинным, особенно с 3D-моделями, которые имеют очень высокий коэффициент сжатия. –

+1

@BlueSpud В зависимости от вашего жесткого диска и процессора, возможно (и, как сказал AdrianMaire, сжатие algo). Более медленный жесткий диск и более быстрый процессор увеличат выгоду. SSD и Raspi, с другой стороны ... – deviantfan

1

Вы можете создать ZIP-файл без сжатия. («Сохраненный» режим.) Существуют также аналогичные архиваторы пакетов, которые полезны для создания одного архива из нескольких файлов. Для этого популярны TAR-файлы на системах * nix, и есть много других.

Кроме того, балансируйте время, затрачиваемое на распаковку, на время, затрачиваемое на загрузку (несжатого) файла с диска. Много раз время чтения диска для несжатого файла больше времени, затрачиваемого на загрузку сжатого файла и разжатие его в памяти.

+1

Ваш ответ верный, но, как я понимаю, BlueSpud, похоже, нуждается в чем-то более похожем на формат файла. –

+1

Согласовано. Я хочу сказать, что продвижение вперед и использование ZIP-файла - с сжатием - может привести к экономии времени из-за уменьшения дискового ввода-вывода. – jwismar

+0

@AdrianMaire Если сжатие без сжатия выполняется так же быстро, как и папка, это удовлетворит мои потребности просто отлично. – BlueSpud

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

0

Время оригинального вопроса может быть случайным. Оказывается, что в будущем подход Find/Load ресурса, который я предложил, не будет для нас ни возможностью (код, который я использовал ранее, идет межплатформенным), поэтому я придумал решение, которое также может работа для вас. Полный код - это немного, чтобы опубликовать его как ответ SO (но см. Мой комментарий), хотя вы, возможно, можете быстро приготовить свою собственную версию.

В принципе, я написал утилиту, которая просто принимает базовое имя для выходных файлов, как argv[1] выходного BASENAME»), и argv[2...(argc-1)] являются входными файлами. Я открываю output-base-name.cpp и output-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. Нет дополнительной зависимости от другой сторонней библиотеки для поиска/извлечения данных файла (при условии, что вы не откатываете свою собственную zip-библиотеку, которая будет работать еще больше)
  3. Все действия по разрешению и поиску выполняются для вы - адреса для каждого байтового массива уже будут разрешены компоновщиком, если вставлять данные в статическую библиотеку или исполняемый файл или загрузчиком ОС, если общая библиотека или DLL
  4. Вы знаете, что данные будут существовать или ваш двоичный файл не может работать (не в случае с подходом zip lib или даже Find/LoadResource в Windows)
  5. Данные немного недоступны (поэтому безопаснее с) Joe User, по сравнению с zip-файлом
  6. Должно быть быстрее, чем почтовый или Windows-ресурс, из-за предварительного разрешения адресов данных во время процесса загрузки для приложения
  7. Он также может использоваться для любой формы относительно статических данных, которые вы хотите отправить (или сделать доступным) ваше приложение - просто файлы пакета в общую/динамическую библиотеку с генератором и использовать сгенерированные экспортированные функции доступа. Вы даже можете создавать обновленные или полностью новые пакеты данных позже (после компиляции/времени отправки) и загружать во время выполнения с помощью опций конфигурации.
  8. Он будет работать в старых компиляторов C++ при необходимости (или, без создания каких-либо пространства имен или класса обертки, даже набившие оскомину-C)

Это только пример подхода, который я использовал, но охватывает все основы, поэтому, если решение скорее, чем позже (опять же, см. комментарий) вам лучше, этого может быть достаточно (вы хотите, чтобы диапазон проверки значений в функциях «получить» - по крайней мере, в отладочных сборках , возможно, использовать какие-либо контейнеры вместо использования массива struct c-style и т. д.).

+0

Комментарий к комментарию, указанному в ответе (часть 1): Хотя полный источник не отправлен в ответ (длина + другие причины обсуждаются в мета-почте [здесь] (http://meta.stackoverflow.com/questions/278616/ предоставление-a-follow-up-link-for-an-so-answer)), я почти закончил с полной реализацией, которая будет выпущена как с открытым исходным кодом. Я выйду из города на несколько дней, но я буду убирать, дополнять и добавлять больше возможностей своей быстрой и грязной/доказательной концепции и размещать ее в своем блоге, когда вернусь. – frasnian

+0

Последующая часть 2 (слишком длинная для одного): Когда я отправлю ее, я удалю этот комментарий и добавлю ссылку на исходное местоположение в ответе, так что если кто-то интересуется полным источником, просто «любимым» «исходный вопрос и вкладка« Избранное »в вашем профиле будут выделены, когда я опубликую ссылку (вероятно, через неделю или около того). – frasnian

Смежные вопросы