Archive for Травень 2009
Щастя десь там, за планкою
Сьогодні мені здалось, що я її майже перестрибнув. Може просто вона була опущена, чи вітер дув в спину? Крім того, я почув думку про те, що в моєму АйТішному блозі забагато ІТ. Зараз зроблю його трошки попсовішим, але погода, і настрій сприяють.
Всі люди хочуть літати. Принаймі десь на підсвідомому рівні. Інакше чому всі янголи мають крила? Янголи – посередники між людиною і Богом. Вони досконаліші за нас, тому мають крила. Люди літати не вміють.
Зате люди вміють стрибати. Правда не всі пробують. Але чим більше пробуєш, тим вище стрибаєш. А чим вище стрибаєш, тим ближче наближаєшся до польоту. І завжди мусить бути планка, яку ти маєш перестрибнути.
Не низька. Низька зовсім не дає відчуття польоту. І не висока. Висока теж не дає відчуття польоту, крім того, падаючи, об неї можна боляче вдаритись. Планка має бути на волосину більша ніж ти зможеш перестрибнути.
Як визначити свою висоту? Просто щоразу ставити планку на рівень минулого результату, і ще чуть-чуть. Наприклад я вже кілька років не міг подолати 20 разову планку у кількості підтягувань. Круглизна числа 20 не давала, чи що? Просто думаєш, – “Все, зробив 20, так мало хто може, досить з мене”. Про 21 якось не думав.
Але одного разу розказав Ярославу про японський метод накачування сили волі. Найкраще розвивати силу волі в спорті. Наприклад ти три рази на тиждень бігаєш по 15хв. І ніби нормально бігаєш. Але, суть спорту полягає в тому, щоб ти щоразу за ці 15 хв пробігав більше кіл. Твоя темна сторона почне стогнати. “Ааа!!! Не муч нас! Може це навіть шкідливо? Та нащо воно тобі треба? Ти і так нормально бігаєш. Розслабся, віддихни.”. Тоді треба пригадати всі моменти, коли ця темна сторона тебе підводила, заколисувала зранку на ліжку, і ти спізнювався на контрольну, чи не познайомився з красивою дівчиною. І тут ти маєш сказати: “Ану тихо! Ти все життя мені заважаєш, і робиш всякі капості. Здохни зараза!!! Аааа-ар-рр-гррааа!!!!”. І прискорюватись на останньому крузі скільки ще сил залишилось. Так ніби далі тобі кисень, і енергія не пригодяться. Ти не вмреш. Зате твоя темна сторона постраждає. Не вмре повністю, бо та падлюка має страшну здатність до регенерації, але здоров’я в неї буде вже не те. І говорити вона менше буде. Вона буде знати хто тут головний.
Отож, коли ти якраз за сантиметр від планки, темна сторона почне опиратись. Може вона просто заздрить всім успіхам світлої. І коли ти оце відчув, знай що межа зовсім близько, і треба викласти все. А за планкою буде новий запас сил і радості. І переможна тишина в голові. Ти будеш ходити з підборіддям паралельно землі. І дивитись не собі під ноги, а в очі людям. І для тебе ця планка буде вже не планкою. Ти ж знаєш що ти можеш дати такі результати. А сама суть стрибка, який наближається до польоту в тому, що ти стрибаєш більше ніж можеш.
В бігу є подібне поняття, називається друге дихання. Чи стінка. Як от в фільмі “Біжи товстун, біжи”.
Що ще допомагає перестрибнути планку? Веселий, бойовий настрій. Весна. А ще, коли тебе бачить дівчина, з ногами … (я б порівняв з Феррарі, такі гарні і швидкі), з якою ти тренувався рік тому. Ну ти не можеш видати що ти слабак, і навіть ніякого розвитку не добився?
Ну і стрибати можна не тільки в спорті. Можна і в програмуванні. Тільки ніколи не треба розказувати іншим про висоту своєї планки. Вони подумають що ти перебільшуєш. Краще їх здивувати. Це ще одна радість від перельоту через планки.
Ослаблення.
Якщо ти не перестрибнув планку, тільки не відмовляйся зробити ще кілька сотень спроб. Можливо пізніше. Коли погода буде краща. Хоча погана погода – це не причина відступати. Займіться чимось подібним в приміщенні. Може твоя планка зависока? Тільки переконайтесь, що це не підступи темної сторони.
Якщо ніякої радості не відчуваєте, спробуйте ще кілька разів. Це також може бути підступ вашої ліні. Але коли зовсім не радує, ні діяльність, ні результат, то подумайте, може варто стрибнути в інший бік?
Ну і не забувай про відпочинок. Стрибки – найважче з того, що може людина. І забирає майже всю енергію. Для її відновлення потрібний довгий час. І коли починати стрибати до того, як вона відновилась повністю – стрибок вийде нижчим. Але і тримати запас енергії в собі довго не рекомендується. Людина також може тренувати здатність до відновлення, і збільшувати запас енергії. Називається це витривалістю. Крім того дуже допомагають зміни заняття. Не можете стрибати? Беріть драбину і лізьте на перекладину
.
А якщо ти не будеш відпочивати, ти ослабнеш, пошодиш здоров’ю, і втратиш радість від такого стилю життя.
Чого я це раптом?
Бо сьогодні я нарешті підтягнувся 21 раз, пробігся до сьомого поту, зробив хорошу розминку, і скупався в холодній воді, яка тече з гарячого крану. Ох, як кричала моя темна сторона! Але відчув себе дуже чистим, сильним, і світлим.
Подолати двадцятиразову межу підтягувань мені запропонував Ярослав Тімченко. На це пішло чотири дні.
Тепер залишилось вбити в собі лінивого програміста, і здати заліки. Чого і вам бажаю!
PS. Перша моя стаття, окрім перекладу хакерів, яку я прочитав. І навіть відредагував. Треба ж колись вчитись
Де взяти гроші?
Підле питання. Треба боятися людей, в яких таке на думці. Бо раз вони думають над цим, не думають про любов до всього людства, комунізм і Open Source. І чисті, альтруїстичні помисли, їм заступили хижі і корисливі. Хоча не все таке чорно-біле.
Але все таки можна постаратись, що щоб помимо того, що ти отримуєш прибуток, ти приносив людям користь. Принаймі в мене є велике сподівання, що все що я тут пишу, страшно сподобалось б мені, на рік молодшому. Тому, може ще комусь сподобається?Про моральність прибутків, достатньо поміркували тут. Зараз я застосую це конкретно до себе.
Для чого мені гроші? Бо хочу полазити по горах, купити собі eBook, потрохи злазити з шиї батьків. І взагалі, Білла Гейтса у моєму віці вже вигнали з Гарварду.
Співпраця
Готовий брати участь в будь-яких цікавих проектах. Навіть не комерційних. Просто заради того щоб навчитись.
Крім того, готовий дати інформаційну підтримку. Наприклад з радістю обміняюсь посиланнями. Інколи навіть ставлю зовнішні посилання просто так. Але це, якщо ви мені сподобались. Якщо ж вам сподобався я, і ви хочете мене підтримати – пишіть: tbunyk Собака ukr.net
Також можу допомогти з вивченням Pascal/Delphi, С/C++, OpenGL, PHP, HTML, і установкою Ubuntu Linux. Оплата договірна. Знову ж таки пишіть tbunyk Собака ukr.net . Липень і Серпень я в Франківську, все решта в Києві.
Реклама
А ще, я зареєструвався на російському рекламному порталі Блогун, де можна заробляти гроші ставлячи посилання. Релевантності обіцяю дотримуватись. Поки що, заради чистого експерименту.
fa56dafe4b878b4f3f06d69e6f899c74
Прибутки від Open Source
Мене завжди цікавило, як заробляють гроші програмісти які працюють над Open Source. Бо як користувач, я всією душею стою за даний напрямок, і вірю, що він приведе нас до комунізму. Але як програміст, я маю деякі сумніви, що програмісти Open Source завжи ситі. А я їсти люблю.
Так, от. Виявляється виробники безплатних продуктів також іноді заробляють непогано. По перше, це пов’язано з специфікою інтелектуального продукту. Його тиражування практично нічого не коштує. Тобто собівартість двох копій продукту дорівнює собівартості одної.
В епоху хакерів, програми були безплатними тільки тому, що їх не було кому продавати, і писали їх тільки для задоволення від самого хакінгу, і для задоволення своєї честолюбності. Таке буває і тепер. Сам таким займаюся.
Тому можна сказати, що створюючи безплатний продукт, автор має інші мотиви, окрім збагачення.
- Задоволення від творення (за безплатно мало хто робить роботу, яку не любить)
- Задоволення від щедрості (як інакше можна поділитись з мільйоном ближніх, і не стати жебраком?)
- Патріотичний мотив (Вклад кожного в розвиток рідної культури важить більше ніж матюкання влади)
- Самопіарний мотив. (Ніщо так не тішить око, як причесаний код, з власним прізвищем в коментарях)
- Просто потреба. (Можливо ця програма просто була потрібна автору)
Тим не менш, працюючи по кілька годин перед сном, не напишеш ні Firefox, ні Linux, ані OpenOffice. Такі продукти вимагають витрат, на електроенергію, на інтернет, і в кінці-кінців, якщо фірма має офіс, то на прибиральницю, і кондиціонери. Ви думаєте прибиральниця захоче працювати заради руху GNU?
Спосіб 1: Техпідтримка (Canonical)
Фірма Canonical створює дистрибутив Linux Ubuntu, покликаний завоювати ринок десктопних систем. Прибуток отримується за допомогою платної технічної підтримки. Звісно є і безплатна підтримка, але вона базується більше на великій спільноті. Подібним чином працювала фірма Red Hat, але вона була ще до моєї пам’яті, тому я точно не знаю. В цю групу, я б заніс всякі навчальні проекти. Наприклад мережну академію Cisco. Хоча вони і не виробляють відкрите ПЗ, зате в них теж є платна техпідтримка, ну і платні курси.
Спосіб 2: Продаж додаткових продуктів (Sun Microsystems).
Sun виробляє величезну кількість продуктів. Операційні системи, середовища програмування, офісні програми, веб-сервери. Суть в тому, що окрім вільної версії програми, є і платна, але з розширеними можливостями, чи умовами використання. Наприклад заміна OpenOffice – StarOffice.
Спосіб 3: Подвійна ліцензія (MySQL)
Ліцензія GPL каже, що всі продукти які базуються на продуктах з цією ліцензією мусять також бути вільно поширюваними. Таким чином стимулюється розвиток вільного ПЗ. Тому, для всіх, хто розробляє некомерційні продукти (наприклад Вікіпедію) MySQL безплатний. Але як тільки ви захочете продати свою програму, яка працює з допомогою сервера MySQL – платіть, будьте ласкаві.
Спосіб 4: Реклама (Mozilla)
Всім надоїлий, але дуже ефективний спосіб. Крім того якщо до нього підійти з розумом, то можна і клієнтам не надоїсти, і прибутки отримати. У моєму Фаєрфоксі, поруч з рядком адреси, стоїть таке маленьке, і майже непомітне поле. Воно дозволяє зручно і швидко шукати в Google, Вікіпедії, пакети Убунти, магазинах Аmazon, і eBay. Це поле поставлене за договором з даними фірмами. Правда з Убунти і Вікіпедії мало що візьмеш, але основне не гроші, основне користь, хіба ні?
За підказкою доброї людини під ніком beroal додаю ще один спосіб:
Спосіб 5:Протокол вуличного виконавця (Blender Foundation)
Спосіб базується на авторитеті творця. Творець обіцяє випустити продукт під вільною ліцензією, при умові, що на спеціальному рахунку назбирається певна сума. Її зберігає посередник (видавець). Цю суму жертвують зацікавлені в продукті особи. Якщо продукт не видається вчасно, чи не назбирується потрібна сума, всі гроші повертаються назад. А коли все в порядку – робота оплачується.
Варто зауважити, що в цій статті я постійно плутаю терміни Open Source, вільне програмне забезпечення, і GPL. Але суть у них майже однакова – програми поширюються безплатно, і з відкритим кодом.
Почитайте ще (тобто список використаної літератури):
Рендеринг тривимірної моделі
Недавно, я розказував про розшифрування формату 3ds. Це доволі поширений формат тривимірної графіки, підтримується більшістю редакторів, Blender в тому числі. І написав програмку, яка витягує з фалу 3ds дані, і записує їх в простіший текстовий формат. Але текст, це хоч і добре, але зображення завжди красивіше. Тому зараз спробуємо завантажити і намалювати тривимірну модель.
Клас, який буде відповідати за модель, назвемо TriMesh (сітка трикутників), так як моделі в основному з трикутників і складаються.
Завантаження
Завантаження відбувається просто. Читаємо символ мітки блоку, і розмір блоку. Якщо мітка ‘N’, то далі читаємо рядок – ім’я мешу. Інакше, виділяємо достатню кількість пам’яті, і читаємо координати вершин, текстурні координати, чи номери вершин трикутників, залежно від мітки. Якщо зустріли якусь неправильну мітку – виводимо повідомлення про помилку.
Відтворення
Малюємо ще простіше. Вмикаємо режим виведення трикутників, цикл по всіх трикутниках, і в тілі виводимо всі три вершини. Але, тут починаються проблеми. Якби в мене була текстура, все би було не так і погано. Але, так як я її ще не намалював, і ще не завантажив, то виводиться тільки плоский силует моделі:
Обчислення
Правда частіше за все, ми взагалі нічого не побачимо, просто тому, що неправильно відредагували модель. Наприклад вона може не стояти в центрі системи координат, і виводитись за межами екрану. А ми будем морочити собі голову тим, чому вона не виводиться. В мене так і було. Але на щастя, я здогадався, і написав метод void computeboundaries(), який обчислює центр обмежуючого паралелепіпеда для моделі, і переміщує модель так, щоб центр попав в точку (0,0,0). Також маштаб моделі може бути не таким як треба, але це я вже залишив на совість художника.
Ну, і виявляється в форматі 3ds переплутані осі Y і Z, тому я просто переставив ці дві змінні при завантаженні.
Щоб з’явилось світло, і наша модель виводилась об’ємною, потрібно обчислювати нормалі. Взагалі то нормалі обчислюються для кожної вершини, залежно від груп згладжування, але я вирішив поки що не морочити собі голову цими групами. В мене нормалі об’числюються для кожного трикутника.
Кожен трикутник лежить в площині яка задається двома векторами – якимись сторонами трикутника. Нормаль до площини – це нормалізований векторний добуток цих векторів. Оце й уся математика.
З світлом і нормалями наш корабель виглядатиме так:
Я правда змінив колір на сірий, бо чорний колір, робить з моделі абсолютно чорне тіло, а як відомо, абсолютно чорне тіло виглядає однаково, що при світлі, що в темряві. Ну, і насправді наша модель не така колюча, я просто намалював в центрі кожного трикутника нормаль, для наочності.
І ще одна думка з’явилась. Завантаження моделі я писав вчора. Сьогодні в обід встав, і виявив, що випадково, засинаючи, замінив код модуля з класом TriMesh нульовим проектом GLUT. І вбив працю всього дня. Тому от зараз написав його заново, і вирішив зберегти резезрвну копію онлайн. Бо це завантаження я пишу, вже далебі не перший раз. Треба збільшувати повторне використання коду. Як і обчислення векторного добутку.
Так отаке розчарування наштовхнуло мене на думку, що клас трикутної сітки треба спростити, викинувши зайві обчислення. Бо потім треба буде ще додавати текстури, і навіть можливо анімації. Тому в цей клас додам функцію збереження моделі, і просто зроблю програмку, яка зберігає результат переміщення в центр, і обчислення нормалей.
І варто зауважити, що код не зовсім безпечний. Якщо вам раптом повідомляють про Access Violation, чи про Segmentation fault (в *nіx системі), то перевірте, чи все завантажилось, і чи не забули ви обчислити нормалі.
Код
#ifndef MESH_H_INCLUDED
#define MESH_H_INCLUDED
#include <stdio.h>
#include <math.h>
typedef struct VertexS
{
float x,y,z;
} Vertex;
typedef struct TriangleS
{
int a,b,c;
} Triangle;
typedef struct MapCoordS
{
float u,v;
} MapCoord;
Vertex Normal(Vertex a, Vertex b, Vertex c)
{
Vertex u,v,res;
u.x=b.x-a.x;
u.y=b.y-a.y;
u.z=b.z-a.z;
v.x=c.x-a.x;
v.y=c.y-a.y;
v.z=c.z-a.z;
res.x=-u.y*v.z+u.z*v.y;
res.y=u.x*v.z-u.z*v.x;
res.z=-u.x*v.y+u.y*v.x;
return res;
}
Vertex Normalize(Vertex x)
{
float length=-sqrt(x.x*x.x+x.y*x.y+x.z*x.z);
x.x/=length;
x.y/=length;
x.z/=length;
return x;
}
class TriMesh
{
char name[30];
int vertcount,tricount;
Vertex *vertexes;
Triangle *triangles;
Vertex* normals;
MapCoord* mapping;
public:
TriMesh()
{
vertcount=0;tricount=0;
vertexes=NULL;triangles=NULL;
normals=NULL;
}
void clear()
{
if(vertexes) free(vertexes);
if(triangles) free(triangles);
if(normals) free(normals);
vertcount=0; tricount=0;
}
void LoadFromFile(char *fn)
{
clear();
FILE *f;
f=fopen(fn,"r");
if(!f)
{
printf("Error: can't open file \"%s\"\n",fn);
return;
}
char label;
int count;
while(!feof(f))
{
fscanf(f,"%c %i",&label,&count);
switch(label)
{
case 'N':
fscanf(f,"%s\n",name);
break;
case 'V':
vertcount=count;
vertexes=(Vertex *)malloc(sizeof(Vertex)*count);
for(int i=0;i<count;i++)
{
fscanf(f,"%f %f %f\n",&vertexes[i].x,&vertexes[i].z,&vertexes[i].y);
};
break;
case 'P':
tricount=count;
triangles=(Triangle *)malloc(sizeof(Triangle)*count);
for(int i=0;i<count;i++)
{
fscanf(f,"%i %i %i\n",&triangles[i].a,&triangles[i].b,&triangles[i].c);
}
break;
case 'M':
if(count!=vertcount) printf("Error: Count of mapping coords isn't equal to count of vertexes\n");
mapping=(MapCoord *)malloc(sizeof(MapCoord)*vertcount);
for(int i=0;i<count;i++)
{
fscanf(f,"%f %f\n",&mapping[i].u,&mapping[i].v);
}
break;
default:
printf("Error: Unknown label: '%s'",label);
break;
}
}
fclose(f);
}
void computeboundaries()
{
if(!vertcount) return;
Vertex min,max;
min=max=vertexes[0];
for(int i=1;i<vertcount;i++)
{
if(min.x>vertexes[i].x) min.x=vertexes[i].x;
if(min.y>vertexes[i].y) min.y=vertexes[i].y;
if(min.z>vertexes[i].z) min.z=vertexes[i].z;
if(max.x<vertexes[i].x) max.x=vertexes[i].x;
if(max.y<vertexes[i].y) max.y=vertexes[i].y;
if(max.z<vertexes[i].z) max.z=vertexes[i].z;
}
min.x=(min.x+max.x)/2; // compute center
min.y=(min.y+max.y)/2;
min.z=(min.z+max.z)/2;
for(int i=0;i<vertcount;i++) // move to center
{
vertexes[i].x-=min.x;
vertexes[i].y-=min.y;
vertexes[i].z-=min.z;
}
}
void computenormals()
{
if(!normals) normals=(Vertex *)malloc(sizeof(Vertex)*tricount);
for(int i=0;i<tricount;i++)
{
normals[i]=Normalize(Normal(vertexes[triangles[i].a],vertexes[triangles[i].b],vertexes[triangles[i].c]));
}
}
void draw()
{
glBegin(GL_TRIANGLES);
for(int i=0;i<tricount;i++)
{
glNormal3f(normals[i].x,normals[i].y,normals[i].z);
glVertex3f(vertexes[triangles[i].a].x,vertexes[triangles[i].a].y,vertexes[triangles[i].a].z);
glVertex3f(vertexes[triangles[i].b].x,vertexes[triangles[i].b].y,vertexes[triangles[i].b].z);
glVertex3f(vertexes[triangles[i].c].x,vertexes[triangles[i].c].y,vertexes[triangles[i].c].z);
}
glEnd();
}
void drawnormals()
{
Vertex centre;
glBegin(GL_LINES);
for(int i=0;i<tricount;i++)
{
centre.x=(vertexes[triangles[i].a].x+vertexes[triangles[i].b].x+vertexes[triangles[i].c].x)/3;
centre.y=(vertexes[triangles[i].a].y+vertexes[triangles[i].b].y+vertexes[triangles[i].c].y)/3;
centre.z=(vertexes[triangles[i].a].z+vertexes[triangles[i].b].z+vertexes[triangles[i].c].z)/3;
glVertex3f(centre.x,centre.y,centre.z);
glVertex3f(centre.x-normals[i].x*10,centre.y-normals[i].y*10,centre.z-normals[i].z*10);
}
glEnd();
}
void SaveToFile(char *fn)
{
if(!mapping) mapping=(MapCoord *)calloc(vertcount,sizeof(MapCoord));
FILE *f;
f=fopen(fn,"w");
fprintf(f,"%i\n",vertcount);
for(int i=0;i<vertcount;i++)
fprintf(f,"%f %f %f %f %f\n",vertexes[i].x,vertexes[i].y,vertexes[i].z,mapping[i].u,mapping[i].v);
fprintf(f,"%i\n",tricount);
for(int i=0;i<tricount;i++)
fprintf(f,"%i %i %i %f %f %f\n",triangles[i].a,triangles[i].b,triangles[i].c,normals[i].x,normals[i].y,normals[i].z);
fclose(f);
}
};
#endif // MESH_H_INCLUDED
Конструктивні наїзди приймаються
.
Розшифрування формату 3ds
Тобто перетворення з бінарного формату в текстовий, з виділенням основної інформації. Завантаження тривимірної моделі з текстового файлу не являє собою великої проблеми.
Файли 3ds складаються з кусків (chuncks). Кожен кусок містить іформацію про конкретний об’єкт. Кусок може мати підкуски. Всі вони містяться всередині одного головного.
Тривимірні моделі являють собою сітку трикутників (triangle mesh). Кожен трикутник – це номери трьох вершин (vertices), нумерація починається з нуля. А вершина – це три координати, і дві текстурні координати.
Мій конвертер базується на статті Damiano Vitulli. В ній ви можете прочитати про формат 3ds детальніше. Також є стаття на gamedev.ru.





