Изображение тора и цилиндра




Лабораторная работа № 1

 

Вариант 27

по дисциплине “ Компьютерная графика”

 

 

Выполнил ____________________ Ларионов В. С.
студент гр. 33534/4 <подпись>  
     
Преподаватель ____________________ Леонтьева Т. В.
  <подпись>  

Оглавление

1. Задание. 3

2. Реализация. 3

2.1. Изображение конусов. 3

2.2. Поворот конусов на a=90° относительно начала координат вокруг оси X. 4

2.3. Изображение тора и цилиндра. 6

2.4. Поворот тора на a=-45° относительно начала координат вокруг оси Z и масштабирование цилиндра в 2 раза относительно начала координат. 7

3. Код программы.. 8

 

 

Задание

· Изобразить два каркасных конуса высотой 25 и 50 соответственно, основание конуса - окружность с радиусом 10 и центром в точке O (20,20).

· Осуществить поворот конусов на угол a=90° относительно начала координат вокруг оси Х.

· Изобразить тор и цилиндр. Размеры и местоположение примитивов задать самостоятельно.

· Повернуть тор на a=-45° вокруг оси Z относительно начала координат, промасштабировать конус с коэффициентом 2 относительно начала координат

Реализация

Для реализации задачи был создан абстрактный класс Shape3D, который содержит основной функционал для данной лабораторной работы. Shape3D содержит следующий список реализованных методов:

rotateAroundLocalAxis Вращение фигуры относительно ее локальных осей
rotateAroundAttributeAxis Вращение фигуры относительно ее осей координат
scaleRelativeToLocalAxis Масштабирование фигуры относительно ее локальных осей
scaleRelativeToAttributeAxis Масштабирование фигуры относительно осей координат
setCenter Установка / получение координат центра фигуры
setFilling Установка заливки фигуры, либо Wire, либо Solid
setColor Установка цвета фигуры (доступные цвета внутри структуры Color)
drawShape Отрисовка фигуры, для каждой фигуры свое определение метода

Для каждой фигуры переопределяется метод прорисовки drawShape(), в котором используются выбранные ранее параметры отрисовки, цвета.

Изображение конусов

Shape3D<T>::setColor(Shape3D<T>::getColor()); Shape3D<T>::setAction(Action::DRAW); if(Shape3D<T>::getFilling() == WIRE) glutWireCone(radius_, height_, slices_, stacks_); elseglutSolidCone(radius_, height_, slices_, stacks_);

 

На рисунках обозначены оси X, Y, Z. Можно увидеть, что центр фигур находится в точке (20, 20). Для удобства в обозрении фигуры были повернуты на -90 градусов.

2.2. Поворот конусов на a=90° относительно начала координат вокруг оси X

Процедура вращения фигуры относительно начала координат вокруг конкретной оси:

T sinA = sin(angle * M_PI / 180); T cosA = cos(angle * M_PI / 180); std::vector<T> rotation_matrix; switch(axis) { caseX: rotation_matrix = { 1, 0, 0, 0, cosA, -sinA, 0, sinA, cosA }; break; caseY: rotation_matrix = { cosA, 0, sinA, 0, 1, 0, -sinA, 0, cosA }; break; caseZ: rotation_matrix = { cosA, -sinA, 0, sinA, cosA, 0, 0, 0, 1 }; } point3d_t<T> new_center = { rotation_matrix[0] * center_.x + rotation_matrix[1] * center_.y + rotation_matrix[2] * center_.z, rotation_matrix[3] * center_.x + rotation_matrix[4] * center_.y + rotation_matrix[5] * center_.z, rotation_matrix[6] * center_.x + rotation_matrix[7] * center_.y + rotation_matrix[8] * center_.z, }; // Reset rotations to set local axis similar to attribute axis reapplyRotations(true); setCenter(new_center); glRotated(angle, axis == X, axis == Y, axis == Z); // Reapply previous rotations reapplyRotations(false); // Write new rotation to the list rotations_.emplace_back(axis, angle);

 

После поворота можно заметить, что центр фигур на рисунках теперь находится в точке (20, 0, 20), а сами фигуры сменили положение после поворота.

Изображение тора и цилиндра

Отрисовка тора:

Shape3D<T>::setColor(Shape3D<T>::getColor()); Shape3D<T>::setAction(Action::DRAW); if(Shape3D<T>::getFilling() == WIRE) glutWireTorus(inner_radius_, outer_radius_, sides_, rings_); elseglutSolidTorus(inner_radius_, outer_radius_, sides_, rings_);

Отрисовка цилиндра:

Shape3D<T>::setColor(Shape3D<T>::getColor()); Shape3D<T>::setAction(Action::DRAW); if(Shape3D<T>::getFilling() == WIRE) gluQuadricDrawStyle(quadObj_, GLU_LINE); elsegluQuadricDrawStyle(quadObj_, GLU_FILL); // Like GL_POLYGON gluCylinder(quadObj_, bottom_radius_, top_radius_, height_, slices_, stacks_); gluDeleteQuadric(quadObj_);

Для отрисовки тора были выбраны следующие параметры:

· Внутренний радиус = 6, внешний радиус = 10, сторон – 25, колец – 25

Для отрисовки цилиндра были выбраны следующие параметры:

· Нижний радиус – 4, верхний радиус – 4, высота – 30, кол-во подразделений вокруг оси Z – 25, кол-во подразделений по оси Z – 25.

2.4. Поворот тора на a=-45° относительно начала координат вокруг оси Z и масштабирование цилиндра в 2 раза относительно начала координат

Процедура масштабирования:

// reset rotations to set local axis similar to attribute axis reapplyRotations(true); setCenter({center_.x * coeffX, center_.y * coeffY, center_.z * coeffZ}); glScaled(coeffX, coeffY, coeffZ); // reapply rotations reapplyRotations(false);

 

Код программы

 

#include <GL/glut.h> #include "GL/gl.h"
#include <cmath>
#include <stdexcept> #include <cstdarg>
#include <cstdio> #include <vector>
#include <utility> #include <memory>

 

enum Action
{
TRANSLATE,
ROTATE,
SCALE,
SET_COLOR,
SET_FILLING,
DRAW
};

 

enum Axis
{
X,
Y,
Z
};

 

enum Color
{
RED,
BLUE,
YELLOW,
GREEN,
WHITE,
PURPLE,
CYAN,
ORANGE,
VIOLET
};

 

enum Filling
{
SOLID,
WIRE
};

 

template < typename T>
struct point3d_t
{
T x;
T y;
T z;
point3d_t<T> operator +=(const point3d_t<T>& lp);
point3d_t<T> operator -=(const point3d_t<T>& lp);
point3d_t<T> operator *(const T& coeff);
};

template struct point3d_t< float >;
template struct point3d_t< double >;

 

template < typename T>
point3d_t<T> point3d_t<T>:: operator +=(const point3d_t<T>& lp)
{
return { this ->x + lp.x, this ->y + lp.y, this ->z + lp.z};
}

template < typename T>
point3d_t<T> point3d_t<T>:: operator -=(const point3d_t<T>& lp)
{
return { this ->x - lp.x, this ->y - lp.y, this ->z - lp.z};
}

template < typename T>
point3d_t<T> point3d_t<T>:: operator *(const T& coeff)
{
return { this ->x * coeff, this ->y * coeff, this ->z * coeff};
}

 

void printv(va_list args, const char * format)
{
int LENGTH = 500;
char buf[LENGTH];
char * ch = buf;
vsnprintf(buf, LENGTH, format, args);
while (*ch)
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10, *ch++);
}

void print(const char * format,...)
{
va_list args;
va_start(args, format);
printv(args, format);
va_end(args);
}

 

template < typename T>
class Shape3D
{
public:
virtual ~Shape3D() = default;
void rotateAroundLocalAxis(const Axis& axis, const T& angle);
void rotateAroundAttributeAxis(const Axis& axis, const T& angle);
void scaleRelativeToLocalAxis(const T& coeff);
void scaleRelativeToAttributeAxis(const T& coeff);
void scaleRelativeToLocalAxis(const T& coeffX, const T& coeffY, const T& coeffZ);
void scaleRelativeToAttributeAxis(const T& coeffX, const T& coeffY, const T& coeffZ);

point3d_t<T> getCenter() const;
Color getColor() const;
Filling getFilling() const;

void setCenter(const T& x, const T& y, const T& z, const bool firstInit = false);
void setCenter(const point3d_t<T>& center, const bool firstInit = false);
void setColor(const Color& color);
void setFilling(const Filling& filling);
void setDrawnStatus();
void resetDrawnStatus();
void checkIfDrawn();
void setAction(const Action& action);

virtual void drawShape() = 0;

private:
void reapplyRotations(const bool inverse);

Color color_;
bool isDrawn_;
Action action_;
Filling filling_;
point3d_t<T> center_;
std::vector<std::pair<Axis,T>> rotations_;
};

template class Shape3D< float >;
template class Shape3D< double >;

 

template < typename T>
void Shape3D<T>::rotateAroundLocalAxis(const Axis& axis, const T& angle)
{
setAction(Action::ROTATE);
checkIfDrawn();

if (!rotations_.empty() && rotations_.back().first == axis)
rotations_.back().second += angle;
else
rotations_.emplace_back(axis, angle);

glRotated(angle, axis == X, axis == Y, axis == Z);
}

template < typename T>
void Shape3D<T>::rotateAroundAttributeAxis(const Axis& axis, const T& angle)
{
setAction(Action::ROTATE);
checkIfDrawn();

T sinA = sin(angle * M_PI / 180);
T cosA = cos(angle * M_PI / 180);

std::vector<T> rotation_matrix;
switch (axis)
{
case X:
rotation_matrix = { 1, 0, 0,
0, cosA, -sinA,
0, sinA, cosA };
break;

case Y:
rotation_matrix = { cosA, 0, sinA,
0, 1, 0,
-sinA, 0, cosA };
break;

case Z:
rotation_matrix = { cosA, -sinA, 0,
sinA, cosA, 0,
0, 0, 1 };
}

point3d_t<T> new_center = {
rotation_matrix[0] * center_.x + rotation_matrix[1] * center_.y + rotation_matrix[2] * center_.z,
rotation_matrix[3] * center_.x + rotation_matrix[4] * center_.y + rotation_matrix[5] * center_.z,
rotation_matrix[6] * center_.x + rotation_matrix[7] * center_.y + rotation_matrix[8] * center_.z,
};

reapplyRotations(true);

setCenter(new_center);
glRotated(angle, axis == X, axis == Y, axis == Z);

reapplyRotations(false);
rotations_.emplace_back(axis, angle);
}

template < typename T>
void Shape3D<T>::scaleRelativeToLocalAxis(const T& coeff)
{
scaleRelativeToLocalAxis(coeff, coeff, coeff);
}

template < typename T>
void Shape3D<T>::scaleRelativeToAttributeAxis(const T& coeff)
{
scaleRelativeToAttributeAxis(coeff, coeff, coeff);
}

template < typename T>
void Shape3D<T>::scaleRelativeToLocalAxis(const T& coeffX, const T& coeffY, const T& coeffZ)
{
glScaled(coeffX, coeffY, coeffZ);
}

template < typename T>
void Shape3D<T>::scaleRelativeToAttributeAxis(const T& coeffX, const T& coeffY, const T& coeffZ)
{
setAction(Action::SCALE);
checkIfDrawn();

reapplyRotations(true);

setCenter({center_.x * coeffX, center_.y * coeffY, center_.z * coeffZ});
glScaled(coeffX, coeffY, coeffZ);

reapplyRotations(false);
}

template < typename T>
point3d_t<T> Shape3D<T>::getCenter() const
{
return center_;
}

template < typename T>
Color Shape3D<T>::getColor() const
{
return color_;
}

template < typename T>
Filling Shape3D<T>::getFilling() const
{
return filling_;
}

template < typename T>
void Shape3D<T>::setCenter(const T& x, const T& y, const T& z, const bool firstInit)
{
setAction(Action::TRANSLATE);
checkIfDrawn();

if (!firstInit)
glTranslated(x - center_.x, y - center_.y, z - center_.z);
else
glTranslated(x, y, z);

center_.x = x;
center_.y = y;
center_.z = z;
}

template < typename T>
void Shape3D<T>::setCenter(const point3d_t<T>& center, const bool firstInit)
{
setCenter(center.x, center.y, center.z, firstInit);
}

template < typename T>
void Shape3D<T>::setColor(const Color& color)
{
setAction(Action::SET_COLOR);
checkIfDrawn();

if (color_!= color)
color_ = color;

point3d_t<T> rgb = {}; // x - 'r', y - 'g', z - 'b'
switch (color_)
{
case RED:
rgb = {1.0, 0.0, 0.0};
break;

case BLUE:
rgb = {0.0, 0.0, 1.0};
break;

case YELLOW:
rgb = {1.0, 1.0, 0.0};
break;

case GREEN:
rgb = {0.0, 1.0, 0.0};
break;

case WHITE:
rgb = {1.0, 1.0, 1.0};
break;

case PURPLE:
rgb = {1.0, 0.0, 1.0};
break;

case CYAN:
rgb = {0.0, 1.0, 1.0};
break;

case ORANGE:
rgb = {1.0, 0.5, 0.0};
break;

case VIOLET:
rgb = {0.6, 0.3, 0.6};
break;
}

glColor3d(rgb.x, rgb.y, rgb.z);
}

template < typename T>
void Shape3D<T>::setFilling(const Filling& filling)
{
setAction(Action::SET_FILLING);
checkIfDrawn();
filling_ = filling;
}

template < typename T>
void Shape3D<T>::setDrawnStatus()
{
isDrawn_ = true;
}

template < typename T>
void Shape3D<T>::resetDrawnStatus()
{
isDrawn_ = false;
}

template < typename T>
void Shape3D<T>::checkIfDrawn()
{
if (isDrawn_)
{
std::string curAction;
switch (action_)
{
case TRANSLATE:
curAction = "TRANSLATE";
break;

case ROTATE:
curAction = "ROTATE";
break;

case SCALE:
curAction = "SCALE";
break;

case SET_COLOR:
curAction = "SET_COLOR";
break;

case SET_FILLING:
curAction = "SET_FILLING";
break;

case DRAW:
curAction = "DRAW";
break;
}

std::string error_msg = "Cannot [" + curAction + "] because shape has already drawn";
throw std::logic_error(error_msg);
}
}

template < typename T>
void Shape3D<T>::setAction(const Action& action)
{
action_ = action;
}

template < typename T>
void Shape3D<T>::reapplyRotations(const bool inverse)
{
for (auto it = rotations_.end() - 1; it!= rotations_.begin() - 1; --it)
glRotated((*it).second * (inverse? -1.: 1), (*it).first == X, (*it).first == Y, (*it).first == Z);
}

 

template < typename T>
class Cone: public Shape3D<T>
{
public:
Cone(const point3d_t<T>& center, const T& radius, const T& height, const T& slices, const T& stacks);
~Cone() = default;
virtual void drawShape();

private:
T radius_;
T height_;
T slices_;
T stacks_;
};

template class Cone< float >;
template class Cone< double >;

 

template < typename T>
Cone<T>::Cone(const point3d_t<T>& center, const T& radius, const T& height, const T& slices, const T& stacks):
radius_(radius),
height_(height),
slices_(slices),
stacks_(stacks)
{
glPushMatrix();
Shape3D<T>::resetDrawnStatus();
Shape3D<T>::setCenter(center, true);
}

template < typename T>
void Cone<T>::drawShape()
{
Shape3D<T>::setColor(Shape3D<T>::getColor());

Shape3D<T>::setAction(Action::DRAW);
if (Shape3D<T>::getFilling() == WIRE)
glutWireCone(radius_, height_, slices_, stacks_);
else
glutSolidCone(radius_, height_, slices_, stacks_);

Shape3D<T>::setDrawnStatus();
glPopMatrix();
}

 

template < typename T>
class Torus: public Shape3D<T>
{
public:
Torus(const point3d_t<T>& center, const T& inner_radius, const T& outer_radius, const T& sides, const T& rings);
~Torus() = default;
virtual void drawShape();

private:
T inner_radius_;
T outer_radius_;
T sides_;
T rings_;
};

template class Torus< float >;
template class Torus< double >;

 

template < typename T>
Torus<T>::Torus(const point3d_t<T>& center, const T& inner_radius, const T& outer_radius, const T& sides, const T& rings):
inner_radius_(inner_radius),
outer_radius_(outer_radius),
sides_(sides),
rings_(rings)
{
glPushMatrix();
Shape3D<T>::resetDrawnStatus();
Shape3D<T>::setCenter(center, true);
}

template < typename T>
void Torus<T>::drawShape()
{
Shape3D<T>::setColor(Shape3D<T>::getColor());

Shape3D<T>::setAction(Action::DRAW);
if (Shape3D<T>::getFilling() == WIRE)
glutWireTorus(inner_radius_, outer_radius_, sides_, rings_);
else
glutSolidTorus(inner_radius_, outer_radius_, sides_, rings_);

Shape3D<T>::setDrawnStatus();
glPopMatrix();
}

 

template < typename T>
class Cylinder: public Shape3D<T>
{
public:
Cylinder(const point3d_t<T>& center, const T& bottom_radius, const T& top_radius, const T& height, const T& slices, const T& stacks);
~Cylinder() = default;
virtual void drawShape();

private:
T bottom_radius_;
T top_radius_;
T height_;
T slices_;
T stacks_;
GLUquadricObj *quadObj_;
};

template class Cylinder< float >;
template class Cylinder< double >;

 

template < typename T>
Cylinder<T>::Cylinder(const point3d_t<T>& center, const T& bottom_radius, const T& top_radius, const T& height, const T& slices, const T& stacks):
bottom_radius_(bottom_radius),
top_radius_(top_radius),
height_(height),
slices_(slices),
stacks_(stacks)
{
glPushMatrix();
Shape3D<T>::resetDrawnStatus();
Shape3D<T>::setCenter(center, true);
quadObj_ = gluNewQuadric();
}

template < typename T>
void Cylinder<T>::drawShape()
{
Shape3D<T>::setColor(Shape3D<T>::getColor());

Shape3D<T>::setAction(Action::DRAW);
if (Shape3D<T>::getFilling() == WIRE)
gluQuadricDrawStyle(quadObj_, GLU_LINE);
else
gluQuadricDrawStyle(quadObj_, GLU_FILL);

gluCylinder(quadObj_, bottom_radius_, top_radius_, height_, slices_, stacks_);
gluDeleteQuadric(quadObj_);

Shape3D<T>::setDrawnStatus();
glPopMatrix();
}

 

int tx = 0;
int ty = 0;

void reshape(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// glOrtho() - orthogonal projection on objects inside its borders:
// first argument - coordinate of the left side (X)
// second argument - coordinate of the right side (X)
// third argument - coordinate of bottom side (Y)
// fourth argument - coordinate of top side (Y)
// fifth argument - zNear (for us must be < 0, or we won't see some shapes which will be closer to us on positive coordinates)
// sixth argument - zFar (as long as we want to render objects rotations/scaling/translating inside the projection)
glOrtho(-40., 40, -80, +80, -100, +200);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

void rotateAxis()
{
glRotated(tx, 1.0, 0.0, 0.0);
glRotated(ty, 0.0, 1.0, 0.0);
}

void drawAxis(const double line_size)
{
glPushMatrix();

// set white color to axis
glColor3d(1.0, 1.0, 1.0);

//............ X axis..............
glBegin(GL_LINES);
glVertex3d(0., 0., 0.);
glVertex3d(line_size, 0., 0.);
glEnd();

glRasterPos3d(line_size, 0.0, 0.0);
print("X");

glBegin(GL_LINES);
glVertex3d(0., 0., 0.);
glVertex3d(-line_size, 0., 0.);
glEnd();
//..................................

//........... Y axis..............
glBegin(GL_LINES);
glVertex3d(0., 0., 0.);
glVertex3d(0., line_size, 0.);
glEnd();

glRasterPos3d(0.0, line_size, 0.0);
print("Y");
//................................

//........... Z axis.............
glBegin(GL_LINES);
glVertex3d(0., 0., 0.);
glVertex3d(0., 0., line_size);
glEnd();

glRasterPos3d(0.0, 0.0, line_size);
print("Z");

glBegin(GL_LINES);
glVertex3d(0., 0., 0.);
glVertex3d(0., 0., -line_size);
glEnd();
//................................

glPopMatrix();
}

void windowKey(unsigned char key, int width, int height)
{
int angle = 5;

switch (key)
{
case 'w':
tx -= angle;
break;

case 's':
tx += angle;
break;

case 'a':
ty -= angle;
break;

case 'd':
ty += angle;
break;

default:
break;
}

tx %= 360;
ty %= 360;

glutPostRedisplay();
}

void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();

rotateAxis();
drawAxis(40.);

point3d_t< double > center = {20.0, 20.0, 0.0};
std::shared_ptr<Shape3D< double >> shape1 = std::make_shared<Cone< double >>(center, 10, 25, 16., 16.);
shape1->setFilling(Filling::WIRE);
shape1->setColor(Color::VIOLET);
shape1->rotateAroundLocalAxis(Axis::X, -90.);
shape1->rotateAroundAttributeAxis(Axis::X, 90.);
shape1->drawShape();

std::shared_ptr<Shape3D< double >> shape2 = std::make_shared<Cone< double >>(center, 10, 50, 16., 16.);
shape2->setFilling(Filling::WIRE);
shape2->setColor(Color::BLUE);
shape2->rotateAroundLocalAxis(Axis::X, -90.);
shape2->rotateAroundAttributeAxis(Axis::X, 90.);
shape2->drawShape();

center = {-10., 0., 0.};
std::shared_ptr<Shape3D< double >> shape3 = std::make_shared<Torus< double >>(center, 6, 10, 25, 25);
shape3->setFilling(Filling::WIRE);
shape3->setColor(Color::CYAN);
shape3->rotateAroundLocalAxis(Axis::X, 90.);
shape3->rotateAroundAttributeAxis(Axis::Z, -45.);
shape3->drawShape();

center = {10., 0., 0.};
std::shared_ptr<Shape3D< double >> shape4 = std::make_shared<Cylinder< double >>(center, 4, 4, 30, 25, 25);
shape4->setFilling(Filling::WIRE);
shape4->setColor(Color::ORANGE);
shape4->rotateAroundLocalAxis(Axis::X, -90.);
shape4->scaleRelativeToAttributeAxis(2);
shape4->drawShape();

glutSwapBuffers();
}

int main(int argc, char * argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(800, 600);
glutCreateWindow("Sas");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutKeyboardFunc(windowKey);
glutMainLoop();
}

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2019-11-20 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: