1. Пользоваться форумом на планшетах и телефонах стало удобнее благодаря Tapatalk

Помогите прочитать позиции vertex

Тема в разделе "MAXScript", создана пользователем Фигли, 8 сен 2013.

Модераторы: Savin Denis
  1. Фигли

    Фигли Пользователь сайта

    С нами с:
    20.01.2012
    Сообщения:
    23
    Симпатии:
    0
    Баллы:
    2
    Насколько мне известно и встречалась запись позиций в файл (бинарный или текстовый) это три числа с плавающей запятой(точкой). В большинстве случаев это три 32-ух битних числа или 12 байт. В этом же файле для записи позиций используется 8 байт. Пример из нескольких строк:
    AFF8EFF77A530100 B92AF34D 00800080 8F4E2200 02010000 FC698380 FFFFFFFF 6A10B780 7A510A80
    1AF829FB19540100 27183853 00800080 AC2E2500 01000200 FE707D80 FFFFFFFF 720DB580 78570780
    CDF7A5FEBB4F0100 519383E9 00800080 96492000 01000200 7275FD80 FFFFFFFF 017B7280 8F027780

    3034 <0000101111011010>: 40 bytes

    D3DVERTEXELEMENT9[] =
    {
    {0, 0x00, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
    {0, 0x08, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
    {0, 0x0C, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
    {0, 0x10, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0},
    {0, 0x14, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES, 0},
    {0, 0x18, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
    {0, 0x1C, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
    {0, 0x20, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_FOG, 0},
    {0, 0x24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0},
    };
    Из файла мне нужно извлечь позицию вертекса, текстурные координаты, весы (BLENDWEIGHT) и к какой кости привязано. Единственное что понятно, как читать, это BLENDWEIGHT 8F4E2200 - 8F 4E 22 00 тут просто, каждый байт делим на 255. результат от 0 до 1. К какой кости привязано, уже не понятно.
    02010000 это не значит, что 2 1 0 0, костей больше ста, а цифры чередуются в пределах 6 (в данном файле)
    Но вопрос дня, как же всё таки записана позиция?
    AFF8 EFF7 7A53 0100 если предположить, что тут три числа Float16, а 0100 это какое-то техническое и не понятно для чего число, получается вот что:
    -0.124512, -8156.0, 51808.0 (фигня получается), если читать байты в другом порядке:
    -38368.0, -32496.0, 59.8125 (снова фигня)
    Пробовал читать как обычное число и делить его на 32767, числа получаются красивые, но не верные)
    Как ещё можно попробовать прочитать, чтобы получить правильные координаты vertex?
    Судя по скелету (его то я вытащил и построил), в данной модели высота около 3 метров, ширина максимум 1.3

    P.S.
    Для чтения чисел с половинной точностью написал функцию на Maxscript.
    Формула взята отсюда - http://www.softelectro.ru/ieee754.html
    -- функция, HEX число в кавычках HalfToFloat "AFE8" (младший разряд справа)
    fn HalfToFloat hex =
    (
    dec = bit.HexAsInt hex
    Sign = 0
    if (bit.get dec 16) == true then Sign = 1
    Expon = 0
    for bits=11 to 15 do if (bit.get dec bits) == true then Expon = bit.flip Expon (bits-10)
    Mant = 0
    for bits=1 to 10 do if (bit.get dec bits) == true then Mant = bit.flip Mant bits
    return (-1.0)^Sign * 2.0^(Expon - 15.0) * (1.0 + Mant/2.0^10)
    )
    Может в скрипте косяк, но я проверял не один раз, всё вроде верно.
     
  2. Black Sphinx

    Black Sphinx Знаток

    С нами с:
    05.09.2003
    Сообщения:
    234
    Симпатии:
    1
    Баллы:
    29
    В функции преобразования HalfToFloat есть маленькая ошибка.
    Так вроде корректнее:
    Код:
    fn HalfToFloat2 hexStr = (
    	local bin = bit.HexAsInt hexStr
    	local s, m, ex
    	
    	if bit.get bin 16 then s = -1 else s = 1
    	
    	ex = bit.and (bit.shift bin -10) 0x1f
    	
    	if ex == 0 then (
    		m = (bit.and bin 0x3ff) / 1024.0
    		ex = -14
    	)
    	else (
    		m = 1.0 + (bit.and bin 0x3ff) / 1024.0
    		ex = ex - 0xf
    	)
    	
    	return s * m * 2.0 ^ ex
    ) 
    
    Там ещё есть случай, когда все 5 бит экспоненты установлены в 1: дают NaN и бесконечность. Но в этом контексте это, думаю, несущественно.
    http://en.wikipedia.org/wiki/Half-precision_floating-point_format
     
  3. Фигли

    Фигли Пользователь сайта

    С нами с:
    20.01.2012
    Сообщения:
    23
    Симпатии:
    0
    Баллы:
    2
    Про NaN, бесконечность, 0 и -0 в курсе, но в этом случае действительно неважно. Мне бы понять, КАК записаны позиции, и прочее.
    Интересное решение, спасибо, пригодится.
    З.Ы. Добавлял условия
    if Expon == 31 and Mant != 0 then return "NaN"
    if Expon == 31 and Mant == 0 then return #NaN
    if Expon > 0 and Expon < 31 then return (-1.0)^Sign * 2.0^(Expon - 15.0) * (1.0 + Mant/2.0^10)
    if Expon == 0 and Mant != 0 then return (-1.0)^Sign * 2.0^(Expon - 14.0) * (0.0 + Mant/2.0^10)
    if Expon == 0 and Mant == 0 then return 0
    Но это ничего не меняет.
     
  4. Black Sphinx

    Black Sphinx Знаток

    С нами с:
    05.09.2003
    Сообщения:
    234
    Симпатии:
    1
    Баллы:
    29
    Я не спец в D3D, поэтому могу только предполагать...

    1. http://msdn.microsoft.com/en-us/library/windows/desktop/bb172534(v=vs.85).aspx
    2. http://msdn.microsoft.com/en-us/library/windows/desktop/bb172533(v=vs.85).aspx
    Думаю, что тебе надо копать в направлении вышеприведённых ссылок.
     
  5. Фигли

    Фигли Пользователь сайта

    С нами с:
    20.01.2012
    Сообщения:
    23
    Симпатии:
    0
    Баллы:
    2
    Был я в библиотеке мелкомягких, точней и там тоже был)
    Ну нашёл выражение наиболее подходящее:
    D3DDECLTYPE_FLOAT16_4
    Four-component, 16-bit, floating point expanded to (value, value, value, value).
    А толку то, во всех бинарниках, что мне попадались, позиции всегда записывались просто - три 32 битных Float. Тут же вроде очевидно, что три 16 битных и 1 (или 256, смотря как читать), а на деле... читай первый пост.
     
  6. Black Sphinx

    Black Sphinx Знаток

    С нами с:
    05.09.2003
    Сообщения:
    234
    Симпатии:
    1
    Баллы:
    29
    Угу... Читаю первый пост:
    Далее см. пост #4, сначала п.2, а затем п.1.

    В данных у тебя короткое целое со знаком, причём похоже первым идёт младший байт, а потом старший (т.е. последние два байта - это 1). А вот как преобразуется целые в диапазон от -1 до 1 - это вопрос. Можно предположить, что, например, так:
    Код:
    fn conv arg = (
    	num = arg as Integer
    	if bit.get num 16 then s = -1 else s = 1
    	num = bit.and num 0x7fff
    	res = num / (0x7fff as float) * s
    	return res
    )
    Точность получается порядка 3e-5.
    Если отконвертить твои данные из #1 по POSITION, получится:
    что в общем похоже на правду - значения по осям для трёх точек идут с небольшим разбросом.
     
  7. Фигли

    Фигли Пользователь сайта

    С нами с:
    20.01.2012
    Сообщения:
    23
    Симпатии:
    0
    Баллы:
    2
    Если перевести AFF8 как его читает из бинарного файла Readshort -1873/32767 = -0.0571612 (а ведь пробовал же так, но видимо напутал с разрядами, старший - младший).
    [0.0571594,-0.0630188,0.652161], [0.0617065,-0.0378113,0.657013], [0.0640564,-0.0105896,0.622894]... и тд (по х менял знак)
    Меш получился, но раза в три меньше, относительно скелета.

    Black Sphinx, сегодня уже мозг взрывается, попробую завтра, выглядит заманчиво)
     
  8. Фигли

    Фигли Пользователь сайта

    С нами с:
    20.01.2012
    Сообщения:
    23
    Симпатии:
    0
    Баллы:
    2
    Black Sphinx
    Не-а, меш похож на бесформенный куб становится)
    Это обычные Short числа:
    [1873, -2065, 21370]
    [2022, -1239, 21529]
    [2099, -347, 20411]
    Ищу коэффициент на который надо делить. У разных групп моделей разный.
     
Модераторы: Savin Denis

Поделиться этой страницей