-
Delphi в отладчике CPU пишет -9.30880643132136E18 В переменной -9.30880643132136e+18
В любом случае переполнение разрядной сетки.
-
У меня это происходит при округлении:
function Round(F: double): int64; asm .NOFRAME
cvtsd2si rax, F end;
-
> dmk © (03.05.18 13:42) [20] > Delphi в отладчике CPU пишет -9.30880643132136E18 > В переменной -9.30880643132136e+18
Славно. А нули-то при этом куда надо рисовать? куда я написал, ведь правда?
> В любом случае переполнение разрядной сетки.
Разрядной сетки чего? какой "разрядной сетки"? Я же уже приводил диапазон для Double, вы почему невнимательно читаете? впрочем, я почитал про "основание" в [14] уу.....
Это называется мантисса, а не основание, и это важно.
-
нда.. вот бы еще понять как приведённый код на asm связан с исходным вопросом...
-
кстати, возвращаемое значение из функции объявлено как int64 это вас не удивляет? 1E+18 не лезет в int64
-
> z := 1.0 + X; > > writeln(z); > > end. > > Выдаёт: > > 1.00000000000000E+0000
совпадает с описанием машинного эпсилона в вики. значит, гуд.
-
телепатирую:
вы вызвали стандартную функцию Round() для числа -9.30880643132136E18 И она рванула "переполнение". Ну так это понятно: ибо диапазон для int64 От -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 т.е. грубо говоря -9.2E+18 до +9.2Е+18
А вы в него пытаетесь запихать -9.3E+18
Оно выходит за границы int64, отсюда и взрыв
Ведь так?
-
> -9.30880643132136e+18 = 0.00000000000000000930880643132136.
Да ну? С какой радости?
-
-
Ну да, неправильно понял из-за разницы в отладочном окне. Там просто E18 написано, а не +. В переменной +18. Учитывая, что тангенс у меня в диапазоне -2Pi..2PI - не ожидал, что число вылезет в обратную сторону после умножения на K.
Это просто масштабирование.
K := (gFactor * Aspect); //Масштаб(%) * соотношение сторон
Это просто графики функций:
//Графики repeat DX := (X * gFactor) + cX; NA := NormalizeAngle(A) * DegToRadD;
sinY := Sin(@NA) * K; cosY := Cos(@NA) * K; tanY := Tan(@NA) * K; cotY := Cot(@NA) * K;
with RT^ do begin FloatPixel(DX, cY + sinY, crLtYellow, 255, Alpha); FloatPixel(DX, cY + cosY, crLtGreen, 255, Alpha); FloatPixel(DX, cY + tanY, crLtBlue, 255, Alpha); FloatPixel(DX, cY + cotY, crLtRed, 255, Alpha); end;
X := (X + StepX); //Шаги в радианах A := (X * RadToDegD); //Угол для вычисления функции until (X > R);
И вот где cY + tanY вылезает Exception.
-
Это просто графики функций: https://yadi.sk/i/Y_w_IWJg3VF9fLПроверял как считаются. Если gFactor > 500% - происходит Exception. А мне надо до 100000%, чтобы отклонения посмотреть. Это свой расчет SinCosTanCot.
-
Извиняшки. Это я дурак. Tan(90°) не определен. Cosec(0°) тоже не определен. Потому и ошибка. Я не обрабатываю эту ситуацию в своей функции ;)
-
Как это всё связано с изначальным вопросом - вот бы понять. Впрочем, не важно.
Что же до приведённого куска кода - очевидно, что ошибок в нём нет, ошибки (если они вообще есть) - где-то в других частях кода. К тому же мы не знаем что за секретная функция FloatPixel и какие значения принимают переменные cY и tanY в момент возникновения проблемы. От нас это зачем-то скрывают, но посочувствовать я готов.
-
Ура, вот всё и разрешилось. А то "не понимаете, не понимаете" :)
-
>что за секретная функция FloatPixel Она не секретная. Просто пиксел распределяется на 4 пиксела и получается сглаженная линия. Удобно функции рисовать. Типа AntiAliasing'а.
procedure FloatPixel(X, Y: double; dColor: TColorRef; dAlpha, dOpacity: byte); var fX, fY, sX, sY: double; x0, y0, x1, y1: integer;
begin //Координата отсчетного пиксела if (X < 0.0) then begin x0 := Trunc(X - 1.0); x1 := (x0 + 1); //Пиксел справа fX := Abs(Frac(X)); //Дробная часть сдвигается в пиксел справа sX := (1.0 - fX); //Остаток в стартовом пикселе end else begin x0 := Trunc(X); x1 := (x0 + 1); //Пиксел справа sX := Frac(X); //Дробная часть сдвигается в пиксел справа fX := (1.0 - sX); //Остаток в стартовом пикселе end;
if (Y < 0.0) then begin y0 := Trunc(Y - 1.0); y1 := (y0 + 1); //Пиксел снизу fY := Abs(Frac(Y)); //Дробная часть сдвигается в пиксел снизу sY := (1.0 - fY); //Остаток в стартовом пикселе end else begin y0 := Trunc(Y); y1 := (y0 + 1); //Пиксел снизу sY := Frac(Y); //Дробная часть сдвигается в пиксел снизу fY := (1.0 - sY); //Остаток в стартовом пикселе end;
//Отсчетный пиксел if FClipRegion.PtInRegion(x0, y0) then FBlendPixel(PAddress32(x0, y0), dColor, dAlpha, Round((fX * fY) * dOpacity)); //Пиксел справа if FClipRegion.PtInRegion(x1, y0) then FBlendPixel(PAddress32(x1, y0), dColor, dAlpha, Round((sX * fY) * dOpacity)); //Пиксел снизу if FClipRegion.PtInRegion(x0, y1) then FBlendPixel(PAddress32(x0, y1), dColor, dAlpha, Round((fX * sY) * dOpacity)); //Пиксел по диагонали справа внизу if FClipRegion.PtInRegion(x1, y1) then FBlendPixel(PAddress32(x1, y1), dColor, dAlpha, Round((sX * sY) * dOpacity)); end;
БлендПиксел тоже не секретный. Смешивает содержимое буфера с цветом. Получается смешанный пиксел.
procedure BlendPixel(dA: QWord; AColor: TColorRef; Alpha, Opacity: byte); var A: word; ADif: word; WR, WG, WB: word;
begin //Прозрачность канала A := (((Alpha + 1) * Opacity) shr 8); //Для исходного пиксела нужно обратное насыщение ADif := (A xor $FF) + 1; //Коррекция на единицу для корректного деления на 256 A := (A + 1);
//Расчет компонентов пиксела наложения WR := TBgrPixel(AColor).r * A; WG := TBgrPixel(AColor).g * A; WB := TBgrPixel(AColor).b * A;
//Смешиваем цвета TBgrPixel(PDWord(dA)^).r := ((TBgrPixel(PDWord(dA)^).r * ADif + WR) shr 8); TBgrPixel(PDWord(dA)^).g := ((TBgrPixel(PDWord(dA)^).g * ADif + WG) shr 8); TBgrPixel(PDWord(dA)^).b := ((TBgrPixel(PDWord(dA)^).b * ADif + WB) shr 8); end;
Есть версия на асме:
procedure BlendPixel(dA: QWord; AColor: TColorRef; Alpha, Opacity: byte); const ShufMask: uint64 = $0100010001000100;
asm .NOFRAME
pxor mm0, mm0 //<- APixel pxor mm1, mm1 //<- AColor movq mm2, ShufMask //Формирование маски умножения
punpcklbw mm0, [dA] //Преобразуем байты в слова psrld mm0, 8 //Преобразование старших бит в младшие
movd mm5, AColor punpcklbw mm1, mm5 //Преобразуем байты в слова psrld mm1, 8 //Преобразование старших бит в младшие
movzx eax, Alpha //Вычислим прозрачность альфа-канала inc eax //Прибавим единицу, чтобы корректно разделить на 256 movzx r8d, Opacity //Компонента прозрачности mul eax, r8d //Умножаем shr ax, 8 //Делим на 256 mov dx, ax xor dx, $FF //<- ADif - величина цвета обратная альфе
inc edx //Прибавим единицу, чтобы корректно разделить на 256 movd mm3, edx pshufb mm3, mm2 //<- mm3: формируем маску разницы ADif
inc eax //Прибавим единицу, чтобы корректно разделить на 256 movd mm4, eax pshufb mm4, mm2 //<- mm2: формируем 64-битную альфа-маску
pmullw mm1, mm4 // AColor * Alpha = lpBR, lpBG, lpBB pmullw mm0, mm3 // APixel * ADif paddusw mm0, mm1 //APixel + AColor psrlw mm0, 8 //(APixel + AColor) div 256
packuswb mm0, mm0 //Транслируем слова в байты movd [dA], mm0 end;
У меня еще куча версий такой фукнции, в том числе и через вектора, но думаю сможете и сами реализовать.
-
ФлоатПикселом удобно Безьешку рисовать. Она же дробная получается.
-
Вот вам сразу бленд-сканлайн:
procedure BlendColorScLineMMX(dA: QWord; dLen: dword; AColor: TColorRef; Alpha, Opacity: byte); const ShufMask: uint64 = $0100010001000100;
asm .NOFRAME
xor r10, r10 mov r10d, dLen
movq mm2, ShufMask //Формирование маски умножения
pxor mm1, mm1 //Очистка старших битов movd mm5, AColor //Цвет наложения punpcklbw mm1, mm5 //Разложим байты в слова 32 -> 64 бита psrld mm1, 8 //Сдвиг вправо для очистки старших бит
movzx eax, Alpha //Вычислим прозрачность альфа-канала inc eax //Прибавим единицу, чтобы корректно разделить на 256 movzx r11d, Opacity //Компонента прозрачности mul eax, r11d //Умножаем shr ax, 8 //Делим на 256 mov dx, ax xor dx, $FF //<- ADif - величина цвета обратная альфе
inc edx //Прибавим единицу, чтобы корректно разделить на 256 movd mm3, edx pshufb mm3, mm2 //<- mm3: формируем маску разницы ADif
inc eax //Прибавим единицу, чтобы корректно разделить на 256 movd mm4, eax pshufb mm4, mm2 //<- mm2: формируем 64-битную альфа-маску
pmullw mm1, mm4 //AColor * Alpha = lpBR, lpBG, lpBB movq mm5, mm1 //Сохраним для повторения
@NextPixel: pxor mm0, mm0 //Очистим для формирования маски следующего пиксела punpcklbw mm0, [dA] //Читаем 32 бита //Транслируем байты в слова psrld mm0, 8 //Сдвиг вправо для очистки старших бит
movq mm1, mm5 //В mm5 сохраненный цвет наложения pmullw mm0, mm3 // APixel * ADif paddusw mm0, mm1 //APixel + AColor psrlw mm0, 8 //mm0 div 256
packuswb mm0, mm0 //Транслируем слова в байты movd [dA], mm0 //Пишем обратно
add dA, 4 dec r10 jnz @NextPixel end;
-
А это супер-секретный PtInRegion:
type PRegion = ^TRegion; TRegion = record private rX: integer; //Позиция слева rY: integer; //Позиция сверху rEX: integer; //Позиция справа rEY: integer; //Позиция снизу rW: integer; //Ширина включая первую точку rH: integer; //Высота включая первую точку end;
function TRegion.PtInRegion(x, y: integer): boolean; begin if (x >= rX) and (x <= rEX) then Result := (y >= rY) and (y <= rEY) else Result := false; end;
-
> dmk ©
а готового всего этого нет? или это практики ради?
-
>а готового всего этого нет? или это практики ради? Готового чего? Если про пиксели, то это я из своего класса подергал. Есть. Много. Почти все на асме. Работает шустро. Тут видео: https://yadi.sk/i/I_NwsFF-3UcVzKЭто 3D-шечка. Движок делаю небольшой.
|