Вход

Просмотр полной версии : Эффект линзы



newart
08.06.2008, 13:16
Имею исходник из IRIS но если им рисовать сразу на экран, то линза получается вогнутая, а хотелось бы обратного эффекта.

Что для этого нужно поменять?

R = 64 (радиус)
M = 30 (выпуклость)
S = SQR(R*R - M*M)

FOR Y = -R TO R Step 4
FOR X = -R TO R Step 4
IF (X*X + Y*Y) >= S*S THEN
A = X
B = Y

Else
Z = SQR(R*R - X*X - Y*Y)
A = INT(X * M / Z)
B = INT(Y * M / Z)
PLOT(A,B)

END If

NEXT X
NEXT Y

Крутые кодеры, вплоть до Sairoos советуют слудущее " где z рассчитывается плюсы на минусы поменяй, либо у самого знак, либо под корнем плюсы на минусы". Забавно, но результат от этих изменений не меняется. :(

SAM style
08.06.2008, 13:42
попробуй
Z = M - SQR (R*R - X*X - Y*Y)

rasmer
08.06.2008, 13:50
слава - кинь результат что получается...

Vitamin
08.06.2008, 14:01
Везде, где есть вычисления вида A=SQR(B*B-C*C) (там где вычисляется Z, С*С=X*X+Y*Y), формулу надо поправить на: A=2(B-C)-SQR(B*B-C*C)

Правда подозреваю, что надо не везде, а только во втором вычислении.

Vladimir Kladov
08.06.2008, 15:21
Если на фотографию Луны или на 3D-модель Луны посмотреть, то кратеры тоже часто кажутся не вогнутыми, а выпуклыми. Вогнутые они или выпуклые, решает мозг, на основе привычных представлений о мире. Линза и кратер таковыми не являются, видимо.

Добавлено через 1 минуту
Да, улыбнуться забыл: :)

newart
08.06.2008, 22:13
Везде, где есть вычисления вида A=SQR(B*B-C*C) (там где вычисляется Z, С*С=X*X+Y*Y), формулу надо поправить на: A=2(B-C)-SQR(B*B-C*C)

Правда подозреваю, что надо не везде, а только во втором вычислении.
Мысль интересная, только с ABC ты меня совсем запутал. :)

Z = SQR(R*R - X*X - Y*Y)

заменть на?

Z = 2*(X-Y) - SQR(X*X - Y*Y) ?

получается что то вроде 4-х угольной звезды, но не линза.

Raider
08.06.2008, 23:08
:smile:

Vitamin
09.06.2008, 10:19
Мысль интересная, только с ABC ты меня совсем запутал.
Блин, на самом деле там все гораздо проще должно быть. X & Y у тебя пробегают по какой картинке? Источник или приемник? Если источник, то это по идее неправильно, ибо на приемнике получаем множество перерисованных и пропущенных пикселов. Отсюда мораль, что алгоритм должен работать следующим образом:

// src, dst- графические контексты источника и приемника соотвецно
// координаты относительно центра "линзы"
// шаг 1 ибо идем по пикселам контекста назначения (хоть сдвигами биты заполнять, не суть важно)
FOR Y = -R TO R
FOR X = -R TO R
// если вышли за пределы "линзы" (она круглая, но сканируем квадратом), то просто копируем точку как есть
// т.е. координаты совпадают
IF (X*X + Y*Y) >= S*S THEN
A = X
B = Y
Else
// иначе вычисляем координаты точки на источнике, которая проецируется на текущую точку приемника
Z = SQR(R*R - X*X - Y*Y)
A = INT(X * M / Z)
B = INT(Y * M / Z)
END If
// просто проверка на установленный бит
If (Point(src, A, B))
PLOT(dst, X,Y)
endif
NEXT X
NEXT Y

newart
09.06.2008, 14:52
Нее, все куда проще, мне нужно получить подобие линзы прямо на экране, из точек.

Вариант из IRIS работает не так, как раз потому что не рисует сразу на экран, а создает таблицу для приемника.

Vitamin
09.06.2008, 15:13
Нее, все куда проще, мне нужно получить подобие линзы прямо на экране, из точек.
Я про это и говорю. Сканирование должно быть линейным на приемнике, а не на источнике. Иначе будет хреново. А рисовать результат сразу или заполнять таблицу- не суть важно.

newart
09.06.2008, 16:18
Я про это и говорю. Сканирование должно быть линейным на приемнике, а не на источнике. Иначе будет хреново. А рисовать результат сразу или заполнять таблицу- не суть важно.
Да блин, нет у меня приемника, то есть иcточника, поэтому и сканировать ничего не надо. :)
Надо просто нарисовать векторную линзу, с дискретностью 8 пикселей.

Добавлено через 8 минут
Вот еще один вариант, в отличае от IRIS линза получается выпуклой, но с артефактами, углы квадрата превращаемого в линзу как бы подгибаются и накладываются на линзу. :(

size = 2 (коффициент "скукоживания" квадрата в сферу)
for i = -radius To radius Step -8
for j = -radius To radius Step -8

s = Sin(M_PI/2 + (M_PI/2) / (radius*size) * sqr(i*i+j*j))
x = i*s
y = j*s
plot(x,y)

Next j
Next i

Raider
11.06.2008, 00:55
Слава, ты, Слава.. Всё-таки не снёс я глядеть на твои мучения,
заставил ты меня оторваться от проекта, взять ручку и карандаш и подумать 3 минуты. Ну тут же всё банально... Я же тебе всё объяснил в ICQ тот раз. Перечитал бы лучше что я тебе писал.



#define RADIUS 256
#define GRIDSTEP 8
#define CURVATURE 0.75

void mesh()
{
int x, y;
float distance, z;

for (y = -RADIUS; y < RADIUS - 1; y += GRIDSTEP)
{
for (x = -RADIUS; x < RADIUS - 1; x += GRIDSTEP)
{
distance = sqrtf(x*x + y*y);

if (distance < RADIUS)
{
z = 1.0 - CURVATURE + CURVATURE * distance/RADIUS;
plot(x/z + RADIUS, y/z + RADIUS);
}
else
plot(x + RADIUS, y + RADIUS);
}
}
}


Добавлено через 15 минут
Работает это так


#define RADIUS 256 // радиус гипотетической сферы
#define GRIDSTEP 8 // шаг сетки
#define CURVATURE 0.75 // кривизна поверхности 0..1

// функиця рассчета искривления поверхности
void mesh()
{
int x, y; // пара целочисл. переменных, координаты
float distance, z; // пара переменных с плав. точкой

// цикл по Y
// цикл нач.значние условие выр.выпол. после кажд итерации
for (y = -RADIUS; y < RADIUS - 1; y += GRIDSTEP)
{

// вложенный цикл по X
// цикл нач.значние условие выр. выпол. после кажд итерации
for (x = -RADIUS; x < RADIUS - 1; x += GRIDSTEP)
{
// расстояние от центра до текущй точки
// вычисляется по теореме пифагора:
// гипотенуза=корень(катет1^2 + катет2^2)
// это расстояние никогда не будет больше RADIUS
distance = sqrtf(x*x + y*y);

// смотрим, лежит ли текущая точка внутри круга, круг задан
// радиусом
if (distance < RADIUS)
{
// да, точка внутри круга
// почитаем ее "дистанцию от экрана", при этом заметим, что
// distance изменяется от 0 до RADIUS, таки образом
// выражение distance/RADIUS принимает значения 0...1
z = 1.0 - CURVATURE + CURVATURE * distance/RADIUS;

plot(x/z + RADIUS, y/z + RADIUS); // ставим точку круга(линзы)
}
else
plot(x + RADIUS, y + RADIUS); // эта точка вне круга
}
}
}

newart
11.06.2008, 03:03
Слава, ты, Слава.. Всё-таки не снёс я глядеть на твои мучения,
заставил ты меня оторваться от проекта, взять ручку и карандаш и подумать 3 минуты. Ну тут же всё банально... Я же тебе всё объяснил в ICQ тот раз. Перечитал бы лучше что я тебе писал.
Красота!!
Спасибо Леха!!
С меня причитается!! :)

Добавлено через 36 минут
Чуток поигрался и заметил что линза, как будто линейная.
То есть не полусфера, а скорее конус.

Вот картинка: (step X = 1, step Y = 8, справа то что выдает выше приведенный мной вариант кода):

Raider
11.06.2008, 16:55
Чуток поигрался и заметил что линза, как будто линейная.
То есть не полусфера, а скорее конус.

Это перспектива. Правильная перспектива дает такие специфические искажения кривизны (вдали искажения меньше, вблизи больше). Так и должно быть в реальности. Называется "рыбий глаз" или профессионально - дисторсия. Перспективный вид параллельных прямых должен быть знаком каждому фотографу.
Если ты читал Я.И.Перельман "Занимательная физика", то должен помнить оттуда вид моста так, как его видят рыбы. Первое изображение своей криволинейностью напоминает фотографию моста в этой книге.

А во втором, твоем случае это просто вид, без перспективы. Кривизна дуг постоянная.

p.s.
"Занимательную физику" Перельмана советую найти тебе и каждому, зачитаешься. А рисунок оттуда, что самое смешное был сделан, как мне кажется, Робертом Вудом из-под воды, специальной камерой. Про Вуда есть отдельная книга - она тоже читается затая дыхание.

newart
11.06.2008, 17:46
А во втором, твоем случае это просто вид, без перспективы. Кривизна дуг постоянная.
Суть в том что второй вариант выглядит привлекательнее и естественннее, он действительно похож на сферу.

Добавлено через 10 минут
Помнишь шарик из Illusion с робокопом? Там никакого рыбьего глаза. Интересно как они расчитывали.

Raider
11.06.2008, 22:24
Суть в том что второй вариант выглядит привлекательнее и естественннее, он действительно похож на сферу.

Добавлено через 10 минут
Помнишь шарик из Illusion с робокопом? Там никакого рыбьего глаза. Интересно как они расчитывали.


Попробуй просто уменьшить фактор кривизны, параметр CURVATURE поставь поменьше.. Чем меньше будет фактор кривизны, тем меньше перспективное искажение. Там у тебя на левой картинке кривизна настолько велика, что это не полусфера, это как бы такая эллиптическая скругленная палочка у тебя из экрана торчит. Вот ты её за "конус" и принял.. Curvature(кривизна) - это и есть, по сути, насколько сфера "вытягивается" из экрана. Ставь меньше.

Ну и вопрос в том, что для тебя является естественным.. Мало ли.. Естественным как? Для глаза привыкшему к спектруму? Как правило, ты в эффектах всегда видишь перед собой просто параллельную проекцию.
А если под "естественным" понимать математически/визуальное правильное построение, как оно Должно Быть На Самом Деле и как оно выглядит в природе - то тогда обрати свой взор на вариант с правильным рассчетом перспективы.

Насчет перспективы ещё. C перспективой все становится хорошо видно в динамике. Если например перспективная коррекция не производится/неверна/симулируется - то когда все это начинает как-то произвольно вращаться/смещаться/наклоняться дефект "Fake perspective" мгновенно вылазит.

newart
11.06.2008, 22:56
Попробуй просто уменьшить фактор кривизны, параметр CURVATURE поставь поменьше.. Чем меньше будет фактор кривизны, тем меньше перспективное искажение. Там у тебя на левой картинке кривизна настолько велика, что это не полусфера, это как бы такая эллиптическая скругленная палочка у тебя из экрана торчит. Вот ты её за "конус" и принял.. Curvature(кривизна) - это и есть, по сути, насколько сфера "вытягивается" из экрана. Ставь меньше.
Конусообразность сохраняется при любых параметрах. В примере выше curvature=0.75


Ну и вопрос в том, что для тебя является естественным.. Мало ли.. Естественным как?
Например шарик из Illusion (http://trd.speccy.cz/demoz/enl96/ILLUSION.ZIP). Вариант на картинке справа вполне примелемлем (если бы не глюк с углами).

Raider
01.08.2008, 00:20
Newart, посмотри как выглядит мост снятый Вудом. Вот ссылка на книгу, фотографии в конце:
http://lib.ru/MEMUARY/WOOD/robertwood.txt