html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Рисуем 3D на осциллографе

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

Общие слова


Итак, мы собираемся рисовать 3D. И не просто рисовать, а рисовать на осциллографе. Я думаю, что будет достаточно изобразить вращающийся кубик, что бы понять принцип работы, а там и до трехмерной стрелялки не далеко.
Вся фишка заключается в том, что в векторных дисплеях(то есть для нас это экран осциллографа) в отличие от, тех к которым мы привыкли, изображение выводится не с помощью последовательного подсвечивания пикселов, а с помощью установки проецирующего луча в нужное место. То есть мы просто «обводим» контуры будущей картинки лучом по экрану, вместо того что бы отмечать точки.

Как подружить компьютер и осциллограф?


Давайте посмотрим, что происходит внутри осциллографа. В самом простейшем случае осциллограф представляет собой электронную пушку, которая создает и фокусирует луч из электронов. Затем этот луч, проходя через два конденсатора, отклоняется горизонтально или вертикально, в зависимости от напряжения на них. Потом луч попадает на экран, покрытый люминофором, и происходит вспышка в том месте куда попал луч. Таким образом при достаточно быстром движении луча формируется картинка.
Напряжение на отклоняющих конденсаторах зависит от напряжения на входах осциллографа. У нас отклонением по оси X будет управлять один вход, а по оси Y другой. Ура, мы уже можем что-нибудь нарисовать подавая соответствующее напряжение осциллографу.
А подавать его мы будем с помощью звуковой карты компьютера, ведь от частоты звука зависит напряжение на ее выходах. Пусть правый канал у нас отвечает за движение по оси X, а левый по оси Y.
То есть просто присоединив правый канал звуковой карты к первому входу осциллографа, а левый ко второму можно будет управлять движением луча по экрану.

Ставим точку


Для начала научимся просто ставить одну точку. Будем использовать всеми любимый Python и пару библиотек к нему. Посмотрим на такой код:

import sys
import struct
import wave
from math import *

# Открываем и инициализируем wav-файл
WaveF = wave.open("output.wav", "wb")
WaveF.setnchannels(2)
WaveF.setsampwidth(2)
WaveF.setframerate(48000)

WaveF.writeframes(struct.pack("hh", 0.5 * 32767.0, 0.5 * 32767.0))

WaveF.close()

* This source code was highlighted with Source Code Highlighter.


Тут все просто: открываем wav-файл, и записываем туда информацию об одной точке(фрейме в терминологии wav файлов). Мы считаем что координаты точки бывают только от -1 до 1, поэтому смело домножаем их на максимальное значение в типе integer, что бы громкость, а соответственно и выходное напряжение были бы достаточно большими. Звук я вывожу в wav только потому что, так его можно залить на плеер и спокойно донести до осциллографа.
Так, мы научились ставить точку на двухмерной плоскости, но ведь мы хотим 3D. Поэтому применим немного простой математики и научимся проецировать точку из трехмерного пространства в двухмерное, вот так:
# Настройки перспективной прекции
xSize = 0.6 # Размер проекционного экрана по оси X
ySize = 0.4 # Размер проекционного экрана по оси Y
Dist = 1.5 # Расстояние от наблюдателя до экрана

# Проецируем точку, у нас уже три координаты
def PutPoint( x, y, z ):
 # Специальные магические формулы
 sx = (xSize / 2) + ((x * Dist) / (z + Dist))
 sy = (ySize / 2) + ((y * Dist) / (z + Dist))

 # Проверяем на корректность полученые значения
 if (sx < -1):
  sx = -1;
 if (sx > 1):
  sx = 1;
 if (sy < -1):
  sy = -1;
 if (sy > 1):
  sy = 1;
 # И выводим в файл
 WaveF.writeframes(struct.pack("hh", sy * 32767.0, sx * 32767.0))

* This source code was highlighted with Source Code Highlighter.

Супер, теперь можно ставить точку с тремя координатами и она будет правильно проецироваться. Самое важное сделано, осталось совсем немного.

Рисуем куб!


Тут все еще проще. Смотрим на интеллектуальный код:

def DrawCube():
 DrawXLine(CPoint(0, 0, 0), CPoint(0.5, 0, 0), 0.0121)
 DrawXLine(CPoint(0, 0.5, 0), CPoint(0.5, 0.5, 0), 0.0121)
 DrawXLine(CPoint(0, 0, 0.5), CPoint(0.5, 0, 0.5), 0.0121)
 DrawXLine(CPoint(0, 0.5, 0.5), CPoint(0.5, 0.5, 0.5), 0.0121)

 DrawYLine(CPoint(0, 0, 0), CPoint(0, 0.5, 0), 0.0121)
 DrawYLine(CPoint(0.5, 0, 0), CPoint(0.5, 0.5, 0), 0.0121)
 DrawYLine(CPoint(0, 0, 0.5), CPoint(0, 0.5, 0.5), 0.0121)
 DrawYLine(CPoint(0.5, 0, 0.5), CPoint(0.5, 0.5, 0.5), 0.0121)

 DrawZLine(CPoint(0, 0, 0), CPoint(0, 0, 0.5), 0.0121)
 DrawZLine(CPoint(0.5, 0, 0), CPoint(0.5, 0, 0.5), 0.0121)
 DrawZLine(CPoint(0, 0.5, 0), CPoint(0, 0.5, 0.5), 0.0121)
 DrawZLine(CPoint(0.5, 0.5, 0), CPoint(0.5, 0.5, 0.5), 0.0121)

* This source code was highlighted with Source Code Highlighter.

Что делаю функции фида DrawXLine, думаю, понятно? Последний параметр в них обозначает шаг луча и выбран на глаз=) Таким образом мы нарисовали статичный куб в начале координат, однако он слишком неподвижен, а это так скучно. Поэтому дабавим анимацию.
Все, что нам потребуется это совсем немного изменить код функции PutPoint.

def PutPoint( x, y, z ):
 global AngleX, AngleY

 # Магический поворот точки вокруг начала координат по оси Y
 nx = x * cos(AngleY) + z * sin(AngleY)
 nz = z * cos(AngleY) - x * sin(AngleY)
 ny = y;

 # И по оси X
 nnx = nx
 nny = ny * cos(AngleX) - nz * sin(AngleX)
 nnz = ny * sin(AngleX) + nz * cos(AngleX)

 # Дальше все по-старому
 sx = (xSize / 2) + ((nnx * Dist) / (nnz + Dist))
 sy = (ySize / 2) + ((nny * Dist) / (nnz + Dist))
 if (sx < -1):
  sx = -1;
 if (sx > 1):
  sx = 1;
 if (sy < -1):
  sy = -1;
 if (sy > 1):
  sy = 1;
 WaveF.writeframes(struct.pack("hh", sy * 32767.0, sx * 32767.0))

* This source code was highlighted with Source Code Highlighter.

Мы добавили две глобальные переменные AngleX и AngleY для управления углами вращения, и просто применили соответствующие преобразования к исходным координатам точки. Вот так теперь выводим кубик:

AngleY = 0
AngleX = 0
for cnt in range(0, 1000):
 DrawCube()

 AngleY += radians(1)
 AngleX += radians(1)

* This source code was highlighted with Source Code Highlighter.

Все предельно просто.
Смотрите на результат:

Ну как оно? Огорчают странные шумы в вершинах кубика, я надеюсь это из-за плохого соединения плеера и осциллографа.
Вот и все, спасибо за внимание, всем удачи=)

_________
Текст подготовлен в ХабраРедакторе
Читать дальше
Twitter
Одноклассники
Мой Мир

материал с habrahabr.ru

95
    +77 surfers

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • godzilla_37rus
          • домен habrahabr.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции