Pokaż wiadomości

Ta sekcja pozwala Ci zobaczyć wszystkie wiadomości wysłane przez tego użytkownika. Zwróć uwagę, że możesz widzieć tylko wiadomości wysłane w działach do których masz aktualnie dostęp.


Wiadomości - voytech

Strony: [1] 2 3 4 5 ... 63
1
Grafika 3D / Odp: Blender i światła w vertex colors
« dnia: Maj 13, 2017, 15:18:02 »
Da się, ale chyba tylko Blender Renderer to obsługuje. Nie widzę żadnych opcji dla Cycles

Obiekt na który chcesz wypalić światło musi mieć Vertex Colors. Potem w zakładce "Bake" zaznaczasz "Bake to Vertex Color" i wypalasz.

Przed chwilą sprawdzałem i chyba jest jakiś bug, bo przed kolejnym wypiekaniem nie usuwa poprzedniego rezultatu. Trzeba usunąć vertex colors i ponownie je stworzyć.

2
Na pewno prześledzę implementację.

Czekaj, może lepiej nie.

Tamten kod jest zbyt stary i brzydki. Mam obecnie coś na widoku i będzie mi potrzebna kamera
więc postanowiłem, że trochę ten kod poprawię (patrz załącznik). Dużo się jeszcze zmieni ale
obecnie kamera wygląda tak:
Kod: (cpp) [Zaznacz]
enum class Moves {
    FORWARD, BACK, RIGHT, LEFT, UP, DOWN, TURN_CW, TURN_CCW, TURN_UP, TURN_DOWN
};

class Camera {
    glm::vec3 _pos {0, 3, 4};
    glm::vec3 _up  {0, 1, 0};

    float _angleLeftRight =   0.0f;
    float _angleUpDown    =   0.0f;
    float _moveSpeed      = 0.005f;   
    float _rotateSpeed    =  30.0f;
   
    const float MIN_ANGLE = -85.0f;
    const float MAX_ANGLE =  85.0f;
public:
    void moveCamera( const float delta, const Moves dir) {
        switch (dir) {
        case Moves::RIGHT   : _pos += getRight() * delta * _moveSpeed; break;
        case Moves::LEFT    : _pos -= getRight() * delta * _moveSpeed; break;
        case Moves::FORWARD : _pos += getDir()   * delta * _moveSpeed; break;
        case Moves::BACK    : _pos -= getDir()   * delta * _moveSpeed; break;
        case Moves::UP      : _pos += getUp()    * delta * _moveSpeed; break;
        case Moves::DOWN    : _pos -= getUp()    * delta * _moveSpeed; break;
        case Moves::TURN_CW :
                     _angleLeftRight += delta * _moveSpeed * _rotateSpeed;
                     if (_angleLeftRight >=  360.0) _angleLeftRight -= 360.0;
                     if (_angleLeftRight <= -360.0) _angleLeftRight += 360.0;
                     break;
        case Moves::TURN_CCW:
                     _angleLeftRight -= delta * _moveSpeed * _rotateSpeed;
                     if (_angleLeftRight >=  360.0) _angleLeftRight -= 360.0;
                     if (_angleLeftRight <= -360.0) _angleLeftRight += 360.0;
                     break;
        case Moves::TURN_UP:
                    _angleUpDown += delta * _moveSpeed * _rotateSpeed;
                    if (_angleUpDown > MAX_ANGLE) _angleUpDown = MAX_ANGLE;
                    if (_angleUpDown < MIN_ANGLE) _angleUpDown = MIN_ANGLE;
                    break;
        case Moves::TURN_DOWN:
                    _angleUpDown -= delta * _moveSpeed * _rotateSpeed;
                    if (_angleUpDown > MAX_ANGLE) _angleUpDown = MAX_ANGLE;
                    if (_angleUpDown < MIN_ANGLE) _angleUpDown = MIN_ANGLE;
                    break;
        }
    }

    //setters
    void setPosition( const  glm::vec3 pos )   { _pos = pos; }
    void setAngleLeftRight( const float angle ) { _angleLeftRight = angle; }
    void setAngleUpDown( const float angle ) { // exception???
        _angleUpDown = angle;
        if (_angleUpDown > MAX_ANGLE|| _angleUpDown < MIN_ANGLE)
            _angleUpDown = 0;
    }
    void setOrientation( const float angleLeftRight, const float angleUpDown ) {
        setAngleLeftRight( angleLeftRight );
        setAngleUpDown( angleUpDown );
    }
    // getters
    glm::vec3 getRight() const          { return glm::normalize( glm::cross( getDir(), _up ) ); }
    glm::mat4 getLookAtMatrix() const   { return glm::lookAt( getPosition(), getCenter(), getUp() ); }
    glm::vec3 getPosition() const       { return glm::vec3( _pos ); }
    float     getAngleLeftRight() const { return _angleLeftRight; }
    float     getAngleUpDown() const    { return _angleUpDown; }
    glm::vec3 getCenter() const         { return glm::vec3( _pos + getDir() ); }
    glm::vec3 getUp() const             { return glm::vec3( _up ); }
    glm::vec3 getDir() const {
        float lr = glm::radians( _angleLeftRight );
        float ud = glm::radians( _angleUpDown );
        return glm::vec3(-sinf( -lr ) * cosf( ud ), sinf(  ud ), -cosf( -lr ) * cosf( ud ) );
    }
};

W przyszłości planuję zrobić kamerę bardziej elastyczną, której będzie się podawać płaszczyznę będącą dla niej "podłogą", ale na chwilę obecną to co jest działa dobrze i zachowuje się prawie tak jak w Blenderze po naciśnięciu SHIFT-f (grawitacji i regulacji prędkości poruszania się jeszcze nie ma).

Ps. jak tam twój eksporter w blenderze? W tym programiku z blendera eksportowałem do formatu Stanford "*.ply" a potem prostym skryptem przerobiłem na plik nagłówkowy "*.h".

Planujesz jakiś własny format? Binarny czy tekstowy? Jeżeli tekstowy to według mnie najlepiej jako kod źródłowy (c/c++, python, java, etc), żeby było łatwo wkleić do własnego programu jakieś proste bryły. Albo jeszcze lepiej wyeksportować jako JSON (eksportery tego pliku są dostępne w wielu językach).

3
Pogrzebałem jeszcze w moich archiwach (nudzi mi się), ciężko było ale udało mi się znaleźć prostą kamerkę którą sobie zaimplementowałem chyba przeszło 10 lat temu. Oto screen najważniejszych funkcji:

http://i.imgur.com/wkCUlce.png


Obsługuje się nią klawiszami WSAD i strzałkami. Kamera porusza się po płaszczyźnie ZX, można się obracać lewo-prawo bez ograniczeń, góra-dół od -89 do 89 stopni (przy 90 w gluLookAt będzie dzielenie przez 0 i program się wysypie, poza tym nie chciałem mieć gimbal-locka).

Nie ma tutaj żadnych klas i encapsulacji, więc trochę to wygląda chaotycznie, ale można nią oblatywać swobodnie scenę. Kodu jest mało (300 linijek), żadnych skomplikowanych rzeczy, parę funkcji na iloczyn wektorowy, normalizację i to wszystko. Jedyne co może być niezrozumiałe:
Kod: (c) [Zaznacz]
        static const float rad = M_PI / 180.0f;
        camera.dir[0] =  sinf(camera.lewoprawo * rad) * cosf(camera.goradol * rad);
        camera.dir[1] = -sinf(camera.goradol   * rad);
        camera.dir[2] = -cosf(camera.lewoprawo * rad) * cosf(camera.goradol * rad);

jest to kierunek kamery [0,0,-1] pomnożony przez macierz Rx a następnie przez Ry (https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations), czyli zwykły zestaw kątów Eulera (goradol,lewoprawo,0).

Zasada działania jest taka, że kamera jest stale zorientowana w kierunku -Z, góra +Y. To dla takiej orientacji są wyprowadzone te wzory. W programie strzałki modyfikują kąty góra-dół i lewo-prawo, więc wektory kamery up, dir, right są redundantne, ale je sobie trzymam i obliczam, żeby je później użyć w gluLookAt i przy przemieszczaniu kamery. Lepiej by je było zrobić polami prywatnymi a obliczenia wsadzić w gettery klasy.

Moja kamera to w zasadzie jest tylko pozycja i dwa kąty Eulera. Proste to jak drut :)

Jedynie co bym zmienił to opakował w klasę i zamiast strzałek skorzystał z myszki. Można by też dodać klawisze Q/Z do podnoszenia się i opadania (pozycja += wektor(0,1,0)*scale).

Inna opcja to skorzystać np. z biblioteki bullet phisics i przyczepić kamerkę to jakiegoś cylindra, wtedy kolizje można wykorzystać, grawitację i inne cuda.

Ps. gdyby twoja scena była w innej niż ZX płaszczyźnie to po gluLookAt można dać glRotafe, wtedy obróci to cały świat o zadany kąt i oś obrotu.

ps2. w załączniku cały kod wraz binarką prostej sceny, kompilacja i uruchamianie:
bash:~$ g++ -o main main.cpp -lSDL -lSDLmain -lGL -lGLU -lGLEW && ./main

4
Szkółka / Odp: Przeliczanie rotacji w Blenderze na rotacje w OpenGL.
« dnia: Kwiecień 30, 2017, 07:27:25 »
Najpierw sprawa z kolejnością rotacji. Próbowałem różnie ale teraz potwierdziłeś mi, że ma być ZYX. Za chwilę to pozmieniam i tego się będę trzymał. Dzięki!

Tak dla potomności, żeby zrozumieć kolejność operacji wektor-macierz w układzie prawoskrętnym:
[vx']   [a b c d]   [vx]
[vy'] = [e f g h] * [vy]
[vz']   [i j k l]   [vz]
[ 1 ]   [m n o p]   [1 ]
albo inaczej tak jak w matematyce z grubymi literkami v'=M*v

1. Przekształcamy wierzchołki macierzą Mx (obrót wokół osi X): v1=Mx*v
2. Następnie to co już żeśmy przekształcili obracamy wokół osi Y: v2=My*v1
3. Na końcu wokół osi Z: v'=Mz*v2

Teraz sobie to podstawimy:
v' = Mz*v2 = Mz * (My * v1) = Mz * (My * (Mx * v))

nawiasy można przemieścić:
v' =  (Mz * My * Mx) * v

widać z tego że macierz złożona jest z mnożeń macierzy w odwrotnej kolejności do poszczególnych operacji:
Mxyz = Mz * My * Mx
v' = Mxyz * v

Druga sprawa to układ współrzędnych Blendera i OpenGL. Po Alt+R faktycznie X jest w prawo i Y do góry. Ale kamera w Blenderze patrzy w kierunku dodatnich Z, a nie ujemnych (jak w OpenGL). Więc tu jest pewna różnica. :(

to co mówisz nie może być prawdą:



jak widać kamera jest na osi OZ na [0,0, +6], ma wyzerowaną rotację i patrzy w kierunku -Z.

Cytuj
A jeszcze mam pytanie o kamerę. Jakiej kolejności transformacji używać dla kamery? Rotacja też ZYX? Pozycję monożę przez -1.

Kamerę zawsze ustawiałem na początku, czyli glLoadIdentity, potem gluLookAt kamery a następnie rysowanie sceny (rotacje, obroty,..., glDrawElements).

Jeżeli chcesz, żeby twoja kamera patrzyła tak samo jak ta w blenderze to może spróbuj wyeksportować matrix_world kamery i na początku renderowania sceny załadować ją komendą glLoadMatrixf(). Z macierzy można odczytać jej pozycję (4ta kolumna) a także prawo(X), góra(Y) i kierunek patrzenia kamery(-Z), są one w pierwszych trzech kolumnach.

Dodawanie do pozycji kamery wektor X kamery (pierwsza kolumna macierzy) spowoduje, że kamera będzie przesuwać się w bok, coś podobnego jak w grach klawisze A/D (strafe). W/S (przód tył) to zmiana pozycji kamery o wartość wektora Z kamery, oczywiście z odpowiednio przeskalowanego.

Przy skręcaniu kamery wokół osi Y, coś jak głową lewo-prawo, trzeba obrócić wektor X i Z kamery o tę oś.

Trzeba pamiętać o tym, że te trzy wektory tworzą bazę ortonormalną, czyli mają długość 1 i są do siebie wzajemnie prostopadłe, gluLookAt zawsze tego pilnuje. Podobnie patrzenie góra-dół, czyli wokół osi X kamery obrócić wektor Y i Z. Po każdej takiej operacji warto znormalizować te wektory i sprawić żeby ponownie były prostopadłe (cross product), bo operacje błędy numeryczne mogą się skumulować i wektory rozjechać.

Wydaje mi się, że to powinno zadziałać, ale nie mam pewności i nie pamiętam jak ja to robiłem dawno temu u siebie


Obiekt w Blenderze jest obrócony:
X = 199 stopni
Y = 123 stopnie
Z = 0 stopni

W Python Console Blendera sprawdzam:

C.selected_objects[0].matrix_world.to_euler()
Euler((0.3316124677658081, 0.9948376417160034, 3.1415927410125732), 'XYZ')

C.selected_objects[0].rotation_euler
Euler((3.473205089569092, 2.1467549800872803, 0.0), 'XYZ')

Wobec tego mi chodzi raczej o ten drugi sposób, bo to są te moje kąty (w radianach), które chcę wyeksportować.

Po skonwertowaniu na stopnie pierwszy kąt to  [199,123,0] a drugi [19, 57, 180]. Zauważ, że oba zestawy dają w efekcie takie samo ustawienie obiektów. Dwa różne zestawy kątów eulera jednocześnie taka sama macierz, <devils laugh mode>bwhahaha</devils laught mode>. Jeżeli oba obiekty animujemy od rotacji [0,0,0] do wcześniej podanych, to w połowie czasu animacji jedno będzie [99.5,61.5,0] a drugie [9.5,28.5,90] a to są całkiem różne orientacje. Tak więc tu też trzeba uważać. Mam nadzieję że nie zwiększyłem tym poziom ześwirowania ;-)


5
Szkółka / Odp: Przeliczanie rotacji w Blenderze na rotacje w OpenGL.
« dnia: Kwiecień 29, 2017, 00:42:38 »
Piszę sobie w Pythonie jakiś prosty exporter scen z myślą o użyciu do OpenGL. Wiem, że trzeba przejść z układu współrzędnych Blendera na OpenGL (right handed).

Ale Blender też ma taki sam układ współrzędnych jak OpenGL. Jak nie wierzysz to zaznacz kamerę i naciśnij Alt-R. Po zresetowaniu rotacji kamery widać, że góra kamery to +Y, prawo +X i patrzy ona w kierunku ujemnych Z. Czyli tak jak w OpenGL.

Jednak nie mogę sobie poradzić z obrotami. Nie mam pojęcia jak przeliczyć kąty obrotów w trzech osiach Blendera na kąty obrotów gotowe do użycia w OpenGL (glRotatef). Gdy robię to tak jak przy translacji to jest dobrze ale tylko w pewnym zakresie kątów i gdy nie składam dwóch obrotów.

obiekty w blenderze zawierają kąty obrotu "rotation_euler" w radianach, glRotate przyjmuje w stopniach więc trzeba sobie przekonwertować:

Kod: (python) [Zaznacz]
import bpy, math

obj = bpy.context.selected_objects[0]
print('Object("%s") Rotation Euler:' % obj.name)
print('  radians: ', [x for x in obj.rotation_euler])
print('  degrees: ', [math.degrees(x) for x in obj.rotation_euler])
print('  euler rotation mode: ', obj.rotation_mode)

ważny jest też tryb obrotu. Jak masz np. XYZ to znaczy, że najpierw jest obracany obiekt wokół osi X, następnie Y a na końcu wokół osi Z. Przekłada się to bezpośrednio na operacje w OGLu (Uwaga! kolejność możenia macierzy są odwrotne do kolejności operacji ):

Kod: (c) [Zaznacz]
for (auto o : scene.objects) {
    glPushMatrix();
         glTranslatef(o.loc_x, o.loc_y, o.loc_z);
         glRotatef(o.deg_z, 0, 0, 1); \\\
         glRotatef(o.deg_y, 0, 1, 0); \\ > XYZ; kolejnosc jest wazna!
         glRotatef(o.deg_x, 1, 0, 0); \\/
         glScalef(o.size_x, o.size_y, o.size_z);
    glPopMatrix();
}

powyższa kolejność się u mnie sprawdzała bo zawsze miałem w Blenderze ustawiony tryb XYZ. Lepiej jednak to wyeksportować i sprawdzać w kodzie programu.

można też odczytać macierz "bpy.context.selected_objects[0].matrix_world" i ładować to bezpośrednio do "glMultMatrixf(m44)"

Tak na marginesie, jeżeli masz animacje opartą na kątach Eulera to może się okazać, że interpolacja liniowa z jednego kąta Eulera do innego powoduje czasami bardzo dziwny ruch obiektu. Warto wtedy bawić się z ustawieniami kolejności rotacji, czyli XYZ zamienić na inny. Nie zawsze to pomoże, wtedy kwaterniony mogą jedynie pomóc.

6
Programowanie grafiki / Odp: Program do generowania normal map
« dnia: Luty 08, 2017, 13:22:52 »
Z blendera wyjdzie zawsze lepiej bo tam jest prawdziwa geometria i realne wektory normalne. W 2D to takie zgadywanie i pozostaje tylko manipulacja filtrami i innymi efektami w celu uzyskania w miarę wyglądającej tekstury. Być może pomogłoby tu jakieś AI albo może jakieś sieci neuronowe czy inne cuda które potrafiły by odczytać mapę wysokości ze zdjęcia?

Tutaj nie chodzi też o to czy piksel jest jaśniejszy czy nie ale bardziej o jego otoczenie. Piksel #808080 jak będzie miał wokoło sąsiednie piksele o wartości #808080 to będzie znaczyło, że leży na płaszczyźnie i na normal mapie jego kolor to #8080FF. Podobnie piksel czarny będzie miał kolor #8080FF jak wokoło będą same czarne. Jeżeli szary będzie sąsiadował z jednej strony z czarnym (najniższym) i białym (najwyższym) to znaczy że leży na stoku o nachyleniu 45 stopni i kolor normalmapy powinien być #2500DA. Już na podstawie tych danym powinieneś móc w stanie zrobić prostą konwersję height mapy na normalmapę, wystarczy potraktować piksele jako wysokość wierzchołków w siatce grida a później już z górki. Pewnie są jakieś liby co potrafią wyliczyć normalne w siatce.

Problem też jest taki, że pluginy nvidii czy te w gimpie badają otoczenie kilku pikseli i nie są w stanie "zobaczyć" większego trendu w zmianie wysokości w heightmapie. Jest jedna w miarę sensowna sztuczka, którą stosowałem, żeby zrobić normalmapę w gimpie, która dawała całkiem ładne cieniowanie:

1. Pierwszy etap do desaturacja obrazka, czyli konwersja na pseudo mapę wysokości. Można zgadnąć, że to jest jeden wielki fałsz bo coś jasnego na teksturze nie oznacza że jest wyżej. Ostre oświetlenie też zrobi przekłamania jak mocno oświetli kanty z jednej strony. Ogólnie przegrana sprawa

2. kopiujemy naszą mapę wysokości w kilku kopiach (widziałem tutoriale z kilkanaście a nawet z kilkadziesiąt różnych warstw :).

3. robimy normalmapę z pierwszej tekstury. Z niej uzyskujemy przede wszystkim drobne szczegóły, ale w szaderze będzie wyglądać ogólnie "płasko" i żaden pluggin nvidii tu nie pomoże.

4. na kolejnych pozostałych teksturach robimy blura o różnym stopniu i na nich robimy osobno normalmapy.
4a. można też zeskalować dany layer w dół i jego konwertować, pluggin będzie w stanie objąć większy obszar oryginalnej tekstury i uwydatnią się większe obiekty na teksturze (kamienie, cegły, etc.)



5. Doprowadzić poszczególne normalmapy do tych samych wymiarów (jeżeli były skalowane w dół) a następnie połączyć je w jedno. Można użyć trybu "Overlay" albo "Grain Merge" w Gimpie. One się najlepiej sprawdzają ale warto popróbować innych.

6. Po scaleniu w jedną warstwę warto ją znormalizować, żeby wektorki miały długość 1. W pluginie ustawiamy konwersję na "Normalize only".


7. 3D Preview pozwala ocenić wygląd naszej normalmapy, trzeba tylko zmienić stadardowe ustawienia z takich które nie występują w realnym świecie na bardziej sensowne. Zawsze Ambient zeruje a Diffuse na 50%, 100% w w przyrodzie nie występuje. Specular włączam i też ustawiam jak Diffuse.


Dzięki tej metodzie tekstura wydaje się "głębsza" i przy nisko padającym oświetleniu daje ładne cienie.

Powodzenia.

7
Programowanie grafiki / Odp: Program do generowania normal map
« dnia: Luty 08, 2017, 00:28:16 »
Jak byś tam miał jakiś gradient a nie pojedyncze prostokąty to miało by to może większy sens, ale wtedy raczej nie mówili byśmy o palecie barw.

W zasadzie to można zawsze mówić o palecie barw dla normalmap bo pewien zakres kolorów raczej nie występuje, np. szary (#808080) bo wektor normalny o długości zero raczej się nie spotyka, podobnie z kolorami, z których odkodowany wektor ma długość różną od 1.

Poza tym wcześniejsza paleta może i ma mały sens ale obrazek i paleta powstała w pośpiechu :), chociaż ograniczenie ich ilości może mieć pozytywny skutek - czasami szybciej się coś tworzy gdy jest ograniczona ilość dostępnych kolorów do wyboru.

Paletę do malowania można dowolnie uszczegółowić a nawet wygenerować programowo bo format palety w gimpie jest tekstowy i prosty jak drut

GIMP Palette
Name: NormalMap
Columns: 7
#
 58 205 189 Untitled
128 128 255 flat
128 128 255 flat
129 238 192 Untitled
128 128 255 flat
...


8
Programowanie grafiki / Odp: Program do generowania normal map
« dnia: Luty 07, 2017, 06:40:08 »
@Reg: Gdyby wziąć pod uwagę to, że normalmapy można również tworzyć i modyfikować metodą malarską w photoshopie albo gimpie to mówienie o palecie barw ma jak najbardziej sens.




9
Programowanie grafiki / Odp: Program do generowania normal map
« dnia: Luty 06, 2017, 07:30:44 »
1. Jeżeli chodzi o normal mapy tangent space to spotkałem się z dwoma odmianami. Jest to normalmapa dla wypukłego obiektu na płaszczyźnie:


Jak napiszesz szader dla pierwszego typu to przy zastosowaniu tej drugiej tekstury (tej dolnej) efekty cieniowania będą dość dziwne. Konwersja jest prosta, wystarczy odwrócić kolory kanału zielonego na teksturze (np. G=255-G) albo w szaderze zanegować wartość współrzędnej Y.

Pierwszy typ (prawoskrętny układ współrzędnych) jest stosowany w Blenderze. Drugi typ (lewoskrętny) z tego co pamiętam był używany w cryenginie. Rozpoznać je dość łatwo, kanał Green wygląda jakby wypukłe elementy były oświetlone z dołu dla lewoskrętnego układu. Oczywiście zależy od tego czy wiemy które elementy są wypukłe. Normalmap pluggin do gimpa też tworzy drugi typ normalmapy. Przypuszczam, że pluggin NVidii dla photoshopa podobnie. Oba plugginy mają jednak opcję "Invert Y", więc można wygenerować mapę dla obu typów.

... Po krótkim sprawdzeniu Internetu Unreal Engine podobnie jak Cryengine.

Ogólnie to nie ma reguły odnośnie skrętności układu na normal mapie, więc jak oświetlenie dziwnie reaguje na ruch światła to pierwsze co trzeba sprawdzić to kanał Green tekstury.

2. Dekodowanie normal map w szaderze wygląda tak:
vec3 normal = normalize (texture2D(normalTexUnit,gl_TexCoord[0].st).xyz*2.0 - 1.0);
//albo poniżej jezeli chcemy miec idealne 0.0 dla 128.
vec3 normal = normalize (texture2D(normalTexUnit,gl_TexCoord[0].st).xyz*255.0/128 - 1.0);
z tego wynika, że paleta barw wygląda następująco: 0 = -1.0, 128 = 0.0, 255 = 1.0 dla każdego kanału RGB.

3. z pozostałych rzeczy to warto wiedzieć jak generuje się tangent i binormal wektor dla danego mesha, google np. "mesh tangent calculation". Biblioteki ładujące siatki (np. Assimp) zazwyczaj potrafią wygenerować tangent i binormal jak dany format pliku ich nie przechowuje. W skrypcie w Blenderze też to się da jakby co

4. oczywiście istnieją normal mapy dla obiektów lustrzanych co jeszcze bardziej utrudnia sprawę :)

5. Na początek to darowałbym sobie tangent space i zaczął od czegoś prostszego, np. world space (normal mapy bardziej kolorowe).

10
Szkółka / Odp: c++ Struct , zapis i odczyt z pliku
« dnia: Styczeń 29, 2017, 22:16:31 »
W zasadzie to powtarzam się za Reg-iem ale co mi tam :) - skoro jest to c++ to nie warto rezygnować z std::string na rzecz tablicy znaków. W Twoim programie to pole struktury może być wykorzystywane do wielu różnych rzeczy i byłoby wygodnie móc skorzystać z metod klasy string.

Najlepiej napisać sobie dwie funkcje która zapisuje i odczytuje stringa z/do pliku znak po znaku plus na początku wielkość napisu. To jest jednorazowa robota w jednym miejscu a decyzja o zamianie stringa na tablice znaków uprzykrzy się później w paru różnych miejscach.

Odnośnie big i little-endian. Na samym początku powinieneś zadecydować który z nich będzie stosowany w pliku i się tego później trzymać. Dane typu int, short, float, double też powinny mieć funkcje ich zapisu bajt po bajcie wtedy będzie konkretne miejsce gdzie trzeba będzie zrobić ewentualną konwersję big->little lub little->big.

Jak endianness pliku jest konkretne i stałe to później łatwiej będzie zaimplementować wczytywanie danych pod inne architektury jak również w innych językach programowania.

Twoja struktura powinna mieć również metodę która będzie zapisywała poszczególne pola do pliku:
Kod: (c++) [Zaznacz]
struct st_profil {
    std::vector<std::string> nazwy(5);
    int ilosc;

    void savetofile(fstream plik);
    void loadfromfile(fstream plik);
}

void st_profil::savetofile(fstream plik) {
    for (auto s : nazwy) {
        save_string(plik, s);
    }
    save_int(plik, ilosc);
}

Wady:
- po dodaniu pola do struktury trzeba pamiętać o uaktualnieniu metody serializującej

Zalety:
- po dodaniu pola do struktury można specjalnie zapomnieć o zapisaniu jej do pliku, takie pseudo transient z javy :)

Ps. Jak już jest konkretne miejsce gdzie jest zapis struktury do pliku to nic nie stoi na przeszkodzie, żeby zrobić wczytywanie/zapisywanie XML albo JSON.

11
Programowanie grafiki / Odp: Mapa do gry C++
« dnia: Maj 27, 2016, 10:29:08 »
Ja bym zrobił to Blenderze. W kilkanaście minut spokojnie można obrysować całą Europę, zaznaczasz jeden wierzchołek wciskasz CTRL i klikasz myszką po mapie tworząc wierzchołki. Potem zaznaczasz wierzchołki danego kraju, wciskasz F i gotowe. CTRL-T potrafi zamienić polygon na pojedyncze trójkąty.



- Wierzchołki można dodać do jednej lub więcej grup, np. kilka z nich można dodać do grupy wierzchołków tworzących granicę między dwoma państwa i jednocześnie do innej grupy wierzchołków składających się na obrys danego kraju, unii krajów, kontynentu, etc.

- fejsom można przypisać różne materiały, kolory, tekstury



Warto pamiętać o "Custom Properties", czyli właściwości które można przypisywać do siatek i materiałów, np. dla materiału 'PL' możesz przypisać {'kraj':'Polska', 'ludność': 38.0e6}.

Całość można wyeksportować jako jeden wielki mesh albo podzielić go wcześniej na mniejsze obiekty. Możliwości jest dużo.

Eksportować siatki można w różnych formatach, ale nie wiem czy któryś z nich potrafi zapisać informacje o VertexGroups albo CustomProperties. Jeżeli nie to zawsze pozostaje możliwość napisanie w pythonie własnego skryptu eksportującego.

12
Szkółka / Odp: Zliczanie liter.
« dnia: Sierpień 21, 2015, 16:22:37 »
Kod: (c) [Zaznacz]
    for(char znak = 'a'; znak<='z';znak++){
      printf("%c %d\n", znak, tablica[znak]);
    }
Cytuj
1.Moglby mi ktos wyjasnic na jakiej zasadzie ten kod segreguje liczby w kolejnosci alfabetycznej ? Ktore miejsce za to odpowiada, skad program wie w jakiej kolejnosci sa liczby w alfabecie ?

z kodu ASCII 'a' == 97 i 'z'==122, więc powyższy kod jest równoważny temu:
Kod: (c) [Zaznacz]
    for(char znak = 97; znak<=122;znak++){
      printf("%c %d\n", znak, tablica[znak]);
    }
'a' + 1 == 'b', 'a'+2 == 'c', itd. Stąd wynika ta cała kolejność alfabetyczna, czyli z porządku liczb całkowitych

2.Czy ta zmienna char znak to ta sama co int znak ?
nie, to jest zmienna lokalna pętli for

btw, 'int znak' jest dlatego że getc odczytuje bajt jako 'unsigned char' 0..255, ale rzutuje to na 'int', żeby mieć możliwość poinformowania użytkownika tej funkcji o wystąpieniu końca pliku (EOF==-1). Schemat jest prosty, odczytujesz int z getc i sprawdzasz czy wynosi EOF . Jeżeli nie jest to wartość -1 to znaczy że jest to poprawnie odczytany znak i int można sobie zrzutować na unsigned char albo zwykły char.

3.
Kod: (c) [Zaznacz]
    for(char znak = 'a'; znak<='z';znak++){
       if (tablica[znak] != 0)
           printf("%c %d\n", znak, tablica[znak]);
    }
i podobnie dla wielkich liczb 'A'..'Z'

13
Grafika 2D / Odp: Jak zapisać TARGA bez premultiplied Alpha?
« dnia: Lipiec 11, 2015, 18:21:35 »
Możesz pokazać jakieś przykładowe obrazki i podać w jaki sposób używasz gimpa? Nie wydaje mi się żeby eksporter TGA robił jakieś ekstra przekształcenia, być może całe psucie odbywa się już wcześniej.

Malowanie czarnym pędzlem na przeźroczystym tle daje takie rezultaty:
http://i.imgur.com/1NcBt3Z.png


Tzn. Na początku dałem "Add Alpha Channel", maznąłem pędzlem a następnie "Add Layer Mask" oraz "Transfer layers's alpha channel" ("Layer Alpha Channel" daje złe rezultaty). Po tym można dać "Remove Alpha channel" bo przezroczystość jest już w masce.

Na końcu dałem "Disable layer mask" i pokazało że pędzel na warstwach RGB ma ostre krawędzie. Być może tu leży przyczyna twoich problemów.

14
Szkółka / Odp: Plik binarny z Javy odczyt w c++
« dnia: Lipiec 04, 2015, 00:32:04 »
float jest zgodny z IEEE754, short i int bez zmian, byte z Javy to 8 bitowy char w c++. Natomiast w javie char to 16 bitów bez znaku, możesz go zastąpić unsigned short
Kod: (c) [Zaznacz]
typedef char JavaByte;
typedef unsigned short JavaChar;
        JavaChar euroSign = 0x20ac; // w java:  char eurosign = '\u20ac';

printf("sizeof(short)=%d, sizeof(int)=%d", sizeof(short), sizeof(int)); // short=2, int=4

15
C++ / Odp: Dwuwymiarowa tablica znakow.
« dnia: Czerwiec 22, 2015, 23:15:53 »
@up: super :)

Gdyby funkcję zdefiniować tak:
Kod: (c) [Zaznacz]
void func(vector<const char*> nazwy) {
for (auto s : nazwy) {
cout << s << endl;
}
}
to można by ją wywoływać w ten sposób:
Kod: (cpp) [Zaznacz]
auto nazwy {"1", "2", "3"};
func( nazwy );
func( {"1", "2", "3"} );

Strony: [1] 2 3 4 5 ... 63