Форум: "Игры";
Текущий архив: 2008.01.13;
Скачать: [xml.tar.bz2];
ВнизПолусфера на поверхности сферы (OpenGL) Найти похожие ветки
← →
ancara © (2006-11-30 11:59) [40]Дело в том, что порядок хранения цветов в bmp-файле и RGB-текстуре различается : в bmp BGR, а в текстуре RGB, вот она и меняет местами крайние байты..
← →
Creative (2006-11-30 12:03) [41]Пример потрясающий. То, что мне нужно!!!
← →
ancara © (2006-11-30 12:41) [42]Кушай, не обляпайся :))
← →
Creative (2006-11-30 12:46) [43]Уляпаюсь по уши и еще попрошу! :-)
Только у меня чуть позже могут вопросы возникнуть, так что заглядывай, если не трудно.
← →
Creative (2006-11-30 15:13) [44]Скажи, у тебя в DisplayMouseMove X и Y - это координаты курсора?
← →
Creative (2006-11-30 15:19) [45]И еще вопрос: в твоем последнем примере у тебя в процедуре DisplayMouseMove что происходит при нажатии Alt+левая мышь?
← →
ancara © (2006-11-30 16:35) [46]
> в DisplayMouseMove X и Y - это координаты курсора?
так точно
> что происходит при нажатии Alt+левая мышь?
не обращай внимания, это лишнее, я не заметил и забыл удалить. В этом примере раньше на плоскость накладывались две текстуры и одну из них можно было перемещать как раз левой кнопкой с зажатым альтом, а tx и ty как раз были координаты смещения текстуры... короче это не нужно :))
← →
Creative (2006-11-30 16:53) [47]В общем, я перетолмачила твой пример на АПИ и теперь все очень здорово работает. ТЫ мне очень помог, спасибо.
Будем учиться натягивать на шарик текстуру :-)
← →
ancara © (2006-11-30 19:18) [48]
> спасибо
На здоровье! :))
> Будем учиться натягивать на шарик текстуру :-)
Нет ничего проще: в BuildList сферы, после вычислений координат вершин,
ну там где glVertex3fv(@Vec2) и glVertex3fv(@Vec1) вставь такой код:glNormal3fv(@vNorm2);
glTexCoord2f(azi/pi/2, zenNext/pi+0.5);
glVertex3fv(@Vec2);
glNormal3fv(@vNorm1);
glTexCoord2f(azi/pi/2, zen/pi+0.5);
glVertex3fv(@Vec1);
и все, текстурные координаты для вершин заданы, осталось "применить" текстуру к объекту, для этого в рендере, перед вызовом списка glCallList
нужно "забиндить" соответствующую текстуру:glBindTexture(GL_TEXTURE_2D, Tex_1);
Tex_1 - это идентификатор текстуры, там в процедуре InitGL загружается картинка 1.jpg в качестве текстуры с номером Text_1:LoadTexture("1.jpg", Tex_1);
Итого, еще раз:
- в процессе инициализации создается текстура с номером Tex_1 (эта переменная примет некот. значение, мы его у OpenGL попросим);
- содержимое этой текстуры загружается из файла 1.jpg;
- в процессе построения диспл. списка сферы для каждой ее вершины указываются текстурные координаты;
- перед рендерингом сферы, "биндится" (становится текущей) соответствующая текстура;
- в результате рендеринга получаем сферу с натянутой текстурой;
Вопросы? :)
← →
Creative (2006-12-01 10:38) [49]Объяснение отличное, пошла делать. Только переведу LoadTexture на понятный язык. :-)
Скажи, а ечли я хочу сделать например глобус - мне нужна карта мира, вырезанная в виду "апельсиновой корки" или как лучше? (я и сама конечно попробую, просто вдруг у тебя опыт есть)
← →
ancara © (2006-12-01 11:24) [50]нужна карта мира в виде равноугольной проекции Меркатора, т.е. той, на которой и параллели и меридианы параллельны, а полюсами являются верхняя и нижняя строны прямоугольника. Вобщем, вот такая вот: http://img135.imageshack.us/img135/6897/earthdaynq0.jpg
она там правда не очень высокого разрешения, 1024х1024.
← →
Creative (2006-12-01 11:35) [51]Спасибо, мне за глаза хватит.
Кстати, если я внутри этой ветки один примитивный вопрос по VCL задам - не страшно?
← →
ancara © (2006-12-01 11:49) [52]
> не страшно?
:)) Это очень страшно! Через пол-часа придут люди в погонах и предъявят обвинение в умышленном оффтопе в игровой ветке! Не делай этого! Только не это!
← →
Creative (2006-12-01 11:51) [53]Ну смотри, сам напросился. :-)
У меня на форме лежат несколько компонентов. Я делаю обработчик onKeyDown (или onKeyPress, как получится) для клавиш vk_Up/DOWN/LEFT/RIGHT. Но при запуске оказывается, что этот обработчик к жизни не вызывается, а при нажатии на стрелки просто по всем компонентам форму бегает фокус. Как правильно с этим бороться? Я точно помню, что как-то можно, но напрочь забыла - как. :-(
← →
ancara © (2006-12-01 12:07) [54]Понятно, можно поступить так:
на форму положи компонент TApplicationEvents (вкладка Additional),
в ее обработчике события OnMessage помести такой код:if msg.message=WM_KEYDOWN then
begin
if msg.wParam=VK_DOWN then //обработать нажатие клавиши "вниз"
if msg.wParam=VK_UP then //обработать нажатие клавиши "вверх"
//если не хочешь чтоб фокус прыгал по компонентам
//раскоментируй след. строчку
// handled:=true;
end;
← →
Creative (2006-12-01 12:23) [55]Угу, попробую.
У меня еще вопросы по поводу шариков.
У меня есть два разных объекта класса TSphere (написанного по твоему примеру). Соответственно у класса есть метод отрисовки TSphere.Render, выглядящий примерно так:
glPushMatrix;
glTranslatef
glRotatef(Fbeta, 1,0,0);
glRotatef(Falpha, 0,1,0);
glCallList(ListID); // рисование собственно сферы
glPopMatrix;
В обработчике onMouseMove вот такой код:
S1.FAlpha:=Round(S1.FAlpha+(lpPoint.X-pX)*0.5);
S1.FBeta:=Round(S1.FBeta+(lpPoint.Y-pY)*0.5);
S1.Render;
S2.Render;
Я сильно надеялась, что этот код заставляет повернуться только одну сферу, а вторую остаться на месте (ты мне вроде бы так объяснял как крутить разные объекты?). Но при запуске картинка вообще не шевелится. Делаешь углы глобальными переменными - опять все нормально, но по прежнему крутится вся сцена целиком. Где я наглючила? Разве не должны сферы двигаться раздельно? Я где-то неправильно поняла?
← →
Creative (2006-12-01 12:33) [56]Стрелки заработали. Ну, ты понял, что я хочу сказать :-)
← →
ancara © (2006-12-01 12:42) [57]lpPoint - а что это?
а вот насчет кода в OnMouseMove, я что-то затупил, не пойму что там должно получится...
Просто при изменениях свойств одного из объектов сцены нужно вызывать не его рендерер, а рендерер всей сцены, потому что в OpenGL невозможно перерисовать один объект а остальные нет, если уж перерисовывать кадр так всю сцену придется рисовать.
Т.е. в OnMouseMove надо вызвать глобальный рендерер (RenderScene или как там?), а в нем уже:
- подготовка всяких параметров (цвет фона там, cull-инг и пр.)
- настройка света;
- установка положения камеры;
- прочие приблуды;
- перебор всех объектов, подлежащих рендерингу и вызов у них метода Render;
- и наконец SwapBuffers;
← →
Creative (2006-12-01 12:59) [58]
> lpPoint - а что это?
Это переменная типа TPoint, куда складываются координаты курсора. Я пользуюсь GetCursorPos(lpPoint:TPoint).
в OnMouseMove надо вызвать глобальный рендерер (RenderScene или как там?), а в нем уже
а его собственно надо заключать в
PushMatrix;
PopMatrix;
?
cull-инг - а это что?
← →
ancara © (2006-12-01 13:31) [59]
> Я пользуюсь GetCursorPos(lpPoint:TPoint).
Дык в процедуру OnMouseMove и так передаются координаты курсора, они хранятся в переменных X и Y :) Ну результат в принципе такой же будет...
> cull-инг - а это что?
Face culling - это дословно "отбраковка граней", каждый полигон в OpenGL имеет лицевую и обратную стороны, для каждой из них модно установить отдельные свойства (материал, например). Включив куллинг (glEnable(GL_CULL_FACE)) и указав какие именно грани не рисовать (например обратные: glCullFace(GL_BACK)) мы позволим OpenGL расчитывать только лицевые грани, сэкономив таким образом процессорное время. Это может быть полезно в случае с какими-то замкнутыми фигурами, кубиком напрмер, если мы будем смотреть на него только снаружи и он непрозрачный мы никогда не увидим его обратных граней, т.к. они будут обращены внутрь (об этом надо позаботится отдельно), следовательно их незачем рисовать. Ну куллинг я как пример привел, его не обязательно использовать :)..
> а его собственно надо заключать в
> PushMatrix;
> PopMatrix;
Как это сделано у меня:
в глобальном рендере каждый кадр:
- устанавливаю единичную матрицу:glLoadIdentity;
- поворачиваю и смещаю сист.коорд. согласно положению камеры:glRotatef(FCamera.Beta, 1,0,0);
glRotatef(-FCamera.Alpha, 0,1,0);
glTranslatef(-FCamera.Position.X, -FCamera.Position.Y, -FCamera.Position.Z);
- всякая приблуда: SetupLights; //солнышко светит
- делаю рендеринг всех объектов: RenderObjects ... (ну это очень упрощенно :)) )
причем каждый объект перед рендерингом себя:
- сохраняет матрицу: glPushMatrix;
- смещает и крутит сист. координат, согласно своей позиции и ориентации;
- назначает нужный ему материал, ставит куллинг, если надо, включает нужную ему текстуру и т.д., вобщем они у меня все взрослые и самостоятельные...
- рендерит сам себя: glCallList;
- возвращает все как было, чтоб следующий не обиделся: glPopMatrix;
- ну и после того как нарисовали все что хотели : SwapBuffers
← →
ancara © (2006-12-01 13:33) [60]
> для каждой из них модно установить
для каждой из них можно установить
гыгы, гламурный куллинг :)
← →
Creative (2006-12-01 13:41) [61]Где-то я глобально запуталась. Вот смотри - всю систему координат мне крутить не надо. Рендеринг объекта я привела в [55], и там по-моему все, как ты и сказал. В глобальном рендере только и остается, что :
glLoadidentity;
S1.Render;
S2.Render;
Так?
обработчик onMouseMove изменяет углы поворота и расстояние до экрана одного из объектов. И что получается: если я пытаюсь крутить или двигать первый объект - я вообще не вижу, что с ним происходит, хотя он уже по всем ожиданиям должен из экрана выпрыгнуть. А если второй - да, он крутится, но лежащий под ним первый объект не виден. Почему так?
← →
Creative (2006-12-01 13:42) [62]
> для каждой из них можно установитьгыгы, гламурный куллинг
> :)
да, меня сильно озадачило, думаю...ишь ты, у них там еще мода бывает :-))))
← →
ancara © (2006-12-01 13:46) [63]Т.е. первый крутится а второй нет?
Ну тогда давай код рендера и OnMouseMove, будем думать :))
← →
Creative (2006-12-01 14:00) [64]
> Т.е. первый крутится а второй нет?
второй (верхний) крутится, а первого просто не видно, что он там делает.
Рендер объекта:
procedure TSphere.Render;
var
diffuse: array [0..3]of GLfloat;
const
light_pos: array [0..3]of GLfloat = (5.0, 5.0, 5.0, 0.0);
begin
diffuse[0] :=FColor[0];
diffuse[1] :=FColor[1];
diffuse[2] :=FColor[2];
diffuse[3] :=1;
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glPushMatrix;
glTranslatef(0,0,-FDistance);
glRotatef(Fbeta, 1,0,0);
glRotatef(Falpha, 0,1,0);
glLightfv(GL_LIGHT0, GL_POSITION, @light_pos);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, @diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, @diffuse);
glCallList(ListID);
glPopMatrix;
end;
Рендер сцены:
procedure DrawScene;
begin
glLoadidentity;
S1.Render;
S2.Render;
end;
onMouseMove:
begin
GetCursorPos(lpPoint);
if mouse[0] then
begin
S2.FAlpha:=Round(S2.FAlpha+(lpPoint.X-pX)*0.5);
S2.FBeta:=Round(S2.FBeta+(lpPoint.Y-pY)*0.5);
end;
if mouse[1] then
begin
S2.FDistance:=S2.FDistance+(pX-lpPoint.X)*S2.FDistance*0.01;
end;
pX:=lpPoint.X;
pY:=lpPoint.Y;
DrawScene;
end;
{if mouse[0/1] - это переменная, указывающая на то, какая мышь зажата - левая или правая, не обращай внимания, я этот обработчик сама писала, как умела}
и еще такой вопрос6 я все-таки переделываю твой пример и я заметила такую вещь: если Distance поставить в glTranslatef не вместо оси Z, а вместо X, то объект доедет до середины окна и замрет там, больше его не сдвинуть. Почему так?
← →
ancara © (2006-12-01 14:38) [65]
> procedure DrawScene;
> begin
> glLoadidentity;
> S1.Render;
> S2.Render;
> end;
И это фсио? А камеру установить? Она по идее будет находится в точке (0, 0, 0) и смотреть вдоль оси Z в положительном направлении, и S1 будет рисоваться там же... получается так.. может она за камерой просто? А вот S2 можно двигать мышкой по оси Z...
попробуй так:
procedure DrawScene;
begin
glLoadidentity;
glTranslatef(0,0,-5); //это мы камеру сдвигаем "назад" на 5
S1.Render;
S2.Render;
end;
> доедет до середины окна и замрет там, больше его не сдвинуть.
> Почему так?
Потому что у меня FDistance определял расстояние от камеры до ее "цели", точки на кот. она смотрит, оно не должно было быть отрицательным.
И поэтому в моем OnMouseMove былоDistance:=Distance+(pX-X)*Distance*0.01;
т.е. инкремент дистанции уменьшался вместе с самой дистанцией, т.е. чем ближе к нулю, тем медленее она к нему стремится, но видимо из-за недостаточной точности она все же обращалась в ноль и поэтому не отъезжала обратно.
← →
Creative (2006-12-01 14:43) [66]
> И это фсио?
не сочти за труд - говори по-русски :-)
А камеру установить? Она по идее будет находится в точке (0, 0, 0) и смотреть вдоль оси Z в положительном направлении, и S1 будет рисоваться там же... получается так.. может она за камерой просто?
Да нет же. Если заремить отрисовку S2 - то S1 преспокойно будет виден, благо он рисуется на тех же координатах. Я имею в виду, что если я поверну S2 или сдвину его назад - я не увижу S1, лежащий за ним, как будто его и нет вовсе.
glTranslatef(0,0,-5); //это мы камеру сдвигаем "назад" на 5
да от же самое, только издали :-(
← →
Creative (2006-12-01 14:43) [67]
> И это фсио?
не сочти за труд - говори по-русски :-)
А камеру установить? Она по идее будет находится в точке (0, 0, 0) и смотреть вдоль оси Z в положительном направлении, и S1 будет рисоваться там же... получается так.. может она за камерой просто?
Да нет же. Если заремить отрисовку S2 - то S1 преспокойно будет виден, благо он рисуется на тех же координатах. Я имею в виду, что если я поверну S2 или сдвину его назад - я не увижу S1, лежащий за ним, как будто его и нет вовсе.
glTranslatef(0,0,-5); //это мы камеру сдвигаем "назад" на 5
да от же самое, только издали :-(
← →
ancara © (2006-12-01 14:50) [68]
> сдвину его назад - я не увижу S1, лежащий за ним, как будто
> его и нет вовсе.
А куда ж он девается-то? Может они вместе уезжают?
А попробуй заремить S2 и кнопки понажимать - S1 двигается? Хотя с чего ему двигаться...
А FDistance, FAlpha и FBeta это точно поля класса, может глоб. переменные?
← →
Creative (2006-12-01 14:54) [69]
> А куда ж он девается-то? Может они вместе уезжают?
С какой стати ему уезжать? Его то коодинаты не изменяются.
А попробуй заремить S2 и кнопки понажимать - S1 двигается? Хотя с чего ему двигаться...
Совершенно верно - никуда он не девается.
А FDistance, FAlpha и FBeta это точно поля класса, может глоб. переменные?
Абсолютно точно.
← →
ancara © (2006-12-01 14:59) [70]ну не знаю тогда... попробуй дебаггером посмотреть FDistances обеих сфер когда ты их двигаешь...
← →
Creative (2006-12-01 15:00) [71]До меня кажется начало доходить!!!! Опытным путем я выяснила, что всему виной была строчка
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
стоящая в рендере объекта. По моему она просто аккуратно вытирала первый объект и спокойно на чистом листе рисовала второй.
← →
Creative (2006-12-01 15:01) [72]просто в твоем примере она стояла в RenderScene. ну я и взяла ее :-)
как дура...
← →
ancara © (2006-12-01 15:13) [73]
> аккуратно вытирала первый объект
ну это конечно зря :)) ее ж надо было перед началом формирования кадра вызвать один раз, и все :))
> как дура
нуну, не надо так себя :)) самокритика хороша, когда в меру :))
← →
Creative (2006-12-01 15:23) [74]Как здорово все получилось!
Ну, до следующего косяка :-)
← →
ancara © (2006-12-01 15:29) [75]
> до следующего косяка :-)
<затягиваясь> Угу, позовешь если что...
← →
Creative (2006-12-01 15:31) [76]
> <затягиваясь>
Я не эту гадость имела в виду :-(
Но позвать - позову
← →
Creative (2006-12-01 15:49) [77]Еще кстати вопрос:
1. я использую дисплейный список.
2. внутри списка я использую поле объекта F.
3. я создаю два объекта с разными значениями поля - F1 и F2.
4. в конструкторе у меня стоит BuildList (F: real - переменная, которая будет принимать в себя значение поля создаваемого объекта)
5. в рендере дисплейный список вызывается glCallList(ListID).
Проблема вот какая: glCallList(ListID) - это ведь уже стандартная процедура, к ней не убавишь, не прибавишь, и получается, что она вызывает список в том виде, в котором он был заполнен для _последнего объекта_.
Я правильно поняла, что именно поэтому все объекты рисуются одинаково (с точки зрения тех переменных, которые находятся внутри BuildList)?
← →
Creative (2006-12-01 15:50) [78]Это же глупо - создавать два идентичных дисплейных списка просто потому, что они различаются на одну цифру?
← →
Creative (2006-12-01 15:52) [79]И еще: мне только что пришло в голову: а почему не написать просто процедуру, например DrawSphere и не вызывать в рендере объекта именно ее, а не Список? В чем принципиальное отличие Списка от процедуры?
← →
ancara © (2006-12-01 16:15) [80]
> Это же глупо - создавать два идентичных дисплейных списка
> просто потому, что они различаются на одну цифру?
Нет, гораздо глупее пересобирать один и тот же список для разных объектов :)) Для каждого объекта нужно выделить отдельный персональный список :))
> В чем принципиальное отличие Списка от процедуры?
ну если рендер сделать просто в процедуре то, очевидно, там будут содержаться такие команды:
glVertex(x,y,z);
glNormal(x,y,z);
и т.д.,
т.е. мы будем по-очереди, каждую вершину с ее координатами, нормалями, текстрными координатами и пр. загонять в видеокарту.
А она, в свою очередь, при получении очередного полигона, почти мгновенно его расчитает (нарисует) и будет ждать, пока мы подготовим следующий и пропихнем его по медленной AGP (PCI-E) шине.
И так каждый кадр, даже если ничего не поменялось, мы опять будем гнать те же данные снова и снова, в итоге FPS -> к нулю..
Когда мы используем список, а точнее его собираем (glNewList и так далее..)
мы проделываем те же операции, т.е. гоним данные по шине в видеокарту, но мы делаем это только один раз (в идеальном случае), а в момент рендеринга мы просто вызываем соответствующий дисплейный список (glCallList), т.е. мы всего лишь просим видеокарту отрисовать некий объект (совокупность полигонов) который уже находится в ней, и это происходит значительно быстрее.
Страницы: 1 2 3 вся ветка
Форум: "Игры";
Текущий архив: 2008.01.13;
Скачать: [xml.tar.bz2];
Память: 0.64 MB
Время: 0.012 c