Как сделать прямоугольный треугольник в си

Обновлено: 02.07.2024

Решение

Как сказал другой, вам нужно изменить:

Я не верю, что ваша программа будет работать правильно.
Используйте вложенные циклы для вывода треугольника следующим образом:

Это даст вам вывод:

Если вы хотите изменить форму треугольника (поместите угол 90 градусов в другом углу, все, что вам нужно сделать, это изменить условия в циклах for.

Вот еще один пример с углом в другом положении:

Я уверен, что вы поняли идею сейчас … Просто поиграйте с изменением условий в циклах for, пока не получите желаемый результат.

Уроки программирования, алгоритмы, статьи, исходники, примеры программ и полезные советы

Исходный код: треугольник Паскаля на Си.

С формулами и и определением треугольника Паскаля можете ознакомиться вот в этой статье.

Для начала не забываем подключить все нужные библиотеки:

Нам понадобятся следующие библиотеки:

  • – отвечает за выделение памяти и контроль процесса компиляции (стандартная, наравне с “stdafx.h”).
  • – отвечает за создание и вывод консоли.
  • – отвечает за работу со строками.
  • – отвечает за локализацию. Благодаря ей мы сможем писать в консоли на русском языке.

Ниже мы объявляем функцию – подпрограмму. В нашем случае эта функция будет считать факториалы:

long – обозначение того, что у нашей функции будет тип данных long int, то есть будет принимать числа от -2 147 483 648 до 2 147 483 647.

factorial – это имя нашей функции. Оно может быть любым.

(int) – означает, что в функцию будут поступать переменные типа int.

Теперь, чтобы подключить русскую локализацию, пишем в функции main:

Затем объявляем некоторые целочисленные переменные, которые понадобятся нам впоследствии:

Далее пишем следующее:

Первой строкой мы выводим на консоль текст с просьбой ввести число.

Во второй строке мы считываем то, что написал нам пользователь. %i означает, что введённое пользователем число будет целочисленным (формата int). &n- это переменная с именем n, в которую мы запишем полученные данные.

Теперь оформляем наш код так, чтобы при выводе у нас получился треугольник, например, вот такой:

Ты всю жизнь ощущал, что мир не в порядке. Странная мысль, но её не отогнать. Она — как заноза в мозгу. Она сводит с ума, не дает покоя. Это и привело тебя ко мне… Примешь синюю таблетку — и сказке конец. Ты проснешься в своей постели и поверишь, что это был сон. Примешь красную таблетку — войдешь в страну чудес. Я покажу тебе, насколько глубока библиотека SFML кроличья нора.

Круги

Предлагаю для начала потренироваться на простых геометрических фигурах типа Михаила круга. В этом деле большую помощь нам окажет класс CircleShape:

конструктор данного класса принимает в качестве параметра радиус нашей будущей фигуры (например, circle(50.f) );

закрасить фигуру можно с помощью метода setFillColor() , который очень похож на уже знакомый нам метод window.clear() ;

ну и для отображения круга в окне используется метод window.draw() .

Результат выполнения программы:


Наша фигура может иметь контур. Для его создания используется метод setOutlineThickness(), а для цвета контура — setOutlineColor():

Результат выполнения программы:


Как уже знаем из предыдущего урока, при закрашивании фигур или фона можно еще указать значение прозрачности. Например, строкой setOutlineColor(Color(80, 220, 50, 150)) мы устанавливаем 150 в качестве значения прозрачности контура:


А теперь с помощью строки setOutlineColor(Color(80, 220, 50, 50)) мы установим 50 в качестве значения прозрачности контура:


Вы уже наверняка заметили, что наш круг выходит за границы окна, а это не совсем хорошо. Нужно его немного подвинуть, а поможет нам в этом метод move():

Результат выполнения программы:


Регулярные полигоны

-Welcome to the real world!

Отлично! Сейчас мы рассмотрим, как нарисовать и другие фигуры. Теперь ты готов узнать истину. Она заключается в том, что, на самом деле, ложки не существует, Нео твой круг — это немножко не круг, а многоугольник. Да-да, самый обычный многоугольник с большИм количеством вершин. Всё дело в том, что у конструктора класса CircleShape есть еще и второй параметр (помимо радиуса), который отвечает за количество вершин у создаваемой фигуры, и он по умолчанию равен 30 . Именно при значениях близких к 30, многоугольник становится мало отличимым от круга. В то же время, задавая этот параметр самостоятельно, мы можем получить абсолютно другие геометрические элементы. Не трудно догадаться, что 3 вершины — это треугольник, 4 вершины — квадрат, 5 вершин — пятиугольник, ну а 8 вершин — восьмиугольник (октагон).

Ниже приведен полный код матрицы программы, которая наглядно покажет создание данных фигур:

OpenGL 3 позволяет довольно легко делать сложные вещи, однако вывод простейшего треугольника может показаться немного сложной задачей.

Если программа "падает" при запуске, то скорее всего это потому, что вы запускаете ее из неправильной директории. Внимательно прочитайте первый урок, чтобы узнать как настроить Visual Studio.

Мы не хотим сейчас углубляться в детали, но вам необходимо создать Vertex Array Object и установить его текущим:

Сделайте это после создания окна (т.е. после создания контекста OpenGL) и до любого другого вызова OpenGL.

Если вы хотите узнать больше о VAO, то здесь есть несколько уроков, но это не так важно сейчас.

Треугольник задается тремя точками. Когда мы говорим о точках в 3D графике, мы используем слово вершина/vertex (вершины/vertices во множественном числе). Каждая вершина имеет 3 координаты: X, Y, Z. Вы можете представить эти координаты так:

  • X находится справа
  • Y находится вверху
  • Z выходит из вашей спины назад. Z указывает именно назад, а не вперед.

Чтобы лучше понять это используйте правило правой руки:

  • X - это ваш большой палец, направленный вправо
  • Y - это ваш указательный палец, направленный вверх
  • Z - это ваш средний палец, направленный на вас, а не от вас.

Заметьте, что вы можете свободно перемещать вашу руку в пространстве и оси X, Y, Z будут передвигаться также, но подробнее об этом мы поговорим позже.

Итак, все что нам нужно - это 3 точки в трехмерном пространстве, чтобы создать треугольник:

Первая вершина имеет координаты (-1, -1, 0). Это означает, что пока мы не используем какие-либо трансформации вершина будет отображаться на экране в точке (-1, -1). Центр экрана имеет координаты (0, 0), ось X направлена вправо, а ось Y вверх, что показано на изображении:

screenCoordinates

Это то, что встроено в вашу видео карту и то, что вы не можете изменить, поэтому точка с координатами (-1, -1) будет находиться в левом-нижнем углу экрана, точка (1, -1) в правом нижнем, а точка (0, 1) будет находиться посередине по горизонтали и вверху по вертикали. Таким образом наш треугольник заполнит экран.

Следующим шагом будет передача данных о нашем треугольнике в OpenGL. Для этого мы создаем буфер:

Сейчас нам необходимо сделать это только 1 раз.

Теперь, в главном цикле, где до этого мы ничего не выводили, наконец можно вывести треугольник :

Если у вас карта NVidia, то уже сейчас вы можете видеть результат (для других карт продолжайте читать):

triangle_no_shader

Наконец мы вывели наш скучный белый треугольник. Чтобы пойти дальше и раскрасить его в красный нам понадобится нечто, что называется “шейдеры”.

Компиляция шейдеров

В простейшей возможной конфигурации нам понадобится два шейдера. Один из них называется Вершинным и выполняется для каждой вершины, а другой называется Фрагментным и выполняется для каждого фрагмента. А так как мы включили 4х сглаживание (см. первый урок), то для каждого пикселя мы имеем 4 фрагмента.

В OpenGL шейдеры программируются на языке GLSL (GL Shader Language). В отличие от C или Java, GLSL компилируется во время выполнения программы, поэтому каждый новый запуск приложения будет сопровождаться перекомпиляцией шейдеров.

Эти два шейдера как правило находятся в разных файлах. В этом примере мы имеем SimpleFragmentShader.fragmentshader и SimpleVertexShader.vertexshader. Расширение файлов не имеет значения и может быть любым, к примеру .txt или .glsl.

Итак, вот код. Сейчас вам не обязательно углубляться в понимание шейдеров и так как этот код выполняется всего 1 раз за время исполнения программы, то комментариев в коде будет достаточно. Эта функция будет использована во всех уроках и находится в отдельном файле common/loadShader.cpp . Обратите внимание на то, что также как и с буферами мы не имеем прямого доступа к шейдерам. Мы лишь имеем Идентификатор, который указывает на шейдер, а все остальное скрыто внутри драйвера.

Наш Вершинный шейдер

Итак, давайте напишем наш первый вершинный шейдер.

Первая строка в нем говорит компилятору, что мы будем использовать синтаксис OpenGL 3.

Вторая строка объявляет входные данные:

Остановимся подробнее на этом моменте:

  • “vec3″ - это вектор с тремя компонентами в GLSL. Это похоже на glm::vec3, который мы использовали для описания треугольника. Главное помнить, что если мы используем 3х компонентные векторы в C++, то мы должны использовать 3х компонентные векторы в GLSL.
  • “layout(location = 0)” указывает на буфер из которого мы будем получать атрибут vertexPosition_modelspace. Каждая вершина может иметь несколько атрибутов, такие как: позиция, один или несколько цветов, текстурные координаты и другие. OpenGL на данном этапе ничего не знает о цвете и все, что он “видит” - это vec3, т. е. вектор с тремя компонентами. Мы же в свою очередь указываем, каким входным данным соответствует какой буфер. Для этого мы устанавливаем параметр location в такое же значение, которое мы использовали в качестве первого параметра в glVertexAttribPointer. Вообще, здесь не обязательно будет 0, здесь может быть и 12 и любое другое, но не большее чем glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &v), а также важно чтобы число в location было таким же, как и в glVertexAttribPointer.
  • “vertexPosition_modelspace” будет содержать позицию вершины для каждого прохода вертексного шейдера. Название может быть любым.
  • Ключевое слово “in” означает, что этот атрибут является входными данными. Также существует слово “out”, которое указывает соответственно на выходные данные.

Функция, которая будет вызываться для каждого шейдера называется “main”, также как и в C:

Наша главная функция будет просто устанавливать позицию вершины в ту, которая получена из буфера. Соответственно, если мы передадим значение (1, 1), то вершина будет отображена в правом верхнем углу экрана, а в следующем уроке мы рассмотрим более интересные вычисления.

gl_Position - одна из нескольких встроенных в GLSL переменных. В данном случае мы просто присваиваем ей полученное из буфера значение. Все остальное не является обязательным и будет рассмотрено в Уроке 4.

Наш Фрагментный шейдер

Для нашего первого фрагментного шейдера мы сделаем очень простую вещь - установим цвет каждого фрагмента в красный. (Не забудьте, у нас будет 4 фрагмента на каждый пиксель, так как мы используем 4х сглаживание):

И да, вы правы, vec3(1, 0, 0) соответствует красному цвету. Это потому, что на экране компьютера каждый цвет представляется триплетом из Красного, Зеленого и Синего. Таким образом (1, 0, 0) показывает, что цвет является полностью красным, без зеленого и синего.

Перед главным циклом вызываем нашу функцию LoadShaders:

Теперь внутри главного цикла первым делом мы будем очищать экран. Строка приведенная ниже будет заполнять экран темно-синим цветом, так как перед главным циклом мы указываем именно его glClearColor(0.0f, 0.0f, 0.4f, 0.0f):

И теперь мы сообщаем OpenGL, что хотим использовать именно наш шейдер:

… и наконец получаем наш красный треугольник:

red_triangle

В следующем уроке вы узнаете о трансформациях, т.е. узнаете как установить камеру, как перемещать объекты и т.д. Увидимся :)

Читайте также: