Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[SFML 2.X] sf::Vertex oraz linie między różnymi kafelkami mapy

Ostatnio zmodyfikowano 2024-10-30 16:23
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
[SFML 2.X] sf::Vertex oraz linie między różnymi kafelkami mapy
» 2024-10-29 19:45:55
Witam. Chciałbym pomiędzy różniącymi się kafelkami wygenerować linie. Do tego celu stworzyłem funkcję generateMesh(). Napisałem funkcję ale coś nie działa czasem nie rysuje linii. Czy mógłby mi ktoś doradzić dlaczego to nie działa i gdzie robię błąd ?

C/C++
class Terrain
    : public sf::Drawable
    , public sf::Transformable
{
public:
   
short width, height;
   
sf::Vector2i coords;
   
   
sf::VertexArray vertexes;
   
sf::Texture tileset;
   
   
sf::VertexArray outlines;
   
   
std::vector < short > tiles;
   
   
Terrain( short x, short y, short width, short height ) {
       
       
coords.x = x;
       
coords.y = y;
       
       
this->width = width;
       
this->height = height;
       
       
tileset = sf::Texture();
       
tileset = * getTexture( "tiles/0_tileset" )->texture;
       
       
vertexes.setPrimitiveType( sf::Triangles );
       
vertexes.resize( width * height * 6 ); // widthMap * heightMap * TwoTrianglesVertices
       
       
tiles.resize( width * height );
       
       
short coord_x, coord_y;
       
       
// TERRAIN - GRASS
       
for( short y = 0; y < height; y++ )
       
for( short x = 0; x < width; x++ ) {
           
           
sf::Vertex * triangles = & vertexes[( y * width + x ) * 6 ];
           
           
coord_x =( coords.x + x );
           
coord_y =( coords.y + y );
           
           
triangles[ 0 ].position = sf::Vector2f( coord_x * tileSide, coord_y * tileSide );
           
triangles[ 1 ].position = sf::Vector2f(( coord_x + 1 ) * tileSide, coord_y * tileSide );
           
triangles[ 2 ].position = sf::Vector2f( coord_x * tileSide,( coord_y + 1 ) * tileSide );
           
triangles[ 3 ].position = sf::Vector2f( coord_x * tileSide,( coord_y + 1 ) * tileSide );
           
triangles[ 4 ].position = sf::Vector2f(( coord_x + 1 ) * tileSide, coord_y * tileSide );
           
triangles[ 5 ].position = sf::Vector2f(( coord_x + 1 ) * tileSide,( coord_y + 1 ) * tileSide );
           
           
edit( x, y, 0 );
       
}
       
       
generateMesh();
   
}
   
   
void edit( short x, short y, short value ) {
       
       
if( x < 0 || x >= width || y < 0 || y >= height )
           
 return;
       
       
if( value > 4 || value < 0 )
           
 return;
       
       
tiles[ y * width + x ] = value;
       
       
short global_x = coords.x + x;
       
short global_y = coords.y + y;
       
       
sf::Vertex * triangles = & vertexes[( y * width + x ) * 6 ];
       
       
short tu =( short( global_x * tileSide ) % 64 ) +( value * 64 );
       
short tv =( short( global_y * tileSide ) % 64 );
       
       
//cout << "tu: " << tu << ", tv: " << tv << "\n";
       
       
triangles[ 0 ].texCoords = sf::Vector2f( tu, tv );
       
triangles[ 1 ].texCoords = sf::Vector2f( tu + tileSide, tv );
       
triangles[ 2 ].texCoords = sf::Vector2f( tu, tv + tileSide );
       
triangles[ 3 ].texCoords = sf::Vector2f( tu, tv + tileSide );
       
triangles[ 4 ].texCoords = sf::Vector2f( tu + tileSide, tv );
       
triangles[ 5 ].texCoords = sf::Vector2f( tu + tileSide, tv + tileSide );
   
}
   
   
void generateMesh() {
       
       
outlines.clear();
       
outlines.setPrimitiveType( sf::Lines );
       
       
cout << "generate mesh\n";
       
       
int x, y;
       
int coord_x, coord_y;
       
       
for( int i = 0; i < tiles.size(); i++ ) {
           
x = i % width;
           
y = i / width;
           
           
if( x > 0 && x < 15 && y > 0 && y < 15 ) {
               
// TOP LINE
               
if( tiles[( y - 1 ) * width + x ] != tiles[ y * width + x ] ) {
                   
                   
coord_x =( coords.x + x );
                   
coord_y =( coords.y + y );
                   
                   
sf::Vertex line[ 2 ];
                   
line[ 0 ].position = sf::Vector2f( coord_x * tileSide, coord_y * tileSide );
                   
line[ 0 ].color = sf::Color::Black;
                   
line[ 1 ].position = sf::Vector2f(( coord_x + 1 ) * tileSide, coord_y * tileSide );
                   
line[ 1 ].color = sf::Color::Black;
                   
outlines.append( line[ 0 ] );
                   
outlines.append( line[ 1 ] );
                   
               
}
               
               
// BOTTOM LINE
               
if( tiles[( y + 1 ) * width + x ] != tiles[ y * width + x ] ) {
                   
                   
coord_x =( coords.x + x );
                   
coord_y =( coords.y + y );
                   
                   
sf::Vertex line[ 2 ];
                   
line[ 0 ].position = sf::Vector2f( coord_x * tileSide,( coord_y + 1 ) * tileSide );
                   
line[ 0 ].color = sf::Color::Black;
                   
line[ 1 ].position = sf::Vector2f(( coord_x + 1 ) * tileSide,( coord_y + 1 ) * tileSide );
                   
line[ 1 ].color = sf::Color::Black;
                   
outlines.append( line[ 0 ] );
                   
outlines.append( line[ 1 ] );
                   
               
}
               
               
// LEFT LINE
               
if( tiles[ y * width + x - 1 ] != tiles[ y * width + x ] ) {
                   
                   
coord_x =( coords.x + x );
                   
coord_y =( coords.y + y );
                   
                   
sf::Vertex line[ 2 ];
                   
line[ 0 ].position = sf::Vector2f( coord_x * tileSide, coord_y * tileSide );
                   
line[ 0 ].color = sf::Color::Black;
                   
line[ 1 ].position = sf::Vector2f( coord_x * tileSide,( coord_y + 1 ) * tileSide );
                   
line[ 1 ].color = sf::Color::Black;
                   
outlines.append( line[ 0 ] );
                   
outlines.append( line[ 1 ] );
                   
               
}
               
               
// RIGHT LINE
               
if( tiles[ y * width + x + 1 ] != tiles[ y * width + x ] ) {
                   
                   
coord_x =( coords.x + x );
                   
coord_y =( coords.y + y );
                   
                   
sf::Vertex line[ 2 ];
                   
line[ 0 ].position = sf::Vector2f(( coord_x + 1 ) * tileSide, coord_y * tileSide );
                   
line[ 0 ].color = sf::Color::Black;
                   
line[ 1 ].position = sf::Vector2f(( coord_x + 1 ) * tileSide,( coord_y + 1 ) * tileSide );
                   
line[ 1 ].color = sf::Color::Black;
                   
outlines.append( line[ 0 ] );
                   
outlines.append( line[ 1 ] );
                   
               
}
               
            }
           
        }
    }
private:
   
   
virtual void draw( sf::RenderTarget & target, sf::RenderStates states ) const
   
{
       
       
// draw tiles - terrain
       
states.transform *= getTransform();
       
states.texture = & tileset; // TO-DO
       
target.draw( vertexes, states );
       
target.draw( outlines, states );
   
}
}
;

C/C++
Terrain * terrain = new Terrain( x * 16, y * 16, 16, 16 );
for( iny y = 0; y < 16; y++ )
for( int x = 0; x < 16; x++ )
   
 terrain->edit( x, y, rand() % 3 );

terrain->generateMesh();
window->draw( * terrain );
P-181781
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-29 20:28:20
Pogrubiłem te linie:

C/C++
void generateMesh() {
   
   
outlines.clear();
   
outlines.setPrimitiveType( sf::Quads );
   
   
cout << "generate mesh\n";
   
   
int x, y;
   
int coord_x, coord_y;
   
float lineThickness = 4.0f; // Grubość linii
   
   
for( int i = 0; i < tiles.size(); i++ ) {
       
x = i % width;
       
y = i / width;
       
       
if( x > 0 && x < 15 && y > 0 && y < 15 ) {
           
           
coord_x =( coords.x + x ) * tileSide;
           
coord_y =( coords.y + y ) * tileSide;
           
           
// GÓRNA KRAWĘDŹ
           
if( tiles[( y - 1 ) * width + x ] != tiles[ y * width + x ] ) {
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x, coord_y - lineThickness / 2 ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide, coord_y - lineThickness / 2 ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide, coord_y + lineThickness / 2 ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x, coord_y + lineThickness / 2 ), sf::Color::Black ) );
           
}
           
           
// DOLNA KRAWĘDŹ
           
if( tiles[( y + 1 ) * width + x ] != tiles[ y * width + x ] ) {
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x, coord_y + tileSide - lineThickness / 2 ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide, coord_y + tileSide - lineThickness / 2 ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide, coord_y + tileSide + lineThickness / 2 ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x, coord_y + tileSide + lineThickness / 2 ), sf::Color::Black ) );
           
}
           
           
// LEWA KRAWĘDŹ
           
if( tiles[ y * width +( x - 1 ) ] != tiles[ y * width + x ] ) {
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x - lineThickness / 2, coord_y ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + lineThickness / 2, coord_y ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + lineThickness / 2, coord_y + tileSide ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x - lineThickness / 2, coord_y + tileSide ), sf::Color::Black ) );
           
}
           
           
// PRAWA KRAWĘDŹ
           
if( tiles[ y * width +( x + 1 ) ] != tiles[ y * width + x ] ) {
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide - lineThickness / 2, coord_y ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide + lineThickness / 2, coord_y ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide + lineThickness / 2, coord_y + tileSide ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide - lineThickness / 2, coord_y + tileSide ), sf::Color::Black ) );
           
}
           
        }
       
    }
}
P-181782
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-29 21:41:35
C/C++
void generateBorders( Terrain * topTerrain, Terrain * bottomTerrain, Terrain * leftTerrain, Terrain * rightTerrain ) {
   
   
outlines.clear();
   
outlines.setPrimitiveType( sf::Quads );
   
   
int x, y;
   
int coord_x, coord_y;
   
float lineThickness = 2.0f; // Grubość linii
   
   
for( int i = 0; i < tiles.size(); i++ ) {
       
       
x = i % width;
       
y = i / width;
       
       
coord_x =( coords.x + i % width ) * tileSide;
       
coord_y =( coords.y + i / width ) * tileSide;
       
       
short tileValue;
       
       
// GÓRNA KRAWĘDŹ
       
if( y == 0 ) {
           
if( topTerrain != nullptr ) {
               
tileValue = topTerrain->tiles[ 15 * width + x ]; // Pobiera kafel z górnej mapy
           
}
           
else {
               
tileValue = tiles[ y * width + x ]; // W przeciwnym razie bierze aktualny kafel
           
}
        }
       
else {
           
tileValue = tiles[( y - 1 ) * width + x ]; // Pobiera kafel powyżej aktualnego
       
}
       
       
// Sprawdzenie różnicy kafli
       
if( tiles[ i ] != tileValue ) {
           
outlines.append( sf::Vertex( sf::Vector2f( coord_x, coord_y - lineThickness / 2 ), sf::Color::Black ) );
           
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide, coord_y - lineThickness / 2 ), sf::Color::Black ) );
           
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide, coord_y + lineThickness / 2 ), sf::Color::Black ) );
           
outlines.append( sf::Vertex( sf::Vector2f( coord_x, coord_y + lineThickness / 2 ), sf::Color::Black ) );
       
}
    }
}
P-181783
pekfos
» 2024-10-29 21:46:25
C/C++
if( x > 0 && x < 15 && y > 0 && y < 15 )
   
Ten warunek nie pokrywa poprawnie przypadków brzegowych. Zapewniłeś tu że każda współrzędna +/-1 jest poprawna, ale przykładowo na górnej krawędzi y-1 jest błędne, podczas gdy x+-1 jest dalej poprawne. Powinieneś testować y > 0 w warunku który wymaga tego do poprawności i analogicznie pozostałe. Np
C/C++
if( y > 0 && tiles[( y - 1 ) * width + x ] != tiles[ y * width + x ] )
   
P-181784
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-29 21:54:31
Teraz potrzebowałbym jeszcze by na granicach mapy też to działało.


C/C++
void generateBorders( Terrain * topTerrain, Terrain * bottomTerrain, Terrain * leftTerrain, Terrain * rightTerrain ) {
   
   
outlines.clear();
   
outlines.setPrimitiveType( sf::Quads );
   
   
int x, y;
   
int coord_x, coord_y;
   
float lineThickness = 4.0f; // Grubość linii
   
   
for( int i = 0; i < tiles.size(); i++ ) {
       
       
x = i % width;
       
y = i / width;
       
       
coord_x =( coords.x + x ) * tileSide;
       
coord_y =( coords.y + y ) * tileSide;
       
       
if( y > 0 && y < 15 && x > 0 && x < 15 ) {
           
           
// GÓRNA KRAWĘDŹ
           
if( tiles[ i ] != tiles[ i - width ] ) {
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x, coord_y - lineThickness / 2 ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide, coord_y - lineThickness / 2 ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide, coord_y + lineThickness / 2 ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x, coord_y + lineThickness / 2 ), sf::Color::Black ) );
           
}
           
           
// DOLNA KRAWĘDŹ
           
if( tiles[ i ] != tiles[ i + width ] ) {
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x, coord_y + tileSide - lineThickness / 2 ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide, coord_y + tileSide - lineThickness / 2 ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide, coord_y + tileSide + lineThickness / 2 ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x, coord_y + tileSide + lineThickness / 2 ), sf::Color::Black ) );
           
}
           
           
// LEWA KRAWĘDŹ
           
if( tiles[ i ] != tiles[ i - 1 ] ) {
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x - lineThickness / 2, coord_y ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + lineThickness / 2, coord_y ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + lineThickness / 2, coord_y + tileSide ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x - lineThickness / 2, coord_y + tileSide ), sf::Color::Black ) );
           
}
           
           
// PRAWA KRAWĘDŹ
           
if( tiles[ i ] != tiles[ i + 1 ] ) {
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide - lineThickness / 2, coord_y ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide + lineThickness / 2, coord_y ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide + lineThickness / 2, coord_y + tileSide ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide - lineThickness / 2, coord_y + tileSide ), sf::Color::Black ) );
           
}
        }
       
       
       
       
       
    }
}

P-181786
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-30 13:24:15
Jak na razie napisałem coś takiego ale generuje mi nie wiadomo skąd linie na granicach map:

https://github.com/tBane1995/test

C/C++
void generateBorders() {
   
Chunk * topChunk;
   
Chunk * bottomChunk;
   
Chunk * leftChunk;
   
Chunk * rightChunk;
   
   
Terrain * topTerrain;
   
Terrain * bottomTerrain;
   
Terrain * leftTerrain;
   
Terrain * rightTerrain;
   
   
int y, x;
   
   
for( int i = 0; i < chunks.size(); i++ ) {
       
       
y = i / width;
       
x = i % width;
       
       
topChunk = getChunk( x, y - 1 );
       
bottomChunk = getChunk( x, y + 1 );
       
leftChunk = getChunk( x - 1, y );
       
rightChunk = getChunk( x + 1, y );
       
       
( topChunk != nullptr ) ? topTerrain = topChunk->terrain
            : topTerrain = nullptr;
       
( bottomChunk != nullptr ) ? bottomTerrain = bottomChunk->terrain
            : bottomTerrain = nullptr;
       
( leftChunk != nullptr ) ? leftTerrain = leftChunk->terrain
            : leftTerrain = nullptr;
       
( rightChunk != nullptr ) ? rightTerrain = rightChunk->terrain
            : rightTerrain = nullptr;
       
       
chunks[ i ]->terrain->generateBorders( topTerrain, bottomTerrain, leftTerrain, rightTerrain );
   
}
}

void generateBorders( Terrain * topTerrain, Terrain * bottomTerrain, Terrain * leftTerrain, Terrain * rightTerrain ) {
   
   
outlines.clear();
   
outlines.setPrimitiveType( sf::Quads );
   
   
int x, y;
   
int coord_x, coord_y;
   
float lineThickness = 4.0f; // Grubość linii
   
   
for( int i = 0; i < tiles.size(); i++ ) {
       
       
x = i % width;
       
y = i / width;
       
       
coord_x =( coords.x + x ) * tileSide;
       
coord_y =( coords.y + y ) * tileSide;
       
       
short tileValue;
       
       
if( y == 0 ) {
           
( topTerrain != nullptr ) ? tileValue = topTerrain->tiles[ y * 15 + x ]
                :
tileValue = - 1;
       
}
       
else
           
 tileValue = this->tiles[ i - width ];
       
       
// GÓRNA KRAWĘDŹ - FOR TEST - NOT WORKING
       
if( this->tiles[ i ] != tileValue ) {
           
outlines.append( sf::Vertex( sf::Vector2f( coord_x, coord_y - lineThickness / 2 ), sf::Color::Black ) );
           
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide, coord_y - lineThickness / 2 ), sf::Color::Black ) );
           
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide, coord_y + lineThickness / 2 ), sf::Color::Black ) );
           
outlines.append( sf::Vertex( sf::Vector2f( coord_x, coord_y + lineThickness / 2 ), sf::Color::Black ) );
       
}
       
       
// DOPIERO BĘDĘ POPRAWiAŁ POZOSTAŁE KRAWĘDZIE
       
if( y > 0 && y < 15 && x > 0 && x < 15 ) {
           
           
           
           
// DOLNA KRAWĘDŹ
           
if( tiles[ i ] != tiles[ i + width ] ) {
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x, coord_y + tileSide - lineThickness / 2 ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide, coord_y + tileSide - lineThickness / 2 ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide, coord_y + tileSide + lineThickness / 2 ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x, coord_y + tileSide + lineThickness / 2 ), sf::Color::Black ) );
           
}
           
           
// LEWA KRAWĘDŹ
           
if( tiles[ i ] != tiles[ i - 1 ] ) {
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x - lineThickness / 2, coord_y ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + lineThickness / 2, coord_y ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + lineThickness / 2, coord_y + tileSide ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x - lineThickness / 2, coord_y + tileSide ), sf::Color::Black ) );
           
}
           
           
// PRAWA KRAWĘDŹ
           
if( tiles[ i ] != tiles[ i + 1 ] ) {
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide - lineThickness / 2, coord_y ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide + lineThickness / 2, coord_y ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide + lineThickness / 2, coord_y + tileSide ), sf::Color::Black ) );
               
outlines.append( sf::Vertex( sf::Vector2f( coord_x + tileSide - lineThickness / 2, coord_y + tileSide ), sf::Color::Black ) );
           
}
        }
       
       
       
       
       
    }
}

Zrobiłem testy i wyszło, że jest problem z przesyłanie terenów przez funkcję:
C/C++
chunks[ i ]->terrain->generateBorders( topTerrain, bottomTerrain, leftTerrain, rightTerrain );
coords 1 1
topTerrain is null
bottomTerrain is null
leftTerrain is null
rightTerrain is null
P-181792
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-30 16:23:00
problemem było, że chunki w liścia niekoniecznie muszą być uporządkowane : :

C/C++
void generateBorders() {
   
Chunk * topChunk = nullptr;
   
Chunk * bottomChunk = nullptr;
   
Chunk * leftChunk = nullptr;
   
Chunk * rightChunk = nullptr;
   
   
Terrain * topTerrain = nullptr;
   
Terrain * bottomTerrain = nullptr;
   
Terrain * leftTerrain = nullptr;
   
Terrain * rightTerrain = nullptr;
   
   
short y, x;
   
   
for( int i = 0; i < chunks.size(); i++ ) {
       
       
y = chunks[ i ]->coords.y; // edited
       
x = chunks[ i ]->coords.x; // edited
       
...
   
}
   
P-181793
« 1 »
  Strona 1 z 1