Но задние предметы или которые стоят сбоку мы не должны проецировать. Также мы не должны проецировать предменты, которые стоят слишком далеко. Всё это за нас делает Open. GL. Проба пера. Скачиваем библиотеку Open.
TK. Запускаем файл, распаковываем библиотеку. Создаём проект, добавляем ссылку на файл Open. TK. dll. А так как, мы будем использовать контрол GLControl, на котором будет отображаться Кубик Рубика, добавляем ещё и ссылку на Open. TK. GLControl. dll.
CSS, не работает ссылка на.css документ через java script. Запрещено размещать ссылки на коды программ, расположенные на других . Мне давно хотелось разобраться с 3D фигурами в Css и сделать вращающийся куб. Спеки прочитаны, можно приступать (почитать про . Кубик будет в 3D и его можно будет вращать мышкой. Я буду использовать OpenGL, внутри обычной GUI-программы. Точка обзора вращается вокруг Кубика Рубика по сфере, поэтому удобно оперировать .
С помощью анимации на и 3D преобразований можно делать просто. Сегодня, в качестве примера, мы создадим вращающийся куб.
Open. TK требует также ссылку на System. Drawing. dll, поэтому ещё раз входим в интерфейс добавления ссылки, и выбираем вкладочку . Net и ищем System.
Drawing, и добавляем. Я буду использовать Open. GL, внутри обычной GUI- программы. Поэтому в режиме конструктора кликаем правой кнопкой мыши по панели инструментов, и выбираем “Выбрать элементы”, переходим на вкладку “Компоненты . NET Framework” и выбираем файл Open. TK. GLControl. dll. В списке появится новый элемент GLControl, ставим напротив него галочку.
На панели инструментов появится новый элемент GLControl. Переносим его на форму и растягиваем на всю её форму. Элемент GLControl имеет событие Load, оно срабатывает, когда этот элемент загрузился.(Щелкнем по нему, чтобы заполнить тело обработчика, появится метод gl. Control. 1. О режимах будет сказано чуть позже.
GL. Clear(Clear. Buffer. Mask. Color. Buffer. Bit . Буфер Цвета.
С каждым пикселем на экране связано значение цвета, которое записывается в буфере цвета. Вызов GL. Clear(Clear.
Buffer. Mask. Color. Buffer. Bit) зальет в нашем случае окно цветом Sky. Blue (смотри выше).
Depth. Buffer. Он же Z- Buffer. Буфер глубины. Дело в том, что две точки в 3.
D пространстве могут проецироваться на одну точку на экране. Нужно чтобы, ближняя точка перекрывала дальнюю. Для этого нужно вычислять “глубину” точки (величины обратнопорциональной расстоянию от камеры до точки) и записывать её значение в буффер (пискель такой- то, глубина такая- то), если же очередная точка проецируется на тот же пиксель, то надо сравнивать “глубину” новой точки с записанной Depth- буффере. Если новая точка находится “менее глубоко” (более ближе к камере), то её проекция должна перекрыть существующую, иначе оставляем всё как есть.
В начале отрисовки кубика мы должны очистить Depth- Buffer. Matrix. 4 modelview = Matrix. Look. At(7. 0, 7. GL. Matrix. Mode(Matrix. Vivaldi Шрифт Русский. Mode. Modelview).
GL. Load. Matrix(ref modelview). Здесь мы задаем нашу камеру в точке (3.
Ориентация такая, что ось OY направлена вверх. Если мы сделаем. Matrix. Matrix. 4. Look. At(3. То мы будем смотреть на кубик под углом, как если бы наклонили голову на 4. Далее собственно рисуются сам кубик: сначала грани красным цветом, потом черным — ребра. Потом вызывается командаgl. Control. 1. Swap.
Buffers(). Дело в том, что по умолчанию Open. GL в Open. TK double- buffer: каждый буффер (Color. Buffer, Depth. Buffer и другие, которые я не упомянул) дублируется. Когда мы рисуем изображение, мы используем одни буферы. А в это время на экране отображается изображение, которое получено из других буферов.
Командой gl. Control. Swap. Buffers(); мы выводим на экран изображение, используя буферы, в которых мы его рисовали. Кстати, если очисть буфер цвета только в первый раз bool b = true. Control. 1. А потом сворачивать/разворачивать окно.
То цвет фона будет меняться с голубого на черный. Эти координаты называются объектными.
Каждый объект может быть определен в своих объектных координатах. Чтобы построить мир из разных 3d объектов, которые стоят относительно друг друга в разных положениях. Matrix). Тогда мы получим новые координаты каждого объекта в новом общем мировом пространстве. В то же время мы можем смотреть на мир объектов с разных сторон, мы можем перевернуть камеру, мы можем приближаться к объекту и удаляться от него. Умножая координаты объектов (координаты в мировом пространстве) на соответствующие матрицы видового преобразования (view Matrix), мы получаем видовые коордианты каждого объекта. В Open. GL матрица модельного преобразования (model Matrix) совмещена с матрицей видового преобразования (view Matrix) в одну (model. View Matrix). Деля каждую координату (x, y, z) на 4 величину .
Чтобы перейти в режим управления матрицей проецирования мы должны вызвать функцию GL. Matrix. Mode с параметром Matrix. Mode. Projection: GL. Matrix. Mode(Matrix. Mode. Projection); А чтобы перейти в режим управления матрицей модельно- видового преобразования мы должны вызвать функцию GL.
Matrix. Mode с параметром Matrix. Mode. Modelvew: GL. Matrix. Mode(Matrix. Mode. Model. View); Добавьте в gl. Control. 1. Заполните её следующим кодом: private void gl.
Control. 1. Опишу ключевые моменты. Ключевые структуры данных. Кубик Рубика, ребро которого состоит из 3- х кубиков состоит из 2. В процессе вращения грани КР, надо знать какие маленькие кубики вращать (ведь в грани могут оказаться разные кубики), также после очередного поворота грани КР, надо проверить, а не собрался ли кубик.
Для отслеживания позиций кубиков, я применил массив positions: int. Когда мы повернули грань на один оборот (9. Следующий класс служет для описания кубика в пространстве. XYZ. . После заканчивания вращения, я обнуляю эти углы, перемещаю кубики на новые позиции (то есть соответствующим образом меняю массив position), и вращаю кубики вокруг своей оси (покажу, что под этим имею в виду). Пользователь видит только само вращение. Объект класса angle. XYZ есть у каждого кубика и хранится в коллекции angles: List< angle.
XYZ> angles = new List< angle. XYZ> (). 3) Каждый кубик содержит 8 угловых точек. Зная эти точки, нарисовать кубик не проблема. Координаты точек хранятся в 3- х мерном массиве edges. Чтобы перенос и поворот координат проходили с помощью только операций умножения (а не сложение и умножение), я использую матрицы 1x. Использование матриц 4x. Тем самым за одну операцию умножения можно сделать две вещи: и перенос, и умножение.
Есть ещё словарь intersect. Но можно было и не заводить отдельный класс, а просто обойтись двумерным массивом: intersect.
Об определении плоскости, по стрелкам которой щелкнули мышкой, будет написано позже. Важный объект моего vp класса View. Point. View. Point vp = new View. Point(). который хранит значение координаты точки обзора Кубика Рубика, дело в том, что при вращении мышкой Кубика Рубика, у меня на самом деле меняется положение точки обзора, а кубик стоит на месте. Класс View. Point нужен для получения ближайшей оси к точке зрения (метод get. Nearest. Axis). Это нужно, чтобы определить, на какой грани показывать стрелочки, то есть какие части вращать, при щелчке мыши.
Точка обзора вращается вокруг Кубика Рубика по сфере, поэтому удобно оперировать углом относительно оси OX (угол . Также у этого класса есть свойства- геттеры, по которым можно определить не верх ногами находится ли камера, с какой стороны определенной оси мы смотрим на кубик (к примеру со стороны положительных значений X, или со стороны отрицательных значений Z). Это нужно для того, чтобы правильно определять в какие стороны крутить грани Кубика Рубика. Сам Кубик Рубика расположен так, чтобы его центр был в центре начала координат.
Перейдём к коду. Я буду описывать только ключевые моменты, иначе будет очень долго. Я и так себя уже Львом Николаевичем чувствую.
Метод Render. Сам Кубик Рубика я хочу, нарисовать так, чтобы его центр совпадал с центром начала координат, поэтому перейдя в режим матрицы Model.