Урок Инициализация в Windows я начинаю это пособие непосредственного с кода, разбитого на секции, каждая из которых будет подробно комментироваться. Первое, что вы должны сделать это создать проект в Visual C++


V[0][] – это первая вершина, V[1][]



страница24/27
Дата17.11.2018
Размер7.85 Mb.
ТипУрок
1   ...   19   20   21   22   23   24   25   26   27

V[0][] – это первая вершина, V[1][] – это вторая вершинаV[2][] – это третья вершина. Каждая вершина состоит из:V[][0] – x-координата вершины, V[][1] – y-координата вершины, V[][2] – z-координата вершины.

 

Простым вычитанием всех соответствующих координат первой вершины из координат следующей мы получим ВЕКТОР от первой вершины к следующей. v1[0] = v[0][0] - v[1][0] - это выражение подсчитывает X-компоненту ВЕКТОРА, идущего от ВЕРШИНЫ 0 к вершине 1v1[1] = v[0][1] - v[1][1] - это выражение подсчитывает Y-компоненту, v1[2] =v[0][2] - v[1][2]  подсчитывает Z компоненту и так далее.



 

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

 

Вот формула векторного произведения:



out[x] = v1[y] * v2[z] - v1[z] * v2[y]         

out[y] = v1[z] * v2[x] - v1[x] * v2[z]

out[z] = v1[x] * v2[y] - v1[y] * v2[x]

 

В итоге в массиве out[] у нас будет находиться нормаль треугольника.



 

void calcNormal(float v[3][3], float out[3])       

// Вычислить нормаль для четырехугольников используя 3 точки

{

  float v1[3],v2[3];      // Вектор 1 (x,y,z) & Вектор 2 (x,y,z)



  static const int x = 0  // Определение X-координаты

  static const int y = 1  // Определение Y-координаты

  static const int z = 2; // Определение Z-координаты

 

  // Вычисление вектора между двумя точками вычитанием



  // x,y,z-координат одной точки из координат другой.

 

  // Подсчет вектора из точки 1 в точку 0



  v1[x] = v[0][x] - v[1][x];  // Vector 1.x=Vertex[0].x-Vertex[1].x

  v1[y] = v[0][y] - v[1][y];  // Vector 1.y=Vertex[0].y-Vertex[1].y

  v1[z] = v[0][z] - v[1][z];  // Vector 1.z=Vertex[0].y-Vertex[1].z

  // Подсчет вектора из точки 2 в точку 1

  v2[x] = v[1][x] - v[2][x];  // Vector 2.x=Vertex[0].x-Vertex[1].x

  v2[y] = v[1][y] - v[2][y];  // Vector 2.y=Vertex[0].y-Vertex[1].y

  v2[z] = v[1][z] - v[2][z];  // Vector 2.z=Vertex[0].z-Vertex[1].z

  // Вычисление векторного произведения

  out[x] = v1[y]*v2[z] - v1[z]*v2[y];  // для Y - Z

  out[y] = v1[z]*v2[x] - v1[x]*v2[z];  // для X - Z

  out[z] = v1[x]*v2[y] - v1[y]*v2[x];  // для X - Y

 

  ReduceToUnit(out);      // Нормализация векторов



}

 

Следующая функция задает точку наблюдения с использованием функции gluLookAt. Мы разместим эту точку в точке (0,5,50), она будет направлена на точку (0,0,0)(центр сцены), при этом верхний вектор будет задан с направлением вверх (0,1,0)! ;D



 

void ProcessHelix()      // Рисование спирали (или пружины)

{

  GLfloat x;      // x-координата спирали



  GLfloat y;      // y-координата спирали

  GLfloat z;      // z-координата спирали

  GLfloat phi;    // Угол

  GLfloat theta;  // Угол

  GLfloat v,u;    // Углы

  GLfloat r;      // Радиус скручивания

  int twists = 5; // пять витков

  // Задание цвета материала

  GLfloat glfMaterialColor[]={0.4f,0.2f,0.8f,1.0f}; 

  // Настройка рассеянного освещения

  GLfloat specular[]={1.0f,1.0f,1.0f,1.0f};     

  glLoadIdentity();    // Сброс матрицы модели

  // Точка камеры (0,5,50) Центр сцены (0,0,0)

  // Верх но оси Y

  gluLookAt(0, 5, 50, 0, 0, 0, 0, 1, 0);

  glPushMatrix();      // Сохранение матрицы модели

  // Смещение позиции вывода на 50 единиц вглубь экрана

  glTranslatef(0,0,-50);   

  glRotatef(angle/2.0f,1,0,0);  // Поворот на angle/2 относительно X

  glRotatef(angle/3.0f,0,1,0);  // Поворот на angle/3 относительно Y

  glMaterialfv(GL_FRONT_AND_BACK,

      GL_AMBIENT_AND_DIFFUSE, glfMaterialColor);

  glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,specular);

 

Далее займемся подсчетом формулы спирали и визуализацией пружины. Это совсем несложно, и я не хотел бы останавливаться на этих пунктах, так как «соль» данного урока совсем в другом. Участок программы, отвечающий за спираль, заимствован у друзей из «Listen Software» (и несколько оптимизирован). Он написан наиболее простым и не самым быстрым способом. Использование массивов вершин не делает его быстрее.



 

  r=1.5f;        // Радиус

  glBegin(GL_QUADS);    // Начать рисовать четырехугольник

  for(phi=0; phi <= 360; phi+=20.0)  // 360 градусов шагами по 20

  {// 360 градусов * количество_витков шагами по 20

   for(theta=0; theta<=360*twists; theta+=20.0)

    {// Подсчет угла первой точки  (0)

    v=(phi/180.0f*3.142f);

    // Подсчет угла первой точки  (0)

    u=(theta/180.0f*3.142f);

    // Подсчет x-позиции (первая точка)

    x=float(cos(u)*(2.0f+cos(v) ))*r;

    // Подсчет y-позиции (первая точка)

    y=float(sin(u)*(2.0f+cos(v) ))*r;

    // Подсчет z-позиции (первая точка)

    z=float((( u-(2.0f*3.142f)) + sin(v) ) * r);

    vertexes[0][0]=x;  // x первой вершины

    vertexes[0][1]=y;  // y первой вершины

    vertexes[0][2]=z;  // z первой вершины

    // Подсчет угла второй точки (0)

    v=(phi/180.0f*3.142f); 

    // Подсчет угла второй точки (20)

    u=((theta+20)/180.0f*3.142f); 

    // Подсчет x-позиции (вторая точка)   

    x=float(cos(u)*(2.0f+cos(v) ))*r;

    // Подсчет y-позиции (вторая точка) 

    y=float(sin(u)*(2.0f+cos(v) ))*r;

    // Подсчет z-позиции (вторая точка)

    z=float((( u-(2.0f*3.142f)) + sin(v) ) * r);

    vertexes[1][0]=x;  // x второй вершины

    vertexes[1][1]=y;  // y второй вершины

    vertexes[1][2]=z;  // z второй вершины

    // Подсчет угла третьей точки  ( 20 )

    v=((phi+20)/180.0f*3.142f);

    // Подсчет угла третьей точки  ( 20 )

    u=((theta+20)/180.0f*3.142f);

    // Подсчет x-позиции (третья точка)

    x=float(cos(u)*(2.0f+cos(v) ))*r;

    // Подсчет y-позиции (третья точка)

    y=float(sin(u)*(2.0f+cos(v) ))*r;

    // Подсчет z-позиции (третья точка)

    z=float((( u-(2.0f*3.142f)) + sin(v) ) * r);

    vertexes[2][0]=x;  // x третьей вершины

    vertexes[2][1]=y;  // y третьей вершины

    vertexes[2][2]=z;  // z третьей вершины

    // Подсчет угла четвертой точки (20)

    v=((phi+20)/180.0f*3.142f);

    // Подсчет угла четвертой точки (0)

    u=((theta)/180.0f*3.142f);

    // Подсчет x-позиции (четвертая точка)

    x=float(cos(u)*(2.0f+cos(v) ))*r;

    // Подсчет y-позиции (четвертая точка)

    y=float(sin(u)*(2.0f+cos(v) ))*r;

    // Подсчет z-позиции (четвертая точка)

    z=float((( u-(2.0f*3.142f)) + sin(v) ) * r);

    vertexes[3][0]=x;  // x четвертой вершины

    vertexes[3][1]=y;  // y четвертой вершины

    vertexes[3][2]=z;  // z четвертой вершины

    // Вычисление нормали четырехугольника

    calcNormal(vertexes,normal);

    // Установка нормали

    glNormal3f(normal[0],normal[1],normal[2]);

    // Визуализация четырехугольника

  glVertex3f(vertexes[0][0],vertexes[0][1],vertexes[0][2]);

  glVertex3f(vertexes[1][0],vertexes[1][1],vertexes[1][2]);

  glVertex3f(vertexes[2][0],vertexes[2][1],vertexes[2][2]);

  glVertex3f(vertexes[3][0],vertexes[3][1],vertexes[3][2]);

  }


  }

  glEnd();       // Конец визуализации четырехугольника

  glPopMatrix(); // Восстанавливаем матрицу

}

 



Две функции (ViewOrtho и ViewPerspective) написаны для упрощения рисования в ортогональной проекции и возврата перспективную.

 

Функция ViewOrtho выбирает текущую матрицу проекции и сохраняет ее копию в стеке системы OpenGL. Затем в матрицу проекции грузится единичная матрица, и устанавливается ортогональный просмотр при текущем разрешении экрана.



 

После этого мы получим возможность рисовать в 2D-координатах от 0,0 в верхнем левом углу и 640,480  нижнем правом углу экрана.

 

И в конце, делается активной матрица модели для визуализации.



 

Функция ViewPerspective выбирает текущую матрицу проекции и восстанавливает из стека «неортогональную» матрицу проекции, которая была сохранена функцией ViewOrtho. Потом также выбирается с матрица модели, чтобы мы могли заняться визуализацией.

 

Советую применять эти две процедуры, позволяющие легко переключаться между 2D и 3D-рисованием и не волноваться об искажениях матрицы проекции и матрицы модели.



 

void ViewOrtho()      // Установка ортогонального вида

{

  glMatrixMode(GL_PROJECTION);  // Выбор матрицы проекции



  glPushMatrix();      // Сохранить матрицу

  glLoadIdentity();    // Сбросить матрицу

  glOrtho( 0, 640 , 480 , 0, -1, 1 );  // Ортогональный режим (640x480)

  glMatrixMode(GL_MODELVIEW);  // Выбор матрицы модели

  glPushMatrix();      // Сохранить матрицу

  glLoadIdentity();    // Сбросить матрицу

}

 

void ViewPerspective()           // Установка вида перспективы



{

  glMatrixMode( GL_PROJECTION ); // Выбор матрицы проекции

  glPopMatrix();                 // Восстановить матрицу

  glMatrixMode( GL_MODELVIEW );  // Выбрать матрицу вида

  glPopMatrix();                 // Восстановить матрицу

}

 



Ну а теперь будем учиться «подделывать» эффект размытия.

 

Нам требуется нарисовать сцену размытой от центра во всех направлениях. Способ рисования не должен понизить быстродействие. Непосредственно считывать и записывать пиксели мы не можем, и если мы хотим сохранить совместимость с большинством видеокарт, различные специфические возможности видеокарт также неприменимы.



 

Так неужели все понапрасну …?

 

Ну нет, решение совсем близко. OpenGL дает нам возможность «размытия» текстур. Конечно, это не реальное размытие, просто в процессе масштабирования текстуры выполняется линейная фильтрация ее изображения, и, если напрячь воображение, результат будет похож на «размытие Гаусса».



 

Так что же произойдет, если мы поместим много растянутых текстур  прямо сверху на 3D-сцену и затем промасштабируем их?

 

Ответ вы уже знаете …– радиальное размытие!



 

Здесь у нас три проблемы: как в реальном времени мы будем создавать текстуры и как мы будем точно совмещать 3D-объект и текстуру?

 

Решение проще, чем вы себе представляете!



 

Проблема первая: текстурный рендеринг.

 

Она просто решается форматом пикселов фонового буфера. Визуализация текстуры (да и визуализация вообще) без использования фонового буфера очень неприятна для созерцания!



 

Визуализация текстуры производится всего одной функцией! Нам надо нарисовать наш объект и затем скопировать результат (ПЕРЕД ТЕМ КАК ПЕРЕКЛЮЧИТЬ РАБОЧИЙ И ФОНОВЫЙ БУФЕР в текстуру с использованием функции glCopytexSubImage.

 

Проблема вторая: подгонка текстуры точно на передней стороне 3D-объекта.

 

Нам известно, что если мы поменяем параметры области просмотра без установки правильной перспективы, у нас получится растянутая визуализация наших объектов. Например, если мы установим слишком широкую область просмотра (экран), визуализация будет растянута по вертикали.



 

Решением этой проблемы будет во-первых то, что надо установить режим вида OpenGL, равной размеру нашей текстуры (128х128). После визуализации нашего объекта в изображение текстуры мы визуализируем эту текстуру в текущем разрешении OpenGL-экрана. Таким образом, OpenGL сначала переносит уменьшенную копию объекта в текстуру, затем растягивает ее на весь экран. Вывод текстуры происходит поверх всего экрана и поверх нашего 3D-объекта в том числе. Надеюсь, я ничего не забыл. Еще небольшое уточнение… Если вы возьмете содержимое экрана размером 640х480 и затем ужмете его до рисунка в 256х256 пикселей, то его также можно будет использовать в качестве текстуры экрана и растянуть на 640х480 пикселей. Качество окажется, скорее всего, не очень, но смотреться будет как исходное 640х480 изображение.

 

Забавно! Эта функция в самом деле совсем несложная и является одним из моих самых любимых «дизайнерских трюков». Она устанавливает размер области просмотра (или внутреннего окна) OpenGL равным размеру нашей текстуры (128х128), или нашего массива BlurTexture, в котором эта текстура хранится. Затем вызывается функция, рисующая спираль (наш 3D-объект). Спираль будет рисоваться в окне в 128х128 и поэтому будет иметь соответствующие размеры.



 

После того, как в 128х128-области визуализируется спираль, мы подключаем BlurTexture и копируем буфера цвета из области просмотра при помощи функции glCopyTexImage2D.

 

Параметры определяются следующим образом:



Слово GL_TEXTURE_2D показывает, что мы используем двумерную текстуру. 0 - уровень мип-мапа, с которым мы совершаем копирование буфера, это значение по умолчанию. Слово GL_LUMINANCE определяет формат копируемых данных. Я использовал GL_LUMINANCE, поскольку с этим результат гораздо красивее, это значение позволяет копировать в текстуру лишь светящуюся часть буфера. Тут же могут быть использованы значения GL_ALPHA,GL_RGBGL_INTENSITY и так далее.

 

Следующие два параметра указывают OpenGL на угол экрана, с которого начнется копирование данных (0,0). Далее идут ширина и высота копируемого прямоугольника экрана. И последний параметр необходим, если мы хотим рамку, которая нам не нужна.



 

Теперь, когда у нас есть копия буфера цвета (с уменьшенной спиралью) в массиве BlurTexture, мы можем очистить буфер и вернуть области просмотра ее естественные размеры (640х480 – во весь экран).

 

ВАЖНОЕ ЗАМЕЧАНИЕ:

Этот трюк возможен лишь при поддержке двойной буферизации форматом пикселя. Причиной данного условия является то, что все эти подготовительные процедуры скрыты от пользователя, поскольку полностью совершаются в фоновом буфере.

 

void RenderToTexture()    // Визуализация в текстуру



{

  // Изменить область просмотра (в соответствии с размером текстуры)

  glViewport(0,0,128,128);

  ProcessHelix();    // Нарисовать спираль

  glBindTexture(GL_TEXTURE_2D,BlurTexture); // Подключить нашу текстуру

  // Копирование области просмотра в текстуру (от 0,0 до 128,128... без рамки)

  glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 0, 0, 128, 128, 0);

  glClearColor(0.0f, 0.0f, 0.5f, 0.5); // Цвет фона

  // Очистка экрана и фоновом буфера

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glViewport(0 , 0,640 ,480);// Область просмотра = (0,0 - 640x480)

}

 



Функция просто рисует несколько смешенных полигонов-прямоугольников на переднем плане нашей 3D-сцены, с использованием текстуры BlurTexture, которую мы уже подготовили. Путем постепенного изменения прозрачности (альфа) полигона и масштабирования текстуры у нас получится нечто,  похожее на радиальное размытие.

 

В первую очередь я отключаю флаги GEN_S и GEN_T (я фанатею по сферическому наложению, и мои программы обычно их включают :P).



 

Включаем 2D-текстурирование, отключаем проверку глубины, выбираем соответствующую функцию смешивания, включаем смешивание и подключаем BlurTexture.

 

Следующее, что мы делаем, это переключаемся на ортогональный вид сцены, что упрощает рисование полигонов, которые точно совпадают с размерами экрана. Это выстроит текстуры поверх 3D-объекта (с постепенным растяжением текстуры до размеров экрана). Таким образом, проблема два решена. Два зайца одной выстрелом! (первый «заяц» - рисование полигона в нужном месте экрана, второй «заяц» - вывод текстуры также в требуемом месте над «размываемой» спиралью, «выстрел» - переход на ортогональный вид, дающий возможность работать с обычными 2D-координатами – прим. перев.).



 

void DrawBlur(int times, float inc)  // вывод размытого изображения

{

  float spost = 0.0f;    // Начальное смещение координат



  float alphainc = 0.9f / times;  // Скорость уменьшения прозрачности

  float alpha = 0.2f;    // Начальное значение прозрачности

  // Отключить автоопределение координат текстуры

  glDisable(GL_TEXTURE_GEN_S);

  glDisable(GL_TEXTURE_GEN_T);

  glEnable(GL_TEXTURE_2D);  // Включить наложение 2D-текстур

  glDisable(GL_DEPTH_TEST); // Отключение проверки глубины

  glBlendFunc(GL_SRC_ALPHA,GL_ONE);// Выбор режима смешивание

  glEnable(GL_BLEND);    // Разрешить смешивание

  glBindTexture(GL_TEXTURE_2D,BlurTexture);// Подключить текстуру размытия

  ViewOrtho();      // переключение на ортогональный вид

  alphainc = alpha / times;  // alphainc=0.2f / число_раз визуализации размытия

 

 

Мы много раз выводим рисунок текстуры для создания эффекта размытия, масштабируя его изменением координат текстуры, и тем самым увеличивая степень размытия. Всего рисуется 25 прямоугольников с текстурой, растягиваемой на 1.015 за каждый проход цикла.



 

  glBegin(GL_QUADS);    // Рисуем прямоугольники

  for (int num = 0;num < times;num++)// Количество походов = times 

  {


    // Установить значение alpha (начальное = 0.2)

    glColor4f(1.0f, 1.0f, 1.0f, alpha);

    glTexCoord2f(0+spost,1-spost);  // Координаты текстуры  (0,1)

    glVertex2f(0,0);    // Первая вершина(0,0)

    glTexCoord2f(0+spost,0+spost);  // Координаты текстуры  (0,0)

    glVertex2f(0,480);  // Вторая вершина(0,480)

    glTexCoord2f(1-spost,0+spost);  // Координаты текстуры  (1,0)

    glVertex2f(640,480);// Третья вершина (640,480)

    glTexCoord2f(1-spost,1-spost);  // Координаты текстуры  (1,1)

    glVertex2f(640,0);  // Четвертая вершина (640,0)

    // Увеличение spost (Приближение к центру текстуры)

    spost += inc;

    // Уменьшение alpha (постепенное затухание рисунка)

    alpha = alpha - alphainc;

  }

  glEnd();        // Конец рисования



  ViewPerspective();        // Назад к перспективному виду

  glEnable(GL_DEPTH_TEST);  // Включить проверку глубины

  glDisable(GL_TEXTURE_2D); // Отключить 2D-текстурирование

  glDisable(GL_BLEND);      // Отключить смешивание

  glBindTexture(GL_TEXTURE_2D,0); // Отвязать текстуру

}

 



И вуаля: самая короткая функция Draw, когда-либо виданная, дающая возможность увидеть превосходный визуальный эффект.

 

Вызывается функция RenderToTexture. Здесь один раз рисуется растянутая пружина маленького размера, благодаря изменению параметров области вывода. Растянутая пружина копируется в нашу текстуру, затем буфер очищается.



 

Затем мы рисуем «настоящую» пружину (трехмерный объект, который вы видите на экране) при помощи функцииProcessHelix().

 

Наконец, мы рисуем последовательность «смешено-размазанных» полигонов-прямоугольников спереди пружины. То есть текстурированные прямоугольники будут растянуты и размазаны по изображению реальной 3D-пружины.



 

void Draw (void)      // Визуализация 3D-сцены

{

  glClearColor(0.0f, 0.0f, 0.0f, 0.5);// Очистка черным цветом



  // Очистка экрана и фонового буфера

  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glLoadIdentity();   // Сброс вида

  RenderToTexture();  // Визуализация в текстуру

  ProcessHelix();     // Рисование спирали

  DrawBlur(25,0.02f); // Эффект размытия

  glFlush ();         // «Сброс» конвейера OpenGL

}

 



Надеюсь, данное руководство вам понравилось, хотя оно больше ничему и не учит, кроме визуализации в текстуру, но определенно может добавить красивый эффект в ваши 3D-программы.

Со всеми комментариями и предложениями по улучшению реализации этого эффекта прошу слать письма на rio@spinningkids.org. (а если вы хотите получить исправленную и улучшенную версию программы, пишите на lake@tut.by, будет интересно пообщаться :) - прим. перев. ).

 

Вы вольны использовать этот код бесплатно, тем не менее, если вы собираетесь использовать его в своих разработках, отметьте это и попытайтесь понять, как он работает, только так и никак иначе. Кроме того, если вы будете использовать этот код в своих коммерческих разработках (разработки, за которые вы потребуете плату), пожалуйста, выделите мне некоторый кредит.



 

И еще я хочу оставить вам всем небольшой список заданий для практики (домашнее задание) :D

1) Переделайте функцию DrawBlur для получения горизонтального размытия, вертикального размытия и каких-нибудь других интересных эффектов (круговое размытие, например).

2) Поменяйте параметры функции DrawBlur (увеличьте или уменьшите), чтобы получился красивый световой эффект под вашу музыку.

3) Поиграйте с функцией DrawBlur, нашей небольшой текстурой и значением GL_LUMINANCE (крутой блеск!).

4) Симитируйте объемные тени при помощи темных текстур взамен светящихся.

 

Ок. Теперь, должно быть, все.



Урок 39. Введение в физический симулятор

 

Если вы знакомы с физикой и хотите написать физический симулятор – этот урок поможет вам. Для того чтобы достигнуть успеха вам понадобятся знания векторных операций в 3D и базовых физических понятий, таких как сила и скорость.



 

В этом уроке вы найдете код очень простого движка физики. (Скорее просто пример, для движка все слишком упрощено – прим. переводчика).

 

Cодержание (в порядке следования):



 

Дизайн:


 * class Vector3D           ---> Объект представляющий 3D - вектор или точку в пространстве

 

Сила и движение:



 * class Mass               ---> Объект представляющий массу.

 

Как работает симуляция:



 * class Simulation         ---> Контейнер для симуляции масс.

 

Управление симуляцией из приложения:



 * class ConstantVelocity :

   public Simulation        ---> Объект создающий массу с постоянной скоростью.

 

Применение силы:



 * class MotionUnderGravitation :

   public Simulation        ---> Объект создающий массу, движущуюся под воздействием гравитации.

 * class MassConnectedWithSpring :

   public Simulation        ---> Объект создающий массу, соединенную с пружиной в точке.

 

Дизайн:


 

Создание физического движка задача не всегда простая. Но есть несколько очевидных зависимостей: приложение зависит от движка, а движок в свою очередь зависит от библиотек математики. Наша задача получить контейнер для симуляции движения масс. Наш движок будет включать в себя класс «Mass» и класс «Simulation» - наш контейнер. После того как эти классы будут готовы, мы сможем писать приложения. Но, прежде всего нам понадобится математическая библиотека. Эта библиотека содержит только один класс «Vector3D», который используется для представления точек, векторов, положений, скорости и силы в 3D.

 

 * class Vector3D           ---> Объект представляющий вектор или точку в пространстве



 


Каталог: forum
forum -> Лечение гепатозов
forum -> Система ведения овцеводства в крестьянско-фермерских и личных хозяйствах населения
forum -> Yaesuft-857 (ft-897) – переходник для подключения cat интерфейса к микрофонному разъему трансивера
forum -> Васильев Владимир Юрьевич
forum -> tl-wr1043ND Беспроводной гигабитный маршрутизатор серии n copyright & trademarks
forum -> Цели и задачи Контакта rtf docx
forum -> Назовите не менее трех результатов революции 1905- 1907гг. Приведите не менее трех положений, отражающих значение революции для отечественной истории начала 20 века


Поделитесь с Вашими друзьями:
1   ...   19   20   21   22   23   24   25   26   27


База данных защищена авторским правом ©vossta.ru 2019
обратиться к администрации

    Главная страница