May 2007

Uwaga! Informacje na tej stronie mają ponad 5 lat. Nadal je udostępniam, ale prawdopodobnie nie odzwierciedlają one mojej aktualnej wiedzy ani przekonań.

# Napisałem FreeList

15:00
Thu
31
May 2007

Napisałem na podstawie artykułów z "Game Programming Gems" (oraz swoich pomysłów) własne alokatory pamięci do obiektów konkretnego typu, czyli tzw. FreeList. Powinny działać szybciej niż standardowe, podobno wolne operatory new i delete. Znajdą się oczywiście w nowej wersji mojej biblioteki CommonLib. Testy (przeprowadzone dla 10240 operacji alokacji lub zwalniania) są bardzo optymistyczne:

DEBUG:
Element typu int:
  FreeList : 68.0636 ms
  DynamicFreeList : 184.441 ms
  new i delete : 78.8142 ms
Element typu zajmujacego 1024 bajty:
  FreeList : 69.3896 ms
  DynamicFreeList : 203.506 ms
  new i delete : 93.2942 ms
RELEASE:
Element typu int:
  FreeList : 7.87224 ms
  DynamicFreeList : 11.4786 ms
  new i delete : 17.0348 ms
Element typu zajmujacego 1024 bajty:
  FreeList : 9.18059 ms
  DynamicFreeList : 18.0729 ms
  new i delete : 24.0537 ms

Comments | #c++ #algorithms Share

# int1, int2, int4, int8

12:41
Thu
31
May 2007

Ilekroć koledzy widzą mój kod, dziwią się, dlaczego swoje typedef-y nazwałem int1, int2, int4, int8, uint1 itd., zamiast int8, int16, int32, int64, uint8 itd. Ja wtedy pytam: Po co miałbym liczyć rozmiar w bitach, zamiast w bajtach? Wiem, że tak się najczęściej robi, ale to i tak są zawsze wielkrotności ósemki. Może w grach komputerowych za zebranie kryształka warto naliczyć graczowi całe 100 punktów zamiast jednego, bo to ma jakiś efekt psychologiczny, ale programiści powinni podchodzić do życia praktycznie. Dlatego dla mnie liczenie w bitach jest po prostu bez sensu. Operator sizeof też zwraca rozmiar w bajtach :P

Comments | #c++ #philosophy Share

# Policy-Based Design

22:27
Wed
30
May 2007

class DeletePolicy {
public:
  template <typename T>
  static void Destroy(T *p) { delete p; }
};
class ReleasePolicy {
public:
  template <typename T>
  static void Destroy(T *p) { if (p) p->Release(); }
};

class scoped_ptr<typename T, typename PolicyT = DeletePolicy>
{
public:
  explicit scoped_ptr(T *p = NULL) : m_Ptr(p) { }
  ~scoped_ptr() { PolicyT::template Destroy<T>(m_Ptr); }
  // ...
};

scoped_ptr<int, DeletePolicy> p1;
scoped_ptr<IDirect3DTexture9, ReleasePolicy> t1;

To przykład techniki zwanej Policy-Based Design, którą wynalazł Andrei Alexandrescu. Wszystkich zainteresowanych zabawami z językiem C++ zachęcam do zgłębiania tematu. Szablony to nie jest lekarstwo na wszystkie (jakże liczne) problemy rodzące się podczas programowania w tym języku, ale to jedna z potężnych i zaawansowanych technik. Znałem ją już wcześniej, ale teraz doceniłem i użyłem. Jak to się mówi w komentarzach na Allegro: Polecam! :)

Comments | #c++ #algorithms Share

# Game Programming Gems TOC

21:42
Wed
30
May 2007

Jako szczęśliwy posiadacz wszystkich sześciu tomów kultowej książki "Game Programming Gems" (trzy pierwsze tomy przetłumaczone i wydane po polsku przez Helion jako "Perełki programowania gier") często do nich zaglądam. Żeby ułatwić znalezienie konkretnego artykułu, podjąłem się zebrania spisów treści wszystkich tomów ze strony Game Programming Gems (tytuły rozdziałów w języku angielskim) i tak powstał plik GameProgrammingGemsTOC.html - zapraszam do korzystania.

Comments | #literature #teaching Share

# Pytanie o inteligentne wskaźniki

22:09
Mon
28
May 2007

Chcę sobie napisać tzw. inteligentne wskaźniki (po to żeby, przyznaję, uwolnić się od biblioteki Boost :) W związku z tym będę wdzięczny każdemu kto potrafi i znajdzie chwilę żeby odpowiedzieć na moje pytanie z tym związane w odpowiednim wątku forum.

Comments | #c++ #algorithms Share

# IntToStr, StrToInt

23:20
Fri
25
May 2007

Na dobry koniec dnia wyniki pomiaru wydajności moich nowych funkcji do konwersji między liczbą a łańcuchem - porównane z funkcjami systemowymi (plus konwersje do std::string, bo takich łańcuchów wszędzie używam i takich używają te moje funkcje). Wyniki w mikrosekundach na pojedyncze wywołanie, już podzielone przez liczbę wykonanych iteracji.

- DEBUG
  - int > string
    itoa : 0.244895 us
    IntToStr (stary) : 3.20974 us
    IntToStr (nowy) : 0.659205 us
  - string > int
    atoi : 0.270027 us
    StrToInt : 0.391424 us
- RELEASE
  - int > string
    itoa : 0.137373 us
    IntToStr (stary) : 0.225465 us
    IntToStr (nowy) : 0.134297 us
  - string > int
    atoi : 0.0785857 us
    StrToInt : 0.0589072 us

Comments | #c++ #algorithms Share

# Signed czy unsigned

14:40
Fri
25
May 2007

Czy do zapisywania rozmiaru danych, liczby bajtów, liczby elementów albo indeksu lepiej stosować liczbę całkowitą ze znakiem, czy bez znaku? Liczby ze znakiem są standardem w Delphi i mają wielu zwolenników dzięki swoim zaletom: Indeksy ujemne, jako niepoprawne, można stosować do oznaczenia wartości specjalnej (np. -1). Nie ma też obawy o "przekręcenie" przy zliczaniu w dół.

Ja jestem jednak zwolennikiem podejścia obowiązującego w C++, czyli stosowania typu bez znaku tam gdzie to możliwe (np. pod nazwą: unsigned, size_t, DWORD czy mój własny uint4). Zaleta tego podejścia to m.in. dwa razy większy dostępny zakres. Nie trzeba też sprawdzać poprawności liczby od dołu - wystarczy od góry. Jako wartości specjalnej można używać 0xFFFFFFFF (taką wartość ma na przykład stała std::string::npos zwracana przez std::string::find kiedy nic nie znaleziono).

Co wtedy z przechodzeniem tablicy w dół? Sposobem na to jest tzw. Pętla Tarlandila (tak sobie ją nazywam, bo nauczył mnie jej Tarlandil):

for (size_t i = RozmiarTablicy; i--; )
{
  Tablica[i] = 0;
}

Jak chcesz to przeanalizuj dokładnie jak działa ta sprytna pętla, a jeśli nie, to uwierz na słowo że ona naprawdę przechodzi tablicę w dół od elementu ostatniego do pierwszego i nie straszne jej przekręcenie się liczby bez znaku poniżej zera :)

Comments | #c++ #philosophy #algorithms Share

# Rzucanie wyjątków w destruktorze

13:11
Fri
25
May 2007

W języku C++ jest zasada, że nie należy rzucać wyjątków w destruktorach. Destruktor to jedyny kod, który może zostać wykonany kiedy wyjątek leci - został już rzucony, a nie został jeszcze złapany. Dzieje się tak dla obiektów utworzonych na stosie. Nie może być na raz dwóch wyjątków. Kiedy jeden leci i drugi zostaje rzucony, program się wysypuje.

Jednak czy na pewno to jest dokładnie tak? Co jeśli od czasu do czasu chcielibyśmy zrobić w destruktorze coś więcej niż tylko zwolnić pamięć, na przykład otworzyć na chwilę jakiś plik za pomocą własnej klasy strumieni, która w przypadku błędu rzuca wyjątek?

Tu będzie dobra wiadomość: MOŻNA rzucać wyjątek w destruktorze i mimo że jeden już leci, ten drugi nie spowoduje wysypania programu o ile zostanie w porę złapany i nie wyleci poza destruktor! Nie daję głowy że tak jest zawsze (nie należę do tych "językoznawców", którzy z pasją studiują standard języka uważając go za cel sam w sobie), ale sprawdziłem to na trzech kompilatorach: Visual C++ 2005 Professional, GCC 4.1.2 oraz Intel ICC 9.1.

Comments | #c++ Share

# Kolorowanie składni HLSL

11:36
Mon
21
May 2007

Kolorowanie składni HLSL

Pisząc od czasu do czasu shadery zauważyłem, że składni języka HLSL nie koloruje nic oprócz nVidia FX Composer i ATI RenderMonkey. Istnieje wprawdzie możliwość wprowadzenia takiego kolorowania do Visual C++, ale jest to paskudne obejście, które tak naprawdę zmusza Visual do traktowania plików FX jako kodu C++ i nowe słowa kluczowe koloruje również w kodzie C++. Dlatego nawet nie będę go tu podawał.

Zamiast tego napisałem wczoraj własny schemat kolorowania składni plików FX (w tym preprocesor, język HLSL i asembler shaderów do wersji 3.0) dla najlepszego edytora tekstu na świecie, czyli jEdit :) Wszystkich żądnych kolorków i niezniechęconych faktem, że ten program jest w Javie (to naprawdę jego jedyna wada) zachęcam do pobrania: hlsl.xml (20 kB). Instrukcja instalacji znajduje się w komentarzu wewnątrz pliku.

Comments | #rendering #software #productions Share

# Windows PowerShell 1.0

17:33
Sun
20
May 2007

Windows PowerShell 1.0 [Wikipedia]

Windows PowerShell 1.0 to kolejne warte uwagi znalezisko. To nowa powłoka systemowa dla Windows XP SP2 lub nowszych, zupełnie inna niż standardowy "cmd". Choć używa tego samego GUI konsoli, w środku posiada ogromny potencjał. Zobacz choćby stronę Comparison of computer shells aby przekonać się, że nie brakuje jej autouzupełniania, tablic haszujących, wyrażeń regularnych ani niczego, co powinna mieć dobra powłoka.

PowerShell przeznaczony jest wprawdzie dla administratorów i jako taki niezbyt mnie interesuje ani też nie mam pomysłu jak dobrze go wykorzystać, jednak zachwyciła mnie jego koncepcja. Sam w sobie nie posiada zbyt wiele - jest raczej platformą do dowolnej rozbudowy. Pozwala za to na tworzenie i używanie obiektów .NET, COM oraz WMI. Wiele jego elementów jest zaczerpniętych z Uniksa - jak choćby wygląd manuali. Posiada własną, całkiem przyjemną składnię. Jego obsługa jest bardzo intuicyjna i prosta do opanowania, polecenia dzielą się zasadniczo na grupy takie jak Add-, Remove-, Convert-, Out-, Format-, Write-, Set-, Get-, drzewo katalogów jest uogólnione na możliwość poruszania się po rejestrze systemowym, bazie certyfikatów itp. Jednak najgenialniejsze jest to, że dane przekazywane przez potok między poleceniami są nie surowym tekstem, ale kolekcją obiektów .NET!

Comments | #windows #tools Share

# MaPZone 2.5 - Generowanie tekstur

14:34
Sun
20
May 2007

MaPZone 2.5 to znalezisko warte uwagi - bardzo potężny program do proceduralnego generowania tekstur. Z jego użyciem każdy, kto lubi bawić się funkcjami, ma odrobinę zmysłu artystycznego (?) oraz szczyptę wytrwałości, żeby opanować jego interfejs może generować naprawdę realistyczne tekstury, łącznie z kanałem alfa czy osobną normal mapą. Tym bardziej, że program jest darmowy, a dołączonych do niego licznych, przykładowych tekstur wolno używać w swoich produkcjach, nawet tych komercyjnych.

Comments | #graphics #tools Share

# Wiadomości strategiczne

11:34
Sat
19
May 2007

Grałem ostatnio w Command & Conquer 3 Tiberium Wars i gorąco polecam wszystkim tą nową grę strategiczną. Jakkolwiek zawsze byłem większym fanem RTS-ów ze stajni Blizzarda niż tych z serii C&C (i nadal jestem), muszę przyznać, że w nowego C&C3 gra się bardzo przyjemnie. Udane połączenie serowania znanego z serii Warcraft/Starcraft z tym Command-and-conquerowym, ciekawa fabuła, pierwszorzędna grafika... Ogólnie polecam :)

Inna dobra wiadomość "strategiczna" to oficjalne już potwierdzenie że strony Blizzarda prac nad StarCraft 2. Premiera pewnie nieprędko, ale jest na co czekać :) Więcej info:

NOWE: Jeśli jeszcze tego nie zrobiłeś, wejdź na stronę StarCraft II - Movies i pobierz opublikowany 21 maja Gameplay Video. Ten ponad-20-minutowy film po prostu trzeba zobaczyć. Jest niesamowity :)

Comments | #games #web Share

# SCMP TechDemo 1.2

18:38
Thu
17
May 2007

Nowa wersja mojego dema poprawia trzy problemy:

Zachęcam do pobrania: TFQ_SCMP_TechDemo_1-2.rar (1.36 MB). Przetestujcie i powiedzcie, czy jest już znośne i czy można iść dalej z robotą :)

Comments | #productions #rendering #engine Share

# Konwencja nazywania identyfikatorów

11:46
Mon
14
May 2007

Istnieje kilka różnych sposobów nadawania nazw funkcjom, zmiennym, poleceniom, znacznikom i wszelkim identyfikatorom. Można je podzielić na:

Który z nich jest najlepszy, tego nie można jednoznacznie powiedzieć. Zamiast tego spróbuj pomyśleć, który jest najgorszy ;)

Comments | #philosophy #software engineering Share

# INF-y i NAN-y

19:01
Sun
13
May 2007

Liczby zmiennoprzecinkowe typu float czy double mogą przyjmować pewne specjalne wartości, m.in. oznaczające nieskończoność, nazywane -INF i +INF, a osiągalne w C++ za pomocą nagłówka <limits> i wywołania std::numeric_limits<float>::infinity(). Ciekawe jest, że w przeciwieństwie do liczb całkowitych dzielenie zmiennoprzecinkowe przez zero nie powoduje "wywalenia" programu, ale daje w wyniku takie właśnie nieskończoności.

Z mojego doświadczenia wynika, że zachowują się one absolutnie sensownie. -(+INF) daje -INF, -INF jest mniejsze od każdej liczby a +INF jest większe, -INF jest mniejsze od +INF, +INF - 2.f daje +INF, -INF * -2.f daje +INF itd. Zastanawia mnie więc, dlaczego wszyscy tych specjalnych wartości tak się boją, a nikt ich nie stosuje w swoim kodzie? Ostatnio znalazłem na to kolejny przykład - programiści nVidia w swoich przykładowych kodach używają liczby 1e32f jako wartości specjalnej.

Comments | #c++ #math Share

# Pakowanie Shadow Mapy do A8R8G8B8

21:55
Sat
12
May 2007

Dzisiaj dopisałem nowy tryb Shadow Mappingu, w którym używam tekstury w formacie A8R8G8B8. To już nie ma prawa nie działać :) Wartość głębokości pakuję do składowych RGB. Składowa A pozostaje do wykorzystania przez Alpha Testing. Zresztą kodując liczbę typu float i tak nie uzyskałbym dokładności większej niż 24 bity, a nawet 16 wystarczy do tego celu.

Jak to się dokładnie robi? Niełatwo znaleźć konkretne informacje na ten temat. Pomogły mi dwa tematy forum: ten i ten. Ostatecznie mój kod wygląda tak:

// Kodowanie
float v = In.ShadowMapZW.x / In.ShadowMapZW.y; // Tak naprawdę to zw
Out = v * float4( 256*256, 256, 1, 0 );
Out = frac(Out);
//Out -= Out.rrgb * float4( 0, 1.0/256.0, 1.0/256.0, 0 );

// Dekodowanie
const float4 Factors = float4(1/256/256, 1/256, 1, 0);
sample = dot(Factors, tex2D(s, t));
itd...

Ta ostatnia linijka w kodowaniu jest zakomentowana, ponieważ choć na forum zalecali ją jako niezbędna do pozbycia się artefaktów, a w moim przypadku właśnie jej usunięcie doprowadziło cienie do porządku. Rozchodzi się tutaj tak naprawdę o pytanie, czy kodując wychodzącą z Pixel Shadera wartość rzeczywistą 0.0 .. 1.0 do całkowitoliczbowego bajtu 0, 1, ..., 255 karta pozostałą część ułamkową obcina czy też zaokrągla? Ayufan twierdzi że obcina i moje doświadczenie też to potwierdza. Ale czy tak jest zawsze? Czy to jest zdefiniowane, czy zależne od konkretnej karty? Tego chyba trudno będzie się dowiedzieć...

Comments | #rendering Share

# Walczący z błędami

11:17
Sat
12
May 2007

Dzięki kolegom z Warsztatu (pozdro!), którzy w tym temacie forum odpowiedzieli na moją prośbę, znalazło się całe stado błędów w moim demie. Opisałem je pokrótce tutaj i teraz spróbuję niektóre naprawić.

Comments | #productions #warsztat Share

# The Final Quest - SCM&P TechDemo

00:01
Thu
10
May 2007

Skończyłem to nad czym pracowałem przez ostatnie tygodnie czy nawet miesiące, czyli:

Efekt można obejrzeć i wypróbować na własne oczy pobierając i uruchamiając moje nowe demo techniczne - SCMP TechDemo 1.0. Oby działało bez zarzutów na różnym sprzęcie...

Comments | #rendering #productions #engine Share

# Visual C++ - debugger wchodzi do źródeł biblioteki standardowej

21:24
Fri
04
May 2007

Ano wchodzi... Jest to szczególnie niewygodne w przypadku używania STL. Wystarczy, że podając parametry do jakiejś funkcji czy metody robimy coś przy okazji, na przykład:

Funkcja(string("Łańcuch"), MojWektor[2]);

Zadałem o tym pytanie na forum i rozwiązanie się znalazło. Trzeba otóż:

  1. Zalogować się na konto o uprawnieniach admina.
  2. Wejść do Rejestru Windows.
  3. Wejść do klucza:
    • Visual C++ 2005 Professional: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\8.0\NativeDE\StepOver
    • Visual C++ 2005 Express: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VCExpress\8.0\NativeDE\StepOver
  4. Utworzyć nową "wartość ciągu". Nazwa dowolna.
  5. Jako jej dane wpisać wyrażenie regularne oznaczające symbole, do których debugger ma nie wchodzić, np. jedno krótkie acz potężne: std\:\:.*

Ponowne uruchomienie Visuala nie jest konieczne - wystarczy nowa sesja debugowania (F5).

Nowa wersja tego wpisu (po angielsku) znajduje się TUTAJ.

Comments | #c++ #visual studio Share

# Zewnętrzny logger/monitor - genialny pomysł?

21:13
Fri
04
May 2007

Wpadłem dzisiaj na taki oto pomysł: A gdyby tak napisać zewnętrzną aplikację okienkową, na przykład w C#, która łączyłaby się z moim silnikiem poprzez jakąś komunikację międzyprocesową? Mogłaby spełniać wiele przydatnych funkcji (niektóre z nich to pomysły zaczerpnięte z artykułu o loggerze w GPG4):

Taki program miałby liczne zalety:

Każdy pomysł w pierwszej chwili wydaje się genialny. W końcu jednak górę wzięło moje lenistwo (to jednak duża rzecz i wymagałaby sporo pracy, a i komunikacji międzyprocesowej nie znam) i argument dostępu podczas pracy na pełnym ekranie. Ostatecznie postanowiłem więc zrobić wszystko In-Game - szczególnie, że mam przecież własny system GUI. Napisałem więc swój własny, prosty Property Grid:

Mój własny Property Grid

Przy okazji ciekawostka: 09 F9 11 02 9D 74 E3 5B D8 41 56 C5 63 56 88 C0 - kto wie o co chodzi, ten wie :) Jest o tym nawet piosenka - Oh Nine, Eff Nine.

Comments | #ideas #tools Share

# Accidental Complexity, Essential Complexity

22:31
Thu
03
May 2007

Accidental Complexity i Essential Complexity to pojęcia, których użył Fred Brooks w swojej książce "Mityczny osobomiesiąc" oraz artykule "No Silver Bullet". Pisząc w skrócie, złożoność każdego programu jest sumą Accidental Complexity - nadmiernej złożoności, której da się uniknąć oraz Essential Complexity - złożoności która musi być, bo, jak mówią, jeśli program ma robić 30 rzeczy, to te 30 rzeczy trzeba zaprogramować.

Pomyślałem sobie dzisiaj, że tych dwóch pojęć, oprócz udowadniania dlaczego Srebrna Kula nie istnieje i nie może istnieć, możnaby też użyć do mierzenia jakości interfejsu API bibliotek (a może też podobnie interfejsu użytkownika programów?). Polegałoby to na tym, aby:

Comments | #philosophy #software engineering Share

# Wchodząc w szczegóły

11:35
Thu
03
May 2007

Kot zadał na forum - w temacie Narzut BeginPass / EndPass - ciekawe pytanie dotyczące jak najlepszej (oczywiście z punktu widzenia wydajności) organizacji procesu renderowania obiektów w silniku, w którym wykorzystujemy mechanizm efektów FX. Temat jest o tyle ciekawy, że mnie również dotyczy :) Dlatego wszelkie odpowiedzi mile widziane.

Przy okazji padł link do ciekawego znaleziska - ktoś napisał sobie swoje My own little DirectX FAQ z kilkoma ciekawymi informacjami.

Jeszcze mały off-topic: Wszystkim kolegom piszącym w tym roku maturę życzę powodzenia i ocen dostatecznie wysokich, żeby dostali się na swoje wymarzone studia - bo w takim momencie chyba to jest dla młodego kodera najważniejsze. GL & HF :)

Comments | #rendering #directx Share

# Singletony precz!

22:55
Tue
01
May 2007

W ramach porządków w kodzie pozbyłem się dzisiaj wszystkich singletonów zamieniając je na zwykłe, globalne zmienne wskaźnikowe. Tak, wiem co sobie teraz pomyślą wszyscy obrońcy programowania obiektowego... Ja nie mam nic do OOP ani nawet do wzorców projektowych, ale jednak krócej niż res::ResManager::GetInstance().Cośtam jest napisać res::g_ResManager->Cośtam. Poza tym to działa szybciej, bo mówcie co chcecie, ale sprawdzać czy obiekt już istnieje tysiące razy na klatkę to nie jest zerowy narzut czasu.

Przede wszystkim jednak mam teraz kontrolę nad tym, kiedy obiekt powstaje i kiedy jest niszczony, bo... robię to sam. Mogę więc powiedzieć dokładnie, czy w pewnej chwili to czy tamto jest utworzone, w jakiej kolejności jest alokowane i zwalniane oraz zagwarantować, że w danym momencie dany obiekt na pewno istnieje. Słowem - mam w pełni formalnie zdefiniowany czas życia obiektów. To rozwiązało problem, który miałem podczas finalizacji różnych modułów, a z którym nie sposób było inaczej sobie poradzić. Co za ulga! A już zaczynałem wierzyć, że singletony są OK...

Comments | #c++ #philosophy #software engineering Share

STAT NO AD
[Stat] [STAT NO AD] [Download] [Dropbox] [pub] [Mirror]
Copyright © 2004-2017