В описалове формата есть неточность!
параметр FaceType никак неможет быть больше 1го байта, а у тебя написано 4!
Вот я тут написал класс C++ для чтения *.LOD [Тестировалось в VC6++]
+ пример работы в комплекте.
http://www.gamedev.ru/download/?id=4030
Сгружай его! и размещай у себя на сайте =)
Там-же уже реализована возможность чтения цветовых значений и индексов =) без доработки форамта и задействуя только reserv!
Возможнсоть чтения нереализованных на сегодня, цветовых массивов и индексов. (формат для этого изменять ненужно, все основано на возможностях существующего) параметр: reserv в блоке MSH1 теперь именуюется как ColorsCnt отвечает за количество цветовых значений. >0 значит следом грузятся цвета размером 4байта каждый. (INTEGER [целое]) это 32бита или 4 байта - RGBA от 0..255 каждый. Получится: Colors имеет размер ColorsCnt*4 байт Если ColorsCnt>0 то в конце каждой фейс группы добавляется параметр ColorsIndexCnt - отвечающий за количество индексов и ColorsIndex - сами цветовые индексы.
так-что уже сейчас можно менять цвет и прозрачность каждой вершины в обьекте =)
Ты если менять формат будеш незабудь меня оповестить =)
Вот новая версия класса C++ для чтения файлов *.LOD отличается от предыдущей, только тем что имеет заточку для работы вместе с OPENGL
http://www.gamedev.ru/download/file.php?id=4035
+ Пример OpenGL Rendera вершин.
2 капитан
Вот еще один серезный косяк в описамнии твоего формата нашел!!!
Притом косяк офегительный! тебе придется исправлять его не в описании, а в самом редакторе. Или может предется переправлять формат.
Сморим параметр PntBnAssocCnt
Количество ассоциаций точек/вершин с костями скелета. Должно быть кратно MeshVertexCnt. На данный момент может быть равно либо нулю либо MeshVertexCnt.
Смотрим PntBnAssoc
Размерность данного пармаетра вычисляется как
= PntBnAssocCnt, если PntBnAssocCnt<255
= PntBnAssocCnt*2, если PntBnAssocCnt>=255
Размерность этого массива зависит от количества костей. Если костей меньше 255, то на кость отводится по байту, если больше ( что крайне редко ), то по два байта.
В примере Тринити. У нас 569 Вершин, PntBnAssocCnt также равен 569!
Исходя из этого у нас получится что PntBnAssoc имеет размер 569 * 2! и равен 1138 байт! Если мы столько прочитаем то у нас все пойдет на перекосяк!
Насамом деле в данном случае размерность у нас недолжна умножатся на 2! и размер PntBnAssoc должен быть равен PntBnAssocCnt.
Поэтому как оказалось из-за этого косяка мой класс неможет вытянуть статичные мэши и фейсы из тринити.
Проблема пока решается тем что мы можем насильно неучитывать в моем классе количество костей, и всегда умножаем на 1.
Если опять же взглянуть описание PntBnAssoc то там говорится о необходимости знать количество костей! которое нам неизвестно и к PntBnAssocCnt неотносится.
Где по твоему брать это количество костей чтобы вычислить длинну PntBnAssoc?
Предложение о том что для этого надо считать блок SKL1 отклоняю!
Поскольку это неправильное построение конструкций блоков.
Блоки должны быть независимыми!
И если блок ненужен или неизвестен то он пропускается, как у тебя заложено изначально, но заставляя читать этот блок ты в корне рубиш всю концепцию построения.
Вообщем, исправляй! незнаю как ты будеш выкручиватся... у меня идей нет, тебе только если подкорень изменить блок MSH1.
И после PntBnAssocCnt добавть что-нить типа PntBnoneCnt
чтобы можно было вычислить всетаки самостоятельно размер PntBnAssoc
И потом в новой версии редактора загружать правельный MSH1
А от старой версии отказатся навсегда! т.к. формат нераспространился. А примеры из неправельного формата можно будет переконвертировать запросто.
Посему давай!
Неправельный формат неподдерживай ! а то глядиш он тоже распространится потом будеш мучится сам!
PS. Ну и что что загруженая статическая тринити без блока скелетки отображается как размазаная по стенке! Главное она должна грузится независимо!
Придумал еще один вариант:
PntBnAssocCnt обявить что теперь в нем хронится количество костей, если 0 то нету,
и потом размер PntBnAssoc вычислять как VertexCnt * 1(если PntBnAssocCnt<256) или *2 (если PntBnAssocCnt>255)
И еще у тебя есть мелкий недочет по вычислению индексов который тоже может привести к ошибке!
у тебя в описании написано что проверка делается при >=65535 и при >=255! Неверно!!!
должно быть при >65535 и при >255 !т.к. размерность байта у нас не от 0..254, а от 0..255 (в сумме 256, а не 255 вариантов!) так быть недолжно исправляй.
PPS Всеравно альтернатив загрузичков *.LOD нету кроме твоего для делфи и моего для С++.
DDMZ
Привет! Спасибо за ошибки.
> параметр FaceType никак неможет быть больше 1го байта, а у тебя написано 4!
Сейчас поправлю.
Вот так вот будет правильно, если по исходнику ULODkaUtilsA1.pas :
FaceType 4 0
FaceMode 1 4
> Размерность данного пармаетра вычисляется как
> = PntBnAssocCnt, если PntBnAssocCnt<255
> = PntBnAssocCnt*2, если PntBnAssocCnt>=255
Да. Там надо так, конечно:
= PntBnAssocCnt, если BonesCnt<255
= PntBnAssocCnt*2, если BonesCnt>=255
В зависимости от количества костей.
> Где по твоему брать это количество костей чтобы вычислить длинну PntBnAssoc?
> Предложение о том что для этого надо считать блок SKL1 отклоняю!
> И если блок ненужен или неизвестен то он пропускается
Пропускаются данные блока SKL1 . А заголовок блока нельзя не прочитать, потому, что в нём указан размер данных. И не прочитав будет непонятно сколько байт пропускать.
Блок SKL1 должен идти перед блоком MSL1. А количество костей как раз содержится в заголовке блока SKL1 в параметре Count. Данные же его ( SKL1 ), в принципе можно не читать.
> должно быть при >65535 и при >255 !т.к. размерность байта у нас не от 0..254, а от 0..255 (в сумме 256, а не 255 вариантов!) так быть недолжно исправляй.
Но это же не принципиально. Имеет значение только для моделей у которых ровно 255 или ровно 65535 вершин и не единой меньше или больше. То есть случай крайне редкий. В первом случае выигрыш составит 255 байт. А второй не может случиться практически никогда, разве что специально. :)
Кроме того можно считать, что 255 и 65535 - это специальные резервные числа на будущее.
papean
Спасибо за иконки! :)
Только, понимаешь, хотелось бы, чтобы было сразу видно, что это именно редактор а не просто лодка ( корабль, парусник ).
DDMZ
> http://www.gamedev.ru/download/?id=4030
> Сгружай его! и размещай у себя на сайте =)
Загрузчик разместил.
> так-что уже сейчас можно менять цвет и прозрачность каждой вершины в обьекте =)
Это можно записать, но нельзя отобразить. В GLScene нету для этого стандартных средств. Что говорит о невостребованности. Это обычно делают или через двоёное текстурирование или лайтмэпами, которые, кстати, реализовать очень не просто.
12345
> Автор не забрасывай проект!
Постараюсь. По мере возможностей. :)
2 Капитан
> Блок SKL1 должен идти перед блоком MSL1. А количество костей как раз содержится в заголовке блока SKL1 в параметре Count. Данные же его ( SKL1 ), в принципе можно не читать.
А вдруг блок SKL1 будет после MSL1 ?
Но не в том дело, дело в другом, то что мы потеряем независимость блоков в данном случае.
Например разработал ты SKL2 и все... SKL2!=SKL1 , неизвестный блок пропустится, что это был за блок мы незнаем, и MSH мы загрузить в таком случае абсолютно несможем. Тебе для этого услучая придется записывать 2 блока SKL1 и SKL2 . Вот к чему приводит твоя зависимость от блоков. При том что возможность независимости заложена изначально. Лучше уж продублировать значение в MSH1 чем мучатся с зависимостью всех блоков друг от друга. Такого! ты сам понимаеш быть недолжно =)
Нужно учитывать что блок SKL1 будет неизвестным для программы. (точнее при разработке нужно учитывать что все блоки могут быть неизвестны (исключение состовялет связка SKL1 и ANM1)
А загрузили мы заголовок SKL1, если он нам неизвестен, зачем нам брать данные из него?) Мы ведь будто-бы незнаем что хранит в себе неизвестный заголовок.
>Это обычно делают или через двоёное текстурирование или лайтмэпами, которые, кстати, реализовать очень не просто.
Я недумаю что просто реализовать разуную прозрачность включая разнуй цветность, например для 1000 вершин ;)
Ну то что нету этой возможности в GLScene это конечно минус... (чего там правда нет команды типа glColorsPointer - этож ведь стандарт?). Но есть возможность со стороны загрузить туда =) вдруг кто сделает в своем редакторе поддержку твоего формата. [А редактор сторонний возмет и SKL1 с ANM1 и запишет в конец после MSH1... все кранты? надо будет пропустить MSH1 загрузить SKL1 потом вернутся. А откуда мы знаем что снами едет SKL1 ?]
Кстати! Таким образом мы сможем снять обязательность следования сначала SKL1 потом ANM1, поскольку раз есть ANM1 значит гдето есть SKL1 который надо найти. или надо было вообще ANM встроить в SKL как фейсы встроены в MSH.
FaceType 4 0
FaceMode 1 4
Поправил =) вот новая версия + есть возможность загружать меш если есть скелет с костями в количестве не более 255.
http://www.gamedev.ru/download/?id=4052
>И еще у тебя есть мелкий недочет по вычислению индексов который тоже может привести к ошибке!
>у тебя в описании написано что проверка делается при >=65535 и при >=255! Неверно!!![i]
Я ошибся =) с индексами все в порядке в этом плане, у тебя такое неправельное сравнение только! для вычисления PntBnAssoc , Хотя все идет к тому что MSH1 нужно переработать и починить, заодно и переделать на ">" , вместо ">=".
В коде у тебя: if aBonesCount < 255 (Правильно будет: if aBonesCount <= 255 )
Дальше для индексов у тебя идет правильно <=High(Byte)
Т.к. 255 костей еще нужно посторатся сделать, то можно сегодня изменить не в ущерб будующего. Что это дает? это дает возможность без напряга создавать данный массив на стороне. Поскольку в других форматах подобные кости хранятся правильно. И из правильного формата имеющего 255 костей, если мы сконвертим такой файл то твоя прога его считать несможет, хоть это и редкое исключение, но твоя прога несможет читать такие файлы. Это нужно будет специально заглючить конвертр =) чтобы в данном случае Конвертр сделал НЕ копию буфера, который он бы просто скинул в файл, ему придется конвертировать данный буфер! только из-за одного данного случая, это уже говорит о невозможности встраивания твоего формата в другие редакторы, поскольку у них сделано правильно. Например Blender.
Мы будем видеть разные размеры буферов для этого варианта не странно ли?)
Но тут у тебя проскачила идея приспособить кудато эти 255 и 65535 . как? куда?
PS Лучше заранее избавлятся от всех недостатков формата на заре его формирования! чем потом поддерживать их в будующем. разве нет?)
DDMZ
> А вдруг блок SKL1 будет после MSL1 ?
Значит это ошибка.
Программа его пишет перед.
> продублировать значение в MSH1 чем мучатся с зависимостью всех блоков друг от друга
И начать мучиться с тем, чтобы случайно не оказалось, что в одном месте один и тот же параметр имеет одно значение, а в другом совершенно другое. И как это отследить потом и согласовать.
> В коде у тебя: if aBonesCount < 255 (Правильно будет: if aBonesCount <= 255 )
А это не ошибка, а так и было задумано.
> Но тут у тебя проскачила идея приспособить кудато эти 255 и 65535 . как? куда?
Например, если 255, то значит дальше идёт какая то дополнительной информацией о данной конкретной точке.
> Лучше заранее избавлятся от всех недостатков формата на заре его формирования! чем потом поддерживать их в будующем. разве нет?)
Есть и другие принципы:
Работает - не трогай.
Можно не менять - не меняй.
Не распыляйся по мелочам.
Думай о главном.
и т. д. и т. п.
> вот новая версия
Давай я поставлю ссылку на твою страничку, где бы был этот файл, чтобы ты мог более оперативно его обновлять?
А то у меня много срочных дел, и часто просто не до ЛОДки.
>Например, если 255 то значит дальше идёт какая то дополнительной информацией
А это не ошибка, а так и было задумано.
т.е. Костей неможет быть больше чем 255? (поскольку количество более 255 вычислить в таком случае будет накладно). тогда это очень хорошо, Можно обходится без блока SKL1. И не утруждать себя вычислением. (что сейчас и сделано)
Этоже хорошо! все упрощается!
Тогда в принципе ничего уже и немешает писать отдельно блоки SKL1 с ANM1 после MSL.
одно значение, а в другом совершенно другое
Я надеюсь ты не изменяеш никаих данных структуры в момент сохранения данных. Если нет, то:
как это отследить потом и согласовать
У тебя уже есть несколько подобных значений, ты ведь както их отслеживаеш и согласуеш =)
- Count в SKL1 (который должен постоянно держатся в памяти, и отслеживатся другими блоками)
- MaterialsCount и count в MAT1
- MSH1 count
Ведь они согласованы. Все согласуется в момент сохранения, когда непроисходит никаких изменений в сохраняемой структуре.
И если они будут какимто образом отличатся(изменятся) при сохранении то это будет брак! т.е. они уже небудут соответсвовать формату. И их загрузить неудастся вообще. А кто будет делать такое сохранение которое несоответсвует формату, это получится всеравно что грузить 3DS как BMP =)
Значит это ошибка.
Программа его пишет перед.
Я поглядел, и если неошибаюсь твой загрузчик грузит все блоки ЖЕСТКО последовательно и непонимает разбросанных в разных местах блоков, например даже если простой INF1 будет в конце. Поэтому понятны возможные привязки блоков друг за другом. Все дело в твоем загрузчике?)
Или мне уже совсем плохо поддается пониманию поскалевский код....
Вообщем я как мог постарался помочь тебе исправить явные недостатки. Ну нехочеш с ними боротся, ладно, пусть остаются. =(
This ERROR is Supported! =)))
This verision it's Old Bag compatible
PS. Да чета я сильно разошелся с попытками убеждения, надо бы мне останавливатся... пока еще никого не допек =)
2 Капитан
как это отследить потом и согласовать
В том то и дело что это некрасиво делать согласование чегота с чемто.
В моем загрузчике этого нет, я полностью доверяю описанию твоего формата.
Ты сравниваеш MaterialsCount и count в MAT1 которые по описанию должны быть равны? но как они в момент сохранения могут быть неравны если они берутся из одной переменной?)
Да даже если чудом какимто count в MAT1 будет отличатся от MaterialsCount это еруда! для нас ключевую роль при загрузке играет только MaterialsCount, а там с ходится это или нет можно и непроверять. Главное чтобы все это загрузилось в итоге как надо!
Версия 1.30
Добавились Smooth groups ( Группы сглаживания ). Бетта версия.
Описание как ими пользоваться: http://lodka3d.narod.ru/help.html#SmoothingGroups
Некоторые изменения в формате LOD-файлов: http://lodka3d.narod.ru/lodfileformat.html
В связи с этим немного изменились загрузчики моделей для GLScene.
Прошу потестить. Возможно будут некоторые глюки.
DDMZ
> т.е. Костей неможет быть больше чем 255?
Может.
> Я поглядел, и если неошибаюсь твой загрузчик грузит все блоки ЖЕСТКО последовательно
Нет.
Но перед загрузкой мешей проверяет загружен ли уже скелет через параметр isSkeletonLoaded.
И берёт количество костей из SkelChunk.Count.
> Вообщем я как мог постарался помочь тебе исправить явные недостатки.
Спасибо.
> Ты сравниваеш MaterialsCount и count в MAT1 которые по описанию должны быть равны?
В count он занесён, только для информации. Чтобы место не пустовало.
Можно считать, что там ничего не записано.
Новая версия загрузчика!
http://www.sinor.ru/~ddmz/cc/?LODinCpp
Поддерживается только новый фейс тип 2! (принятый в версии LODKA 1.3)
хех круто ты сделал индексы >256 и >65536 =)
т.е у тебя сейчас при количестве индексов =256 создается массив от 0 до 255 ? (256 элементов в сумме) (C++: делаем new[256] и получаем от 0 до 255)
а то вдруг(я то незнаю, на всякий случай говорю) если у тебя массив от 1 до 256 то индекс со значением 256 станет равным 0, надо в этом случае индекс-1 при сохранении делать.
Вот теперь правильно =) и память удобно под это выделять.
Включил возможность загрузки >255 костей беря значение из SKL1, Под твою ответственность=)
Пришось создать новую переменную и держать ее в классе и перед каждой загрузкой инициализировать, чтобы при загрузке следующего LOD она содержала только верное значение, в рекурсии ...
Тема в архиве.