31.05.2015, 11:10 | #11 (permalink) | |
Специалист
Регистрация: 27.08.2008
Адрес: Санкт-Петербург
Сообщений: 27,807
Сказал(а) спасибо: 340
Поблагодарили 583 раз(а) в 208 сообщениях
Репутация: 113184
|
Цитата:
1. Насчет плавного перехода - по-моему, таких сервисов в Паскале не предусмотрено. Только густотой точек. Впрочем, если у Вас есть графпакет, который может работать с экраном высокого разрешения, то это оно и будет. У меня только VGA-мода (640х480). 2. По самой задаче. Начнем с рассеянного света. Как я вижу, задача решается так. а) Рисуем темный (фоновый) круг. б) Вводим две системы сферических координат. Первая (основная) решает задачу, когда солнце светит в направлении "северного полюса", т.е. вдоль оси Z, т.е. θ=0, φ - произвольное. Вторая (повернутая) - для случая, когда солнце светит в направлении θs, φs. Ищем в книжках, на сайтах либо, мобилизуя все знания матричной алгебры, решаем самостоятельно задачу перехода от основной к повернутой системе координат, т.е. задачу преобразования координат θ, φ → θ', φ' для любой точки сферы. в) Методом случайного выбора задаем угол θ в основной системе координат. Фишка в том, что распределение здесь не равномерное, а косинусное. Подскажу, что оно задается функцией θ = arcsin(x), где х - равномерно распределенная случайная величина в интервале 0-1, т.е. значение функции Random без параметров. Также методом случайного выбора задаем φ=Random*2π. На всякий случай, приведу вид функции вычисления арксинуса: Код:
function ArcSin(X:Real):Real; begin if X= 1 then ArcSin:= Pi/2 else if X=-1 then ArcSin:=-Pi/2 else ArcSin:=ArcTan(X/Sqrt(1-X*X)); end; д) В повернутой системе определяем декартовы координаты Y' и Z' (плоскость рисунка) нашей точки. е) В случае выполнения условия (Y')²+(Z')²≤R² ставим красную точку с координатами Y' (по горизонтали) и Z' (по вертикали). ж) Повторяем процедуру, пока не станет красиво. Или до потери пульса. Итак, будем считать, что с рассеянным светом разобрались. Но это всё как раз еще цветочки. Ягодки начнутся, когда мы захотим решить задачу зеркального отражения. Вот тут - совсем ой! Здесь я вижу решение, например, такое: а) Фоном является решение предыдущей задачи. б) Переходим в основную систему координат (солнце светит в направлении Z=0). Задаем в этой системе направление на наблюдателя θн, φн. Забегая вперед, отмечу, что, когда мы повернем систему, это направление изменится - ну да нам-то не всё ли равно? в) Разбиваем верхнюю полусферу на элементы площадью S=R²sin(θ)ΔθΔφ. В двойном цикле проходим их все. г) Для каждого элемента определяем угловые координаты луча, соответствующего отражению, исходя из постулата "угол падения равен углу отражения". Эти координаты составят θr=2θ, φr=φ. д) Определяем угол β между направлением отраженного луча и направлением на наблюдателя (в трехмерном пространстве, не забываем!). е) Заполняем случайным образом элемент поверхности S так: i. Фиксируем полное количество "квантов" N, упавших на каждый элемент поверхности площадью S (для всех элементов это число будет одинаковым). Например, N=1000. Или 10000. Или еще сколько-нибудь. Тогда число точек М для каждого из элементов определится из соотношения M=Round(N(cos²β)²) (в смысле косинуса в четвертой степени). ii. Выбираем для каждой точки углы θр, φр так: θp = θ + Δθ(0.5-Random) φp = φ + Δφ(0.5-Random) iii. Как и в предыдущей задаче, для каждой точки переходим к повернутой системе координат и, как и в том случае, при выполнении условия в пункте е) ставим желтую точку. iiii. Процедуру повторяем М раз. Вот как-то так. Такой вот конгломерат из векторной алгебры, аналитической геометрии, оптики, дизайна и программирования. Где-то на месячишку плотной работы. Дерзайте! |
|
31.05.2015, 11:10 | |
Helpmaster
Member
Регистрация: 08.03.2016
Сообщений: 0
|
Некоторые темы по содержанию очень напоминают вашу тему Погрешности для вычисления объема шара. Численные методы Создание развертки шара Изображение пропадает |
13.06.2015, 00:34 | #14 (permalink) |
Member
Регистрация: 12.01.2015
Сообщений: 71
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 10
|
Мне помогли с решением. Но оно другое и на PascalABC. Но я не совсем понимаю как здесь использована формула. И вообще как идет затемнение, осветление. Может кто знает, подскажите пожалуйста! Просто очень нужно и интересно. Хочу также с кубом сделать.
Код:
program zadacha_4; uses GraphABC; const {window center} xc = 300; yc = 250; {ball} xb = 100; yb = 10; zb = 70; R = 70; {vector sun} sx = -30; sy = -2; sz = -11; type tPoint = record x, y, z: real; end; procedure DrawPixel(x, y: real; R, G, B: integer); begin if R < 0 then R := 0; if G < 0 then G := 0; if (B < 0) then B := 0; if (x > 0) and (y > 0) then SetPixel(round(x), round(y), RGB(R, G, B)); end; function Angle(sx, sy, sz, x, y, z: real): real; var A: real; begin A := 0; if sqrt((sx * sx + sy * sy + sz * sz) * ((xb - x) * (xb - x) + (yb - y) * (yb - y) + (zb - z) * (zb - z))) <> 0 then A := (sx * (xb - x) + sy * (yb - y) + sz * (zb - z)) / sqrt((sx * sx + sy * sy + sz * sz) * ((xb - x) * (xb - x) + (yb - y) * (yb - y) + (zb - z) * (zb - z))); Angle := A; end; function ForeAngle(sx, sy, sz, x, y, z: real): real; var A: real; begin A := 0; if sqrt((sx * sx + sy * sy + sz * sz) * ((xb - x) * (xb - x) + (yb - y) * (yb - y) + (zb - z) * (zb - z))) <> 0 then A := (sx * (xb - x) + sy * (yb - y) + sz * (zb - z)) / sqrt((sx * sx + sy * sy + sz * sz) * ((xb - x) * (xb - x) + (yb - y) * (yb - y) + (zb - z) * (zb - z))); if A > 0 then ForeAngle := A * A * A * A else ForeAngle := -A * A * A * A; end; var i, j, k: integer; shadow: tPoint; begin SetWindowSize(2 * xc, 2 * yc); SetBrushColor(clBlack); SetPenColor(clBlack); Window.Clear(rgb(200, 200, 200)); LockDrawing; for i := xb - R + 1 to xb + R - 1 do for j := round(yb - sqrt(R * R - (i - xb) * (i - xb))) + 1 to round(yb + sqrt(R * R - (i - xb) * (i - xb))) - 1 do for k := round(zb - sqrt(R * R - (i - xb) * (i - xb) - (j - yb) * (j - yb))) to round(zb + sqrt(R * R - (i - xb) * (i - xb) - (j - yb) * (j - yb))) do begin {sun} if sz < 0 then begin shadow.x := (i - (i - sx)) / (1 - k / (k - sz)) + i - sx; shadow.y := (j - (j - sy)) / (1 - k / (k - sz)) + j - sy; end; {point} {shadow.x :=(i-xl)/(1-k/zl)+xl; shadow.y :=(j-yl)/(1-k/zl)+yl; } {DrawPixel(round(shadow.x)+xc,round(shadow.y)+yc,55,55,55);} DrawPixel(round(-(sqrt(3 / 4) * (-shadow.y + shadow.x)) / 1.2 + xc), round(-(0 - (shadow.x + shadow.y) / 2) / 1.2 + yc), 55, 55, 55); end; for i := xb - R + 1 to xb + R - 1 do for j := round(yb - sqrt(R * R - (i - xb) * (i - xb))) + 1 to round(yb + sqrt(R * R - (i - xb) * (i - xb))) - 1 do for k := round(zb - sqrt(R * R - (i - xb) * (i - xb) - (j - yb) * (j - yb))) to round(zb + sqrt(R * R - (i - xb) * (i - xb) - (j - yb) * (j - yb))) do begin {DrawPixel(i+xc,j+yc,255,0,0);} DrawPixel(round(-(sqrt(3 / 4) * (-j + i)) / 1.2 + xc), round(-(k - (i + j) / 2) / 1.2 + yc), round(95 + 100 * Angle(sx, sy, sz, i, j, k) + 60 * ForeAngle(sx, sy, sz, i, j, k)), round(290 * ForeAngle(sx, sy, sz, i, j, k) - 55), round(290 * ForeAngle(sx, sy, sz, i, j, k) - 55)); end; Redraw; end. |
Ads | |
Member
Регистрация: 31.10.2006
Сообщений: 40200
Записей в дневнике: 0
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 55070
|
Метки |
pascal, задача, помощь |
|
|