Сообщество - TECHNO BROTHER

TECHNO BROTHER

2 018 постов 13 454 подписчика

Популярные теги в сообществе:

38

Ответ на пост «Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году?»1

Когда я учился в 9 классе, а это был вроде 2003 год, начали заниматься программированием на информатике, хотя я начал изучать его чуть раньше. Нам объясняли, как на бейсике отрисовать точку, круг, квадрат, и прописав несколько координат, линиями нарисовать многоугольник в виде разных лодочек. Меня это так увлекло, ведь мы на алгебре как раз строили графики, а задав нужную функцию, вывести точки в виде графика, нет ничего проще. В общем первой моей программой был "решебник" для проверки верности моих построений графиков. Потом втянулся, нажал на кнопочку, нарисована ось координат с необходимым масштабом и штрих отметками, перерисовка при изменении масштабов окна и т.д. были, конечно проблемы с тормозами, ведь если точки рисовать достаточно плотно друг к другу, происходит эффект анимации рисования, а если точки редко, отрисовка быстрая, но приблизительная. В общем довел эту программу практически до уровня примитивного графического редактора, можно сказать даже некое подобие графического движка, способного выводить необходимые 2д модели, сохраняя их в файле и пользоваться ими в дальнейшем как спрайтами. Сделал на нем даже две игры, лабиринт, по которому бегает колобок, и пятнашки. Когда учитель информатики увидел мои работы, он конечно мне отлично поставил за будущие года, так как я там ничего нового больше не узнаю, но в то же время предложил заниматься со мной факультативно. Хоть он мне и сказал, что я изобрел велосипед, и все это уже реализовано в DX, но меня преисполняла гордость, что допер до этого сам. Тем не менее, я купил книжку по директу, и тут понеслось. Как же изменилось качество графики, в основном из за смены буферов. Затем разобрался с фотошопом и 3dsmax. Вуаля, и первая полноценная 3d игра, где все тот же лабиринт из рельс и вагонетки, в которой помимо стандартного прохождения, нужно еще переключать стрелки в нужном порядке, чтобы собирать золото. В общем игра не слишком захватывающая, но играл в нее чаще, чем в КС. Эх как же жаль что исходников не сохранилось.

Показать полностью
10

XTREMCAM Pro VTR V1

Досталась мне по случаю камера. Непростая, а раллийная.

XTREMCAM Pro VTR V1 Электроника, Экшн-камера, Ралли, Камера, Видеорегистратор, Видео, Вертикальное видео, YouTube, Длиннопост

Эх, такую бы штуку лет …цать назад!

Увы, прогресс шагает вперед, и прекрасный инструмент уже не актуален.

Но, обо всём по порядку.

Название у камеры Pro-motion Camera Systems HD PRO VTR 1080P , она же  XTREMCAM Pro VTR V1, она же Mangrove SM-SH0198.

XTREMCAM Pro VTR V1 Электроника, Экшн-камера, Ралли, Камера, Видеорегистратор, Видео, Вертикальное видео, YouTube, Длиннопост

Краткий обзор был выложен на Ютюб https://youtu.be/xCL6Qxwp-8U, откуда был каким-то деятелем скопирован и выложен на Рутюб. Ну да ладно, был бы толк.

Там же в описании приведены характеристики, взятые с сайтов в открытом доступе. Этими параметрами утомлять не стану, кому нужно сам найдёт.

Буду делиться личными впечатлениями.

Камера поставляется в таком приличном полужёстком кейсе, набор включает в себя камеру , соединенную с блоком управления толстым кабелем длиной около 2 метров.

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

К ней идут два аккумулятора, набор всяких соединительных проводов и проводов питания. Есть пульт и чехол на блок управления.  HDMI отсутствует. Только аналог. Запись идёт на Карту памяти SD. Можно делать снимки (такое себе конечно).

Если кратко, то очень жаль, что производитель забросил модернизацию и поддержку данной камеры. Битрейта видео явно маловато. Возможно, злую шутку сыграло появление Гоупро.


Тут же выложу инструкцию к данной камере.

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

Кому нужны оригиналы видео, выложу в облако.

Ссылка будет в комментариях

И на последок, вкусное - реальное видео с раллийных гонок

Всем хорошего настроения!

Показать полностью 36 5
515
TECHNO BROTHER

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году?1

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

Осторожно: Несмотря на кажущуюся сложность статьи о разработке целой 3D-игры с нуля, я постарался систематизировать и упростить материал так, чтобы понятно было любому заинтересованному читателю, даже если вы далеки от программирования в целом!

Статьи о разработке инди-игр — это всегда интересно. Но разработка чего-то абсолютно с нуля, без каких-либо движков или фреймворков — ещё интереснее! Почти всю свою жизнь, буквально с 13-14 лет меня тянет пилить какие-нибудь прикольные 3D-демки и игрушки. Ещё на первом курсе ПТУ я написал небольшую демку с 3D-вертолетиками по сети и идея запилить какие-нибудь прикольные леталки не покидала меня по сей день! Спустя 6 лет, в 22 года я собрался с силами и решил написать небольшую аркадную демку про баталии на самолетиках, да так, чтобы работало аж на видеокартах из 90-х — NVidia Riva 128 и 3DFX Voodoo 3! Интересно, как происходит процесс разработки игры с нуля — от первого «тридэ» треугольника, до работающей на реальном железе демки? Тогда добро пожаловать под кат!

❯ Мотивация


Друзья! Вижу, что вам очень заходит моя постоянная рубрика о том, как работали графические ускорители из 90-х «под капотом», где мы не только разбираем их архитектуру, но и пишем демки на их собственных графических API. Мы уже успели с вами рассмотреть 3Dfx Voodoo, S3 ViRGE и мобильный PowerVR MBX и, думаю, теперь пришло время рассмотреть инструменты для разработчиков игр под Windows из 90-х. Про «старый» OpenGL рассказывать смысла не вижу — до сих пор многие новички учатся по материалам с glBegin/glEnd и FFP (Fixed Function Pipeline), а спецификацию с описанием первой версии API можно найти прямо на сайте Khronos. Зато про «старый» DirectX информации в сети очень мало и большинство документации уже потёрли даже из MSDN, хотя в нём было много чего интересного!

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

Вероятно читатель спросит — зачем пилить что-то для компьютеров 90-х годов, если большинство таких машин (к сожалению) отправились на цветмет и «никто в своем уме» не будет ими пользоваться? Ну, ретро-компьютинг и программирование демок — это, во-первых, всегда интересно. Среди моих подписчиков довольно много ребят, которые ещё учатся в школе, а уже натаскали с барахолок Pentium III или Pentium IV и GeForce 4 MX440 и сидят, балдеют и играют в замечательные игрушки из нулевых на таких машинах с по настоящему трушным опытом, да и я сам таким был и остаюсь по сей день. Вон, мне даже dlinyj скидывал свои девайсы в личку, а я сидел и слюни пускал. Так что факт остаётся фактом — ретро-компьютинг становится всё более и более популярен — что не может не радовать!

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

А во-вторых — это челлендж для самого себя! Посмотреть на то, как делали игры «деды» и попытаться запилить что-то самому, не забыв об этом написать статью и снять интересное видео в попытке донести это как можно большему числу читателей и зрителей! Конечно сам DirectX6 в целом значительно проще DX12, но некоторые техники весьма заковыристые и для достижения оптимальной производительности приходится пользоваться хаками. Ну а почему именно леталки? Потому что, наверное, хотел бы когда-нибудь полетать :)

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

Игру я решил писать на C#. Кому-то решение может показаться странным, но я уже не раз говорил, что это мой любимый язык, а при определенной сноровке — программы на нем работают даже под Windows 98. В качестве основного API для игры я выбрал DirectX 6, который вышел 7 августа 1998 года — за 3 года до моего рождения :)

Перед тем как что-то начинать делать, нужно определиться с тем, что нам нужно для нашей 3D-игры:

  • Графический движок или рендерер, работающий на базе Direct3D. В его задачи входит отрисовка геометрии, работа с освещением и материалами, отсечение моделей, находящихся вне поле зрения глаз, генерация ландшафтов из карт высот и т. п. Собственно, в нашем конкретном случае это графическим движком назвать сложно — никакого полноценного графа (иерархической структуры, как в Unity) сцены нет, толковой анимации тоже, зато есть довольно продвинутая система материалов :)

  • Звуковой движок на базе DirectSound. Здесь всё по классике: программный 3D-звук с эффектами типа «виу» и «вжух» с загрузкой звуковых дорожек из wav-файлов. Никакого стриминга звука с кольцевыми буферами и ogg/mp3 здесь не нужно!

  • Подсистема ввода, которая представляет из себя «получить состояние кнопки на клавиатуре» и «получить позицию курсора» :)

  • Остальные модули — сюда входят алгоритмы расчёта коллизий, математическая библиотека для работы с векторами и матрицами, система игровых объектов и загрузчики ресурсов. Это весьма небольшие и легкие в реализации подсистемы, но писать про каждый отдельный пункт смысла не очень много, поскольку они так или иначе часть других систем.




Как известно, в самолёте всё зависит от винта! Ну, или в нашем случае, от 3D-движка — поэтому предлагаю рассмотреть архитектуру нашего рендерера и заложить первые кирпичики в нашу 3D-игру!

❯ Графический движок


Поскольку C# — управляемый язык и напрямую дёргать COM-интерфейсы формально не может, а готовых обёрток для DirectX 6 по понятным причинам нет, мне пришлось писать свою. Простыми словами, обёртка обеспечивает слой совместимости между нативными библиотеками, написанными на C++ и управляемым кодом, написанном на C#/VB и т.п. Благо в мире .NET есть такое замечательное, но увы, забытое расширение плюсов, как С++/CLI, которое позволяет прозрачно смешивать нативный код и «байткод» .NET, благодаря которому разработка пошла значительно быстрее.

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

Любой графический движок начинается с создания окна и инициализации контекста графического API (инициализации видеокарты, если простыми словами) для рисования в это самое окно. В случае Direct3D6 всё интереснее тем, что фактически здесь уже был свой аналог современного DXGI (DirectX Graphics Infrastructure — библиотека для управления видеокартами, мониторами в системе), который назывался DirectDraw. Изначально DDraw использовался для аппаратного ускорения графики на VGA 2D-акселеллераторах — тех самых S3 ViRGE и Oak Technology и предназначался в основном для операций блиттинга (копирования картинки в картинку), но в D3D ему выделили функции управления видеопамятью и поэтому они очень тесно связаны.

Инициализация начинается с создания так называемой первичной поверхности (которая будет отображаться на экран) и заднего буфера (в который будет рисоваться само изображение), или в терминологии современных API — Swap-chain.

DDSURFACEDESC rtDesc;
memset(&rtDesc, 0, sizeof(rtDesc));
rtDesc.dwSize = sizeof(rtDesc);
rtDesc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
rtDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
rtDesc.dwWidth = Width;
rtDesc.dwHeight = Height;
Guard(ddraw->CreateSurface(&rtDesc, &sSurf, 0));
Guard(sSurf->QueryInterface(IID_IDirectDrawSurface4, (LPVOID*)&sSurf4));

Теперь у нас есть окно, куда можно что-нибудь нарисовать!

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

Но 3D мы пока рисовать не можем — ведь контекста D3D у нас всё ещё нет, благо создаётся он очень просто. Единственный момент: Z-буфер нужно создать перед созданием устройства, иначе работать он не будет.

DDSURFACEDESC zbufDesc;
memset(&zbufDesc, 0, sizeof(zbufDesc));
zbufDesc.dwSize = sizeof(zbufDesc);
zbufDesc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
zbufDesc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
memcpy(&zbufDesc.ddpfPixelFormat, Window::zBufferFormat, sizeof(zbufDesc.ddpfPixelFormat));
zbufDesc.dwWidth = Width;
zbufDesc.dwHeight = Height;

IDirectDrawSurface* zTemp;
IDirectDrawSurface4* zSurface;
Guard(ddraw->CreateSurface(&zbufDesc, &zTemp, 0));
Guard(zTemp->QueryInterface(IID_IDirectDrawSurface4, (LPVOID*)&zSurface));

// Attach Z-Buffer to backbuffer
Guard(d3dSurface->AddAttachedSurface(zSurface));
Guard(d3d->CreateDevice(IID_IDirect3DHALDevice, surf, &device, 0));

Мы уже на полпути перед тем как нарисовать первый тридэ-треугольник: осталось лишь объявить структуру вершины и написать обёртки над… Begin/End! Да, в Direct3D когда-то тоже была концепция из OpenGL, а связана она с тем, что в видеокартах тех лет вершины передавались не буферами, а по одному, уже трансформированные. Подробнее об этом можно почитать в моей статье о S3 ViRGE:

public value struct Vertex
{
public:
float X, Y, Z;
float NX, NY, NZ;
D3DCOLOR Diffuse;
float U, V;
};

...

Vertex[] v = new Vertex[3];
v[0] = new Vertex()
{
X = 0,
Y = 0,
Z = 0,
U = 0,
V = 0
};
v[1] = new Vertex()
{
X = 1,
Y = 0,
Z = 0,
U = 1,
V = 0
};
v[2] = new Vertex()
{
X = 1,
Y = 1,
Z = 0,
U = 1,
V = 1
};

dev.BeginScene();
dev.Begin(PrimitiveType.TriangleList, Device.VertexFormat);
dev.Vertex(v[0]);
dev.Vertex(v[1]);
dev.Vertex(v[2]);
dev.End();
dev.EndScene();

И вот, у нас есть первый треугольник! Читатель может спросить — а где же здесь игра и причём здесь треугольники, мы же не на уроке геометрии… Дело в том, что вся 3D-графика в современных играх строится из треугольников. Любая моделька на экране — это набор из маленьких примитивов, которые в процессе рисования на экран подвергаются процессу трансформации — преобразованию из мировых координат (то есть абсолютной позиции в мире) сначала в координаты камеры (таким образом, при движении камеры, на самом деле двигаются объекты вокруг камеры), а затем и в экранные координаты, где происходит перспективное деление и каждый треугольник начинает выглядеть как трёхмерный…

Таким образом, из тысяч треугольников можно описать самые разные объекты — от трёхмерной модели моих любимых «жигулей», до персонажей.

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

Но если сейчас нарисовать самолетик, то он будет исключительно белым, без намёка на освещение или детали. А для его «раскрашивания» служат текстуры — специальные изображения, подогнанные под текстурные координаты геометрии, которые помогают дополнить образ 3D-моделей деталями: асфальт на дороге, трава на земле, дверная карты в жигулях…

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

И вот с текстурами ситуация в D3D6 не менее интересная и очень похожа на современные GAPI: нам необходимо сначала создать текстуру в системной памяти (ОЗУ) и только затем скопировать её в видеопамять. Причём форматов текстур не слишком много. Я выбрал RGB565 (16-битный), хотя есть поддержка и форматов со сжатием — тот-же S3TC.

bool hasMips = mipCount > 1; // If texture has more than 1 mipmap, then create surface as complex, if not - then as single-level.

DDSURFACEDESC2 desc;
memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc);
desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_TEXTURESTAGE | DDSD_CKSRCBLT;
desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | (hasMips ? (DDSCAPS_MIPMAP | DDSCAPS_COMPLEX) : 0);
desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
memcpy(&desc.ddpfPixelFormat, DXSharp::Helpers::Window::opaqueTextureFormat, sizeof(desc.ddpfPixelFormat));
desc.dwWidth = Width = width;
desc.dwHeight = Height = height;

IDirectDrawSurface4* surf;
IDirect3DTexture2* tex;

IDirectDraw4* dd2;
window->ddraw->QueryInterface(IID_IDirectDraw4, (LPVOID*)&dd2);

Guard(dd2->CreateSurface(&desc, &surf, 0));
Guard(surf->QueryInterface(IID_IDirect3DTexture2, (LPVOID*)&tex));

А чтобы её использовать, нужно «сказать» об этом видеокарте с помощью биндинга текстуры к текстурному юниту. Те, у кого были в свое время 3dfx Voodoo, наверняка поймут, о чём я :)

Guard(device->SetTexture(stage, tex->texture));

И вот у нас уже есть треугольник с текстурой! Осталось лишь домножить его матрицы трансформации, перспективную матрицу…

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

Реализуем простенький загрузчик моделей из формата SMD (GoldSrc, Half-Life или CS1.6), который грузит статичные модельки без скиннинга, а также загрузчик текстур из bmp и вот — мы уже имеем 3D-модельку самолёта с текстурой.

for(int i = 0; i < smd.Triangles.Count; i++)
{
uint c = new Color(255, 255, 255, 255).GetRGBA();

for (int j = 0; j < 3; j++)
vert[i * 3 + j] = new Vertex()
{
X = smd.Triangles[i].Verts[j].Position.X,
Y = smd.Triangles[i].Verts[j].Position.Y,
Z = smd.Triangles[i].Verts[j].Position.Z,
U = smd.Triangles[i].Verts[j].UV.X,
V = smd.Triangles[i].Verts[j].UV.Y,
NX = smd.Triangles[i].Verts[j].Normal.X,
NY = smd.Triangles[i].Verts[j].Normal.Y,
NZ = smd.Triangles[i].Verts[j].Normal.Z,
Diffuse = c
};
}

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

Возможно в каких-то играх и не нужно небо, но в леталках — уж точно необходимо. И без учёта динамических облаков, здесь есть две популярные техники:

Возможно в каких-то играх и не нужно небо, но в леталках — уж точно необходимо. И без учёта динамических облаков, здесь есть две популярные техники:

  • Sky-sphere, которая заключается в том, что небо представляет из себя полусферу с наложенной поверх текстурой неба в специальном формате. Такую полусферу очень часто крутят вокруг своей оси по оси Y, создавая эффект плывущих облаков. И получается вполне себе симпатичное анимированное небо. Иные варианты включают в себя многослойные реализации, где крутится могут лишь облака, когда статичные элементы фона остаются на месте.

  • Skybox — здесь суть простая, вокруг камеры рисуется «коробка» с вывернутыми в обратную сторону треугольниками, на которых рисуется текстура одной из сторон панорамы с выключенной записью в Z-буфер. Получается не только симпатично, но ещё и быстрее Skysphere на слабом железе, правда скайбоксы обычно статичным. Скайбоксы можно найти почти везде: например, в Counter-Strike, Half-Life.

    На скриншоте ниже можно увидеть пример скайбокса:

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост



Я выбрал скайбоксы. Реализация — проще пареной репы:

materials[0].Texture = TextureLoader.LoadFromImage(string.Format("{0}{1}_bk.bmp", Path, name));
materials[1].Texture = TextureLoader.LoadFromImage(string.Format("{0}{1}_ft.bmp", Path, name));
materials[2].Texture = TextureLoader.LoadFromImage(string.Format("{0}{1}_lf.bmp", Path, name));
materials[3].Texture = TextureLoader.LoadFromImage(string.Format("{0}{1}_rt.bmp", Path, name));
materials[4].Texture = TextureLoader.LoadFromImage(string.Format("{0}{1}_up.bmp", Path, name));
materials[5].Texture = TextureLoader.LoadFromImage(string.Format("{0}{1}_dn.bmp", Path, name));

....

Engine.Current.Graphics.DrawMesh(mesh, 0, 6, v, new Vector3(0, 0, 0), new Vector3(1, 1, 1), materials[1]); // Forward
Engine.Current.Graphics.DrawMesh(mesh, 6, 12, v, new Vector3(0, 0, 0), new Vector3(1, 1, 1), materials[3]); // Right
Engine.Current.Graphics.DrawMesh(mesh, 12, 18, v, new Vector3(0, 0, 0), new Vector3(1, 1, 1), materials[0]); // Back
Engine.Current.Graphics.DrawMesh(mesh, 18, 24, v, new Vector3(0, 0, 0), new Vector3(1, 1, 1), materials[2]); // Left
Engine.Current.Graphics.DrawMesh(mesh, 24, 30, v, new Vector3(0, 0, 0), new Vector3(1, 1, 1), materials[4]); // Left

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

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

Мы проходимся по всей картинке и строим сетку треугольников, где высота определяется именно соседними пикселями на этой самой карте высот. На практике это выглядит так:

for (int i = 1; i < bmp.Width - 1; i++)
{
for(int j = 1; j < bmp.Height - 1; j++)
{
float baseX = (float)i * XZScale;
float baseZ = (float)j * XZScale;

// Transform vertices
verts[vertOffset] = new DXSharp.D3D.Vertex()
{
X = baseX,
Y = ((float)bmp.GetPixel(i, j).R / 255.0f) * YScale,
Z = baseZ,
U = 0,
V = 1 * TextureScale,
NY = 1
};
verts[vertOffset + 2] = new DXSharp.D3D.Vertex()
{
X = baseX,
Y = ((float)bmp.GetPixel(i, j + 1).R / 255.0f) * YScale,
Z = baseZ + XZScale,
U = 0,
V = 0,
NY = 1
};
verts[vertOffset + 1] = new DXSharp.D3D.Vertex()
{
X = baseX + XZScale,
Y = ((float)bmp.GetPixel(i + 1, j + 1).R / 255.0f) * YScale,
Z = baseZ + XZScale,
U = 1 * TextureScale,
V = 0,
NY = 1
};
verts[vertOffset + 3] = new DXSharp.D3D.Vertex()
{
X = baseX,
Y = ((float)bmp.GetPixel(i, j).R / 255.0f) * YScale,
Z = baseZ,
U = 0,
V = 1 * TextureScale,
NY = 1
};
verts[vertOffset + 4] = new DXSharp.D3D.Vertex()
{
X = baseX + XZScale,
Y = ((float)bmp.GetPixel(i + 1, j).R / 255.0f) * YScale,
Z = baseZ,
U = 1 * TextureScale,
V = 1 * TextureScale,
NY = 1
};
verts[vertOffset + 5] = new DXSharp.D3D.Vertex()
{
X = baseX + XZScale,
Y = ((float)bmp.GetPixel(i + 1, j + 1).R / 255.0f) * YScale,
Z = baseZ + XZScale,
U = 1 * TextureScale,
V = 0,
NY = 1
};

vertOffset += 6;
}
}

А результат — такой! Это самый простой кейс с Terrain'ом: в реальных играх, где ландшафт достаточно большой, его обычно бьют на так называемые патчи и дальние участки ландшафта упрощают с помощью специальных алгоритмов. Таким образом построены ландшафтры, например, в TES Skyrim.

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

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

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

Этот способ даёт возможность использовать всего лишь две текстуры за один проход, в современных играх используется сплат-маппинг, позволяющий использовать более 4х-текстур за один проход!

Context.SetTextureStageState(1, (int)TextureStageState.AlphaOp, (int)TextureStageOp.Modulate);
Context.SetTextureStageState(1, (int)TextureStageState.AlphaArg1, (int)TextureArgument.Texture);
Context.SetTextureStageState(1, (int)TextureStageState.AlphaArg2, (int)TextureArgument.Texture);

Context.SetTextureStageState(0, (int)TextureStageState.ColorOp, (int)TextureStageOp.SelectArg1);
Context.SetTextureStageState(0, (int)TextureStageState.ColorArg1, (int)TextureArgument.Texture);
Context.SetTextureStageState(0, (int)TextureStageState.ColorArg2, (int)TextureArgument.Texture);

Context.SetTextureStageState(1, (int)TextureStageState.ColorOp, (int)TextureStageOp.BlendDiffuseAlpha);
Context.SetTextureStageState(1, (int)TextureStageState.ColorArg1, (int)TextureArgument.Texture);
Context.SetTextureStageState(1, (int)TextureStageState.ColorArg2, (int)TextureArgument.Current);

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

Но тем не менее, выглядит вполне прикольно. Однако текстуры вдали выглядят слишком грубо и отдают пикселями. Ретро-стайл скажете вы? Согласен, но фильтрация и мипмаппинг здесь необходимы! Мип-маппинг — это техника, которая делит большую текстуру на несколько небольших разного размера. Каждый размер называется mip-уровнем и в два раза меньше прошлого: таким образом, у текстуры 256x256 9 уровней: 256x256, 128x128, 64x64 и так до 1x1. Мой самопальный конвертер текстур в собственный формат заранее «запекает» все мип-уровни, дабы быстро грузить текстуры с медленных HDD, а линейная фильтрация с мипмаппингом позволяет сгладить текстуры вдали, дабы они не резали глаза:

device->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_LINEAR);
device->SetTextureStageState(0, D3DTSS_MINFILTER, D3DFILTER_LINEAR);
device->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DFILTER_LINEAR);

device->SetTextureStageState(1, D3DTSS_MIPFILTER, D3DTFP_LINEAR);
device->SetTextureStageState(1, D3DTSS_MINFILTER, D3DFILTER_LINEAR);
device->SetTextureStageState(1, D3DTSS_MAGFILTER, D3DFILTER_LINEAR);

Ну и давайте же посадим немного деревьев на наш ландшафт! Для этого я добавил псевдослучайное добавление деревьев и кустов при генерации геометрии ландшафта:

if (rand.Next(0, 32) % 8 == 0)
foliageBatches.Add(new FoliagePlacement()
{
Mesh = foliage[rand.Next(0, foliage.Length)],
Position = new Vector3(baseX, ((float)bmp.GetPixel(i, j).R / 255.0f) * YScale, baseZ)
});

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

Упс, наши деревья — черные! А всё потому, что у них нет альфа-канала, благодаря которому видеокарта может отделить прозрачные пиксели текстуры от непрозрачных. Полноценный альфа-блендинг (полупрозрачность) здесь слишком дорогой, поэтому приходится использовать технику, называемую колоркеями (Color key). Техника очень схожая с Chromakey, благодаря которым вырезают фон из видео, но чуть попроще (тем, что цвет прозрачности фиксированный, без Threshold). У нас есть определенный цвет, который считается прозрачным и не используется во всей картинке. Нередко это Magenta, в моём случае — полностью чёрный:

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

Включаем колоркей и наслаждаемся прозрачными деревьями на фоне ландшафта!

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

Ой-ой, а FPS то успел просесть с 1.000 до 50 из-за большого количества DIP'ов (и не очень хорошей работе современных GPU с старыми гапи). Время оптимизаций! Пока что нам хватит обычного Frustum culling'а, также известного как «отсечение по пирамиде видимости». Суть алгоритма простая: из матрицы вида и проекции строятся 6 плоскостей, каждая из которых описывает одну из сторон системы координат: левая, правая, верхняя, нижняя, ближняя и дальняя. Таким образом, делая обычную проверку нахождения точки в World-space и одной из плоскостей, мы можем отсечь невидимую глазам геометрию и не тратить ресурсы GPU и CPU на отрисовку невидимой геометрии:

public void Calculate(Matrix viewProj)
{
float[] items = viewProj.Items;
Planes[0] = new Vector4(items[3] - items[0], items[7] - items[4], items[11] - items[8], items[15] - items[12]);
Planes[0].Normalize();
Planes[1] = new Vector4(items[3] + items[0], items[7] + items[4], items[11] + items[8], items[15] + items[12]);
Planes[1].Normalize();
Planes[2] = new Vector4(items[3] + items[1], items[7] + items[5], items[11] + items[9], items[15] + items[13]);
Planes[2].Normalize();
Planes[3] = new Vector4(items[3] - items[1], items[7] - items[5], items[11] - items[9], items[15] - items[13]);
Planes[3].Normalize();

Planes[4] = new Vector4(items[3] - items[2], items[7] - items[6], items[11] - items[10], items[15] - items[14]);
Planes[4].Normalize();
Planes[5] = new Vector4(items[3] + items[2], items[7] + items[6], items[11] + items[10], items[15] + items[14]);
Planes[5].Normalize();
}

// Allocation-less
public bool IsPointInFrustum(float x, float y, float z)
{
foreach(Vector4 v in Planes)
{
if (v.X * x + v.Y * y + v.Z * z + v.W <= 0)
return false;
}

return true;
}

public bool IsSphereInFrustum(float x, float y, float z, float radius)
{
foreach (Vector4 v in Planes)
{
if (v.X * x + v.Y * y + v.Z * z + v.W <= -radius)
return false;
}

return true;
}

Затем проверяем, находится ли сфера внутри каждой из 6 плоскостей и если нет, то не рисуем геометрию вообще:

if (mesh.Radius > 0 && !Camera.IsSphereVisible(position, mesh.Radius))
return;

С учётом всех оптимизацией, получаем 17-20 кадров на этом GPU что можно считать… весьма неплохим результатом, учитывая что всё ещё есть куда оптимизировать!

❯ Звук


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


Инициализация контекста DSound начинается с создания primary-буфера, который выступает в роли микшера перед отправкой звука на аудио-карту. Создаётся он довольно легко:

BufferDescription desc = new BufferDescription();
desc.Flags = BufferFlags.PrimaryBuffer | BufferFlags.Control3D;

primaryBuffer = Context.CreateSoundBuffer(desc);

После этого, в самом простом случае (без стриминга звука) нам достаточно лишь выгрузить PCM-поток на аудио-карту и начать его играть:

public WaveBuffer(WaveFormat fmt, byte[] pcmData)
{
BufferDescription desc = new BufferDescription();
desc.BufferBytes = (uint)pcmData.Length;
desc.Flags = BufferFlags.ControlDefault |BufferFlags.Software;
desc.Format = fmt;

buffer = Engine.Current.Sound.Context.CreateSoundBuffer(desc);
IntPtr data = buffer.Lock();
Marshal.Copy(pcmData, 0, data, pcmData.Length);
buffer.Unlock();

buffer.Play();
}

И всё! Да, вот так легко. BufferFlags.Software заменяется на Hardware, если необходимо аппаратное ускорение.

❯ Ввод


Пожалуй, это самая простая часть нашей статьи :) Как я уже говорил ранее, никакого особого функционала от модуля обработки ввода не нужно, лишь получать состояние кнопок — и с этим справляется лишь один метод…

[DllImport("user32.dll")]
static extern short GetAsyncKeyState(Keys vKey);

public static bool GetKeyState(Keys key)
{
return (GetAsyncKeyState(key) & 0x8000) != 0;
}


Ну что ж, основа готова, давайте перейдем к реализации самого геймплея!

❯ Пилим геймплей


Сначала нам нужно реализовать логику полёта нашего самолётика. В целом, в нашем конкретном кейсе всё просто — для поворотов используем углы Эйлера (лень было писать класс для кватерниона), считаем Forward-вектор (вектор, указывающий на направление прямо) и просто крутим повороты по оси X и Y в нужную сторону, прибавляя к позиции самолетика Forward вектор, умноженный на скорость полёта. Правда, с таким подходом есть некоторые проблемы: выполнить петлю не получится, поскольку Forward-вектор всегда смотрит именно прямо и не учитывает обратную направленность по оси X.

Rotation.X += -v * (YawSpeed * Engine.Current.DeltaTime);
Rotation.Y += h * (YawSpeed * Engine.Current.DeltaTime);

Rotation.Z = MathUtils.Lerp(Rotation.Z, 35 * -h, 4.0f * Engine.Current.DeltaTime);

Vector3 fw = GetForward();
Position.X += fw.X * (Speed * Engine.Current.DeltaTime);
Position.Y += fw.Y * (Speed * Engine.Current.DeltaTime);
Position.Z += fw.Z * (Speed * Engine.Current.DeltaTime);

Мы с вами хотим, чтобы камера всегда следила за нашим самолётиком. Для этого нужно взять Forward-вектор объекта и умножить каждую его компоненту на дальность от источника камеры. Эдакая бомж-версия lookat, правда с кучей ограничений, как минимум с Gimbal lock (потерей одной из осей поворота), а чтобы камера казалась плавной и придавала динамичности игре — мы делаем EaseIn/EaseOut эффект путём неправильного использования формулы линейной интерполяции :)

Vector3 forward = GetForward();
// Adjust camera
Engine.Current.Graphics.Camera.Position = new Vector3(Position.X + (forward.X * -12.0f),
Position.Y + (forward.Y * -12.0f) + 4.0f, Position.Z + (forward.Z * -12.0f));
Engine.Current.Graphics.Camera.Rotation.Y = MathUtils.Lerp(Engine.Current.Graphics.Camera.Rotation.Y, Rotation.Y + (yaw * 30), 3.0f * Engine.Current.DeltaTime);
Engine.Current.Graphics.Camera.Rotation.X = MathUtils.Lerp(Engine.Current.Graphics.Camera.Rotation.X, Rotation.X + (pitch * 5), 3.0f * Engine.Current.DeltaTime);
Engine.Current.Graphics.Camera.MarkUpdated();

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

Ну, летать мы с вами уже можем… да, сильно по аркадному, но всё же :) Пришло время реализовать каких-нибудь соперников, а именно вражеские самолёты! Вообще, реализация нормального ИИ на самолетах, тем более в симуляторах — задачка очень нетривиальная, поскольку боты будут либо читерить, используя не те рычаги, что использует игрок, либо тупить и играть будет не сильно интересно. Вон, что «Варгейминг», что «Гайдзины» крутые в этом плане — я б ниасилил нормальных ботов для мультиплеерного симулятора или даже аркады :))

Вычисляем угол между позицией самолетика соперника и позицией игрока и интерполируем текущий угол по оси Y: получается вполне плавно, правда в нормальных играх ещё и компенсируют эффект «плаванья» вокруг игрока по синусоиде. Для подъёма и спуска по вертикали просто берём абсолютную величину выше/ниже:

float angle = (float)Math.Atan2(Game.Current.Player.Position.X - Position.X, Game.Current.Player.Position.Z - Position.Z);
float vert = MathUtils.Clamp(Position.Y - Game.Current.Player.Position.Y, -1, 1);
Rotation.X = MathUtils.Lerp(Rotation.X, vert * 35, 1.5f * Engine.Current.DeltaTime);

float prevY = Rotation.Y;
Rotation.Y = MathUtils.Lerp(Rotation.Y, angle * MathUtils.RadToDeg, 1.5f * Engine.Current.DeltaTime);
float diffY = Rotation.Y - prevY > 0 ? 1 : -1;
Rotation.Z = MathUtils.Lerp(Rotation.Z, 15 * -diffY, 4.0f * Engine.Current.DeltaTime);

Наши боты будут читерить, причём жёстко. Они будут иметь значительно большую маневренность, нежели игрок, но при этом их скорость будет сильно медленнее игрока, дабы можно было их обогнать и стряхнуть с хвоста.

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

Ну что ж, демка у нас есть и в этот раз я подготовился получше, чем в статье про 3dfx Voodoo: я собрал целых два тестовых стенда и попросил у подписчиков потестировать демку на своих машинах с диковинным железом из 90-х и нулевых годов. Железо у нас такое:

  • Процессор: Celeron 600MHz Coppermine

  • ОЗУ: 192Mb SDRAM 133MHz

  • GPU: Asus GeForce 4 MX420

  • ОС: WinXP SP3

Сам написал, сам полетал: как и зачем я разработал 3D-игру с нуля под компьютеры из 90-х в 2024 году? Опрос, Горячее, Ништяки, Программирование, Net, 3D графика, Игры, Леталки, Пилот, Самолет, Fw-190, Directx, Gamedev, Видео, Без звука, Длиннопост

На Win98 я так и не смог нормально накатить драйвера на MSDC (Mass Storage Device Class — «флэшки»), поэтому «считерил» и поставил WinXP. Изначально я планировал ставить Win2000 — но там .NET 2.0 работает с косяками (при том что этот же самый .NET работает на Win98!).

❯ Тесты


Давайте же посмотрим, как демка идёт на трушном железе. Для наглядности, я решил записать видео.

Переходим к интегрированной графике, а именно к EEEPC 701 4G с Intel GMA 900 на борту! Те, кто знают что такое GMA, понимают насколько эти встройки не приспособлены для игр. Несмотря на наличие поддержки вторых шейдеров, из-за отсутствия аппаратного вершинного конвейера чип ничего не тянет. Но моя игрушка — исключение и она работает на удивление очень даже неплохо! 15-20 кадров точно есть и это при том что есть куда оптимизировать!

А дальше у нас идут тесты от подписчиков в Telegram-канале, которым я скинул билд и пригласил потестить демку на ретро-железе. Первый тест от читателя на ноутбуке с Pentium III и редкой встройкой Trident CyberBlade XP показал весьма неплохой результат — 15-20 кадров:

Дальше тот же читатель, имя которое он просил не раскрывать, потестил демку на ATI Rage M6 — очень и очень бодрый GPU, который выдает стабильные 20-25-30 кадров!

❯ Заключение


Вот такая демка, мини-игрушка у меня получилось. Да, весьма примитивненько, зато прикольно, запилено за пару дней и можно полетать на виртуальных самолетиках. Также у меня есть Telegram-канал, куда я публикую различные мысли связанные с подручным ремонтом, моддингом и программированием под гаджеты прошлых лет, а также публикую туда ссылки на новые статьи и видео! Найти исходный код демки вы можете на моём Github.

Понравилась статья? Пишите своё мнение в комментариях, я старался :)

Статья подготовлена при поддержке TimeWeb.Cloud. Подписывайтесь на меня и @Timeweb.Cloud, чтобы не пропускать новые статьи каждую неделю!

Статья...
Всего голосов:
Показать полностью 20 4 1
73

Делаем вентилятор умным или как улучшить микроклимат в ванной комнате с помощью домашней автоматизации

Автор текста: CyberexTech

Делаем вентилятор умным или как улучшить микроклимат в ванной комнате с помощью домашней автоматизации Гаджеты, Умный дом, Timeweb, Arduino, Электроника, Техника, Своими руками, Самоделки, Сборка, Длиннопост

Привет, Пикабу!

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

❯ Подопытный


В качестве подопытного был выбран вентилятор AURAMAX OPTIMA 5 от компании ERA Group.

Технические характеристики данного вентилятора:

Делаем вентилятор умным или как улучшить микроклимат в ванной комнате с помощью домашней автоматизации Гаджеты, Умный дом, Timeweb, Arduino, Электроника, Техника, Своими руками, Самоделки, Сборка, Длиннопост

Ниже на изображении показан внешний вид вентилятора:

Делаем вентилятор умным или как улучшить микроклимат в ванной комнате с помощью домашней автоматизации Гаджеты, Умный дом, Timeweb, Arduino, Электроника, Техника, Своими руками, Самоделки, Сборка, Длиннопост

Как можно видеть, корпус вентилятора имеет место с прорезями на лицевой стороне, которое идеально подходит для установки датчика температуры и влажности. Однако внутреннее пространство достаточно ограничено для размещения управляющей электроники, что нужно будет учесть при проектировании принципиальной схемы и печатных плат. Ну и в лучших традициях DIY — разработку управляющей электроники мы будем делать самостоятельно.

❯ Разработка электроники


Ядром нашей системы управления будет ESP8266 — бюджетный микроконтроллер от компании Espressif Systems с интерфейсом Wi-Fi, который позволяет выполнить интеграцию в системы умного дома или обеспечить автономное функционирование. И так как мы ограничены в пространстве для размещения электроники внутри корпуса вентилятора, то я решил применить в качестве источника питания бестрансформаторное решение на базе высоковольтного импульсного стабилизатора напряжения LNK306GN, а для коммутации силовой цепи вентилятора будем использовать симистор. Ниже представлена принципиальная схема нашей системы управления.

Делаем вентилятор умным или как улучшить микроклимат в ванной комнате с помощью домашней автоматизации Гаджеты, Умный дом, Timeweb, Arduino, Электроника, Техника, Своими руками, Самоделки, Сборка, Длиннопост

В данной схеме в качестве датчика температуры и влажности используется DHT22, а для звукового оповещения о включении или выключении вентилятора используется пьезоэлектрический бузер со встроенным генератором. Также на схеме вы можете заметить Zero Cross датчик, который реализован на оптроне U2. Данный датчик предполагалось использовать в реализации системы импульсно-фазового управления для регулировки скорости вращения вентилятора, но как показала практика, ESP8266 не «вывез» «хотелок» разработчика. Данную систему целесообразнее реализовывать на отдельном маломощном микроконтроллере типа Attiny 2313 и тому подобное. В настоящее время данный датчик задействован в функции аппаратного прерывания для включения/выключения вентилятора в момент перехода через нуль.

Если интересно, то вот осциллограмма работы zero cross датчика^

Делаем вентилятор умным или как улучшить микроклимат в ванной комнате с помощью домашней автоматизации Гаджеты, Умный дом, Timeweb, Arduino, Электроника, Техника, Своими руками, Самоделки, Сборка, Длиннопост

Осциллограмма работы zero cross датчика

Как я писал ранее, источник питания реализован на ШИМ контроллере LNK306GN, где выходное напряжение в 3.3 В задается обратной связью, которая формируется с помощью резисторов R1 и R5. Увеличиваем номинал R5, соответственно, увеличивается выходное напряжение источника питания. Для силового управления вентилятором используется «классическая» схема на базе оптрона с симисторным выходом (U3) и силового симистора (Q1). Ниже представлены скриншоты разводки и рендера печатных плат.

Разводка:

Делаем вентилятор умным или как улучшить микроклимат в ванной комнате с помощью домашней автоматизации Гаджеты, Умный дом, Timeweb, Arduino, Электроника, Техника, Своими руками, Самоделки, Сборка, Длиннопост

Рендер 3D модели:

Делаем вентилятор умным или как улучшить микроклимат в ванной комнате с помощью домашней автоматизации Гаджеты, Умный дом, Timeweb, Arduino, Электроника, Техника, Своими руками, Самоделки, Сборка, Длиннопост

❯ Изготовление печатных плат


Настало время изготовления печатных плат. Прототипы, как правило, я изготавливаю в «домашних» условиях с помощью моего компактного лазерного станка, методом, о котором я писалранее.

Ниже на фото показан процесс активации фоторезиста с помощью 445нм лазера:

Делаем вентилятор умным или как улучшить микроклимат в ванной комнате с помощью домашней автоматизации Гаджеты, Умный дом, Timeweb, Arduino, Электроника, Техника, Своими руками, Самоделки, Сборка, Длиннопост

После засветки фоторезиста, необходимо выполнить проявку в растворе гидроксида натрия (10%) или карбоната натрия, кому как нравится.

Платы после процесса проявки:

Делаем вентилятор умным или как улучшить микроклимат в ванной комнате с помощью домашней автоматизации Гаджеты, Умный дом, Timeweb, Arduino, Электроника, Техника, Своими руками, Самоделки, Сборка, Длиннопост

Далее, после травления плат, выполняем монтаж радиокомпонентов в соответствии с принципиальной схемой и после этого производим тестовое включение и отладку. Для улучшения диэлектрических характеристик модуля питания, так как плата работает с высоким напряжением и во избежании пробоя, была нанесена паяльная маска. Чтобы предотвратить преждевременную аннигиляцию платы источника питания, рекомендую выполнять тесты с последовательно подключенной нагрузкой (в моём случае это лампа накаливания 60 Вт) в цепь питания 220 В. Также не стоит пренебрегать элементарными правилами электробезопасности при выполнении данных работ, так как модуль питания не имеет гальванической развязки с сетью.

❯ Установка печатных плат в корпус вентилятора


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

Размещение печатных плат на корпусе вентилятора:

Делаем вентилятор умным или как улучшить микроклимат в ванной комнате с помощью домашней автоматизации Гаджеты, Умный дом, Timeweb, Arduino, Электроника, Техника, Своими руками, Самоделки, Сборка, Длиннопост

❯ Прошивка и интерфейс


Устройство работает на базе моей прошивки, которую уже можно назвать стандартом для моих умных устройств. Разработка велась в средеArduino IDE. Исходный код прошивки будет доступен в конце статьи.

Конфигурация устройства классическая — через web интерфейс. При первоначальном подключении, устройство создает точку доступаCYBEREX-SmartFANс беспарольным доступом. После подключения к точке доступа, у пользователя автоматически откроется страница авторизации, где необходимо будет ввести пароль по умолчанию "admin". После входа необходимо выполнить все необходимые настройки устройства. Интерфейс простой и интуитивно понятный. Ниже представлены скриншоты интерфейса.

Страница входа и основная:

Делаем вентилятор умным или как улучшить микроклимат в ванной комнате с помощью домашней автоматизации Гаджеты, Умный дом, Timeweb, Arduino, Электроника, Техника, Своими руками, Самоделки, Сборка, Длиннопост

Страницы конфигурации передачи данных и автоматического режима:

Делаем вентилятор умным или как улучшить микроклимат в ванной комнате с помощью домашней автоматизации Гаджеты, Умный дом, Timeweb, Arduino, Электроника, Техника, Своими руками, Самоделки, Сборка, Длиннопост

Конфигурация Wi-Fi подключения:

Делаем вентилятор умным или как улучшить микроклимат в ванной комнате с помощью домашней автоматизации Гаджеты, Умный дом, Timeweb, Arduino, Электроника, Техника, Своими руками, Самоделки, Сборка, Длиннопост

Как я писал ранее, устройство может работать как в составе системы «Умный дом», так и в автономном режиме. Для интеграции в системы умного дома используется протокол MQTT, где обмен данными выполняется в формате JSON. Ниже представлен пример вывода (топик «ваше имя корня»/jsondata):

{
"c": "Off",
"temp": "29.00",
"hum": "49.70",
"a": "1",
"h_on": "65.00",
"h_off": "52.00",
"fan_level": "0.00"
}

Для управления вентилятором используется топик «ваше имя корня»/control, где переданное значение:

0 - включает или отключает вентилятор в зависимости от текущего состояния;
возвращаемый статус: On или Off
1 - включает автоматический режим работы;
2 - выключает автоматический режим работы;
возвращаемый статус: 0 или 1

Ниже показан пример «карточки объектов» данного вентилятора в системе умного дома Home Assistant:

Делаем вентилятор умным или как улучшить микроклимат в ванной комнате с помощью домашней автоматизации Гаджеты, Умный дом, Timeweb, Arduino, Электроника, Техника, Своими руками, Самоделки, Сборка, Длиннопост

График относительной влажности в ванной комнате:

Делаем вентилятор умным или как улучшить микроклимат в ванной комнате с помощью домашней автоматизации Гаджеты, Умный дом, Timeweb, Arduino, Электроника, Техника, Своими руками, Самоделки, Сборка, Длиннопост

Хочется добавить, что в данном устройстве реализован механизм MQTT Auto Discovery, позволяющий в автоматическом режиме добавлять датчики и переключатели в Home Assistant. Ниже представлен пример кода карточки объектов, позволяющий реализовать отображение датчиков и элементов управления на панели Home Assistant:

type: entities
entities:
- entity: switch.f_onoff
name: Управление вентилятором
- entity: sensor.smart_fan_temp
name: Температура
- entity: sensor.smart_fan_hum
name: Влажность
- entity: switch.smart_fan_auto_switch
name: Автоматический режим
- entity: sensor.smart_fan_hum_on
name: Порог включения
- entity: sensor.smart_fan_hum_off
name: Порог выключения
title: Вентилятор в ванной

❯ Итоги & Выводы


Давайте подведем итоги. Как можно видеть, мы реализовали очень полезную и необходимую систему, которая позволяет с минимальным бюджетом автоматизировать вытяжные вентиляторы для достижения качественных показателей микроклимата в ванной комнате. Как я уже говорил ранее, данная система может работать как автономно, так и в составе умного дома, что позволяет упростить процесс автоматизации без применения IoT инфраструктуры. И если сравнивать финансовые затраты на реализацию моего DIY проекта, описанного в данной статье, с готовыми решениями, например с обычным вентилятором со встроенным датчиком влажности, то DIY явно побеждает не только с финансовой точки зрения, но и по функциональности. Ниже приведены примерные затраты на реализацию данного решения:

  • Микроконтроллер ESP8266 — 1 шт: 94 руб или $ 1,07

  • Контроллер питания LNK306GN-TL — 1 шт: 95 руб или $ 1,09

  • Датчик температуры и влажности DHT22(AM2320) — 1 шт: 98 руб или $ 1,12

  • Оптрон с симисторным выходом MOC3052 — 1 шт: 141 руб или $ 1,61

  • Силовой симистор BT136-600(TO-252) — 1 шт: 9 руб или $ 0,10

  • Вентилятор AURAMAX OPTIMA 5 — 1 шт: 890 руб или $ 10,17

  • Другие компоненты и материалы: ~ 200 руб или $ 2,29

  • ИТОГО : ~ 1327 руб или $ 15,17


Если сравнивать с готовым решением, то цена на обычный вентилятор с автоматическим управлением от встроенного датчика, где нет и намека на интеграцию с системами умного дома, начинается от 2939 руб или $ 33,59. Вывод об экономической эффективности нашего DIY проекта напрашивается сам собой.

Если Вам понравилась статья, поддержите её стрелочкой вверх. А если есть что добавить, то добро пожаловать в комментарии. Всем творчества, добра и спасибо за внимание.

Ссылки к статье:

Делаем вентилятор умным или как улучшить микроклимат в ванной комнате с помощью домашней автоматизации Гаджеты, Умный дом, Timeweb, Arduino, Электроника, Техника, Своими руками, Самоделки, Сборка, Длиннопост

Написано специально для Timeweb Cloud и читателей Пикабу. Больше интересных статей и новостей в нашем блоге на Хабре и телеграм-канале.

Хочешь стать автором (или уже состоявшийся автор) и есть, чем интересным поделиться в рамках наших блогов — пиши сюда.

Облачные сервисы Timeweb Cloud — это реферальная ссылка, которая может помочь поддержать авторские проекты.

Показать полностью 15
116

"Отечественные" частотники ОВЕН

"Отечественные" частотники ОВЕН Техника, Электроника, Импортозамещение, Овен, Частотный преобразователь

При всем уважении к компании ОВЕН, документация отвратительная, но это уже традиция. Сам частотник ПЧВ1 М1 вполне рабочий, но хочу поддержать действительно отечественное производство, чтобы самобытно наш, а не собранный по лицензии. Кто такие делает? Понятно, что элементная база - импорт, но чтобы ПО и проектирование точно наши.

Показать полностью 1
14

TSMC подымает цены на всю продукцию

🌐 Заказчики 3-нм продукции TSMC согласились на повышение цен в обмен на условие, что тайваньский гигант будет продолжать поставки полупроводников в необходимых объемах.

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

🎫 Согласно Morgan Stanley, TSMC достигла соглашения, согласно которому клиенты приняли увеличение цен на полупроводники, но при условии, что завод будет своевременно выполнять заказы. В 2025 году рост валовой прибыли TSMC составит 55,1 %, а в 2026 году подпрыгнет еще на 60 %.

💭 Именно этого и добивается полупроводниковый техногигант. С ростом валовой прибыли компания планирует тратить больше средств модернизацию производства, в том числе увеличить инвестиции в разработку 2-нм техпроцесса.

🔻 Готовьтесь к значительному росту цен на ПК комплектующие.

#TSMC #Цены

TSMC подымает цены на всю продукцию Экономика, Tsmc, Производство, Промышленность, Электроника, Процессор, Видеокарта, Компьютер, Тайвань, Цены, Бизнес, Микроэлектроника
80

Ржомба

Давненько я не делал арт-объектов. Но наконец долгострой доделан, встречайте — ржомба. (Видео в конце поста)

Ржомба Арт, Современное искусство, Инсталляция, Перформанс, Рукоделие без процесса, Техника, Видео, YouTube, Длиннопост

Тактический боеприпас, разработан в Чугуноуральском НИИ Тактического юмора. После активации травит токсичные шутки, все в радиусе поражения умирают или со смеху, или с испанского стыда, или как сейчас говорят кринжа.

Ржомба Арт, Современное искусство, Инсталляция, Перформанс, Рукоделие без процесса, Техника, Видео, YouTube, Длиннопост

Идея арт-объекта пришла ко мне когда я смотрел видео где в один из моментов Стас Асафьев говорит «ржомба», меня осенило — прикольное название для штуки. Идея практически сразу выкристаллизовалась и я начал делать корпус.

Ржомба Арт, Современное искусство, Инсталляция, Перформанс, Рукоделие без процесса, Техника, Видео, YouTube, Длиннопост

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

Ржомба Арт, Современное искусство, Инсталляция, Перформанс, Рукоделие без процесса, Техника, Видео, YouTube, Длиннопост

Мне надоело об него спотыкаться и я решил проект доделать. Самое сложное оказалось — нарыть короткие шутки за которые не присядешь по статьям за экстремизм, оскорбление чувств верующих, дискредитацию, пропаганду ЛГБТ и тд. (еще один артъобьект из-за изменения в законодательстве придется как-то переделывать, недоделанным лежит слишком долго) Пришлось разбавлять безобидными, вроде «колобок повесился». Озвучивал я их при помощи бота максима — это тот всратый голос из донатов.

Ржомба Арт, Современное искусство, Инсталляция, Перформанс, Рукоделие без процесса, Техника, Видео, YouTube, Длиннопост

Алгоритм работы: после нажатия кнопки ПУСК идет вступление, потом шутка 1, отбивка, шутка 2, отбивка, шутка 3, завершающая реплика. Всего в пуле около 100 шуток, так что может шутить минут 40 не повторяясь. Электроника на ардуине + dfrobot minimp3.

Брутальной ржомбе — брутальный разъем

Ржомба Арт, Современное искусство, Инсталляция, Перформанс, Рукоделие без процесса, Техника, Видео, YouTube, Длиннопост

Что же хотел сказать автор? Автор хотел натолкнуть на размышления о месте юмора в нашей жизни и культуре. И его месте в интеллекте, все-таки юмор больше про социальный интеллект. Есть вот такая интересная картинка: (переведена пикабушником @dazzl3one, )

Ржомба Арт, Современное искусство, Инсталляция, Перформанс, Рукоделие без процесса, Техника, Видео, YouTube, Длиннопост

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

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

Видеоверсия:

P.S. Арт-объект был задуман до СВО, и в нынешних реалиях конечно играет несколько иными красками. Все смыслы и аналогии с современными процессами будут ложными.

Показать полностью 7 1
Отличная работа, все прочитано!