From Ulrich Hertlien, supported add to textures in the .lwo format.
This commit is contained in:
@@ -64,12 +64,12 @@ Lwo2::~Lwo2()
|
||||
bool
|
||||
Lwo2::ReadFile( const string& filename )
|
||||
{
|
||||
notify(INFO) << "Opening file: " << filename << endl;
|
||||
notify(INFO) << "Opening file: " << filename << std::endl;
|
||||
|
||||
_fin.open(filename.c_str(), ios::in | ios::binary );
|
||||
if (!_fin.is_open())
|
||||
{
|
||||
notify(NOTICE) << "Can't open file '" << filename << "'" << endl;
|
||||
notify(NOTICE) << "Can't open file '" << filename << "'" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -77,30 +77,30 @@ Lwo2::ReadFile( const string& filename )
|
||||
// http://www.lightwave3d.com/developer/75lwsdk/docs/filefmts/eaiff85.html
|
||||
if (_read_long() != tag_FORM)
|
||||
{
|
||||
notify(INFO) << "File '" << filename << "' is not IFF format file." << endl;
|
||||
notify(INFO) << "File '" << filename << "' is not IFF format file." << std::endl;
|
||||
_fin.close();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
notify(INFO) << "Detected EA-IFF85 format" << endl;
|
||||
notify(INFO) << "Detected EA-IFF85 format" << std::endl;
|
||||
}
|
||||
|
||||
unsigned long form_size = _read_long();
|
||||
notify(DEBUG_INFO) << "Form size: " << form_size << endl;
|
||||
notify(DEBUG_INFO) << "Form size: " << form_size << std::endl;
|
||||
|
||||
// checking LWO2 format
|
||||
// http://www.lightwave3d.com/developer/75lwsdk/docs/filefmts/lwo2.html
|
||||
if (_read_long() != tag_LWO2)
|
||||
{
|
||||
unsigned long make_id(const char*);
|
||||
notify(DEBUG_INFO) << "File '" << filename << "' is not LWO2 format file." << endl;
|
||||
notify(DEBUG_INFO) << "File '" << filename << "' is not LWO2 format file." << std::endl;
|
||||
_fin.close();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
notify(INFO) << "Detected LWO2 format" << endl;
|
||||
notify(INFO) << "Detected LWO2 format" << std::endl;
|
||||
}
|
||||
|
||||
_geode = osgNew osg::Geode();
|
||||
@@ -229,7 +229,7 @@ Lwo2::_print_tag(unsigned int tag, unsigned int size) {
|
||||
<< char(tag >> 8)
|
||||
<< char(tag)
|
||||
<< " size " << size << " bytes"
|
||||
<< endl;
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
// print 4-char type
|
||||
@@ -240,7 +240,7 @@ Lwo2::_print_type(unsigned int type) {
|
||||
<< char(type >> 16)
|
||||
<< char(type >> 8)
|
||||
<< char(type)
|
||||
<< endl;
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
// read TAGS info
|
||||
@@ -255,7 +255,7 @@ Lwo2::_read_tag_strings(unsigned long size)
|
||||
size -= name.length() + name.length() % 2;
|
||||
_tags.push_back(name);
|
||||
|
||||
notify(DEBUG_INFO) << " name \t'" << name.c_str() << "'" << endl;
|
||||
notify(DEBUG_INFO) << " name \t'" << name.c_str() << "'" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,7 +298,7 @@ void
|
||||
Lwo2::_read_points(unsigned long size)
|
||||
{
|
||||
int count = size / 12;
|
||||
notify(DEBUG_INFO) << " count \t" << count << endl;
|
||||
notify(DEBUG_INFO) << " count \t" << count << std::endl;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
@@ -342,7 +342,7 @@ Lwo2::_read_polygons(unsigned long size)
|
||||
{
|
||||
|
||||
// not recognized yet
|
||||
notify(DEBUG_INFO) << " skipping..." << endl;
|
||||
notify(DEBUG_INFO) << " skipping..." << std::endl;
|
||||
_fin.seekg(size + size % 2, ios::cur);
|
||||
}
|
||||
}
|
||||
@@ -360,12 +360,12 @@ Lwo2::_read_vertex_mapping(unsigned long size)
|
||||
short dimension = _read_short();
|
||||
size -= 2;
|
||||
|
||||
notify(DEBUG_INFO) << " dimension \t" << dimension << endl;
|
||||
notify(DEBUG_INFO) << " dimension \t" << dimension << std::endl;
|
||||
|
||||
string name;
|
||||
_read_string(name);
|
||||
size -= name.length() + name.length() % 2;
|
||||
notify(DEBUG_INFO) << " name \t'" << name.c_str() << "'" << endl;
|
||||
notify(DEBUG_INFO) << " name \t'" << name.c_str() << "'" << std::endl;
|
||||
|
||||
if (type == tag_TXUV && dimension == 2)
|
||||
{
|
||||
@@ -387,7 +387,7 @@ Lwo2::_read_vertex_mapping(unsigned long size)
|
||||
{
|
||||
|
||||
// not recognized yet
|
||||
notify(DEBUG_INFO) << " skipping..." << endl;
|
||||
notify(DEBUG_INFO) << " skipping..." << std::endl;
|
||||
_fin.seekg(size + size % 2, ios::cur);
|
||||
}
|
||||
|
||||
@@ -406,12 +406,12 @@ Lwo2::_read_polygons_mapping(unsigned long size)
|
||||
short dimension = _read_short();
|
||||
size -= 2;
|
||||
|
||||
notify(DEBUG_INFO) << " dimension \t" << dimension << endl;
|
||||
notify(DEBUG_INFO) << " dimension \t" << dimension << std::endl;
|
||||
|
||||
string name;
|
||||
_read_string(name);
|
||||
size -= name.length() + name.length() % 2;
|
||||
notify(DEBUG_INFO) << " name \t'" << name.c_str() << "'" << endl;
|
||||
notify(DEBUG_INFO) << " name \t'" << name.c_str() << "'" << std::endl;
|
||||
|
||||
if (type == tag_TXUV && dimension == 2)
|
||||
{
|
||||
@@ -438,7 +438,7 @@ Lwo2::_read_polygons_mapping(unsigned long size)
|
||||
{
|
||||
|
||||
// not recognized yet
|
||||
notify(DEBUG_INFO) << " skipping..." << endl;
|
||||
notify(DEBUG_INFO) << " skipping..." << std::endl;
|
||||
_fin.seekg(size + size % 2, ios::cur);
|
||||
}
|
||||
|
||||
@@ -473,7 +473,7 @@ Lwo2::_read_polygon_tag_mapping(unsigned long size)
|
||||
{
|
||||
|
||||
// not recognized yet
|
||||
notify(DEBUG_INFO) << " skipping..." << endl;
|
||||
notify(DEBUG_INFO) << " skipping..." << std::endl;
|
||||
_fin.seekg(size + size % 2, ios::cur);
|
||||
}
|
||||
}
|
||||
@@ -485,7 +485,7 @@ Lwo2::_read_image_definition(unsigned long size)
|
||||
{
|
||||
unsigned int index = _read_long();
|
||||
size -= 4;
|
||||
notify(DEBUG_INFO) << " index \t" << index << endl;
|
||||
notify(DEBUG_INFO) << " index \t" << index << std::endl;
|
||||
|
||||
unsigned int type;
|
||||
while (size > 0)
|
||||
@@ -511,7 +511,7 @@ Lwo2::_read_image_definition(unsigned long size)
|
||||
|
||||
_images[index] = name.c_str();
|
||||
|
||||
notify(DEBUG_INFO) << " name \t'" << name.c_str() << "'" << endl;
|
||||
notify(DEBUG_INFO) << " name \t'" << name.c_str() << "'" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,12 +526,12 @@ Lwo2::_read_surface(unsigned long size)
|
||||
|
||||
_read_string(surface->name);
|
||||
size -= surface->name.length() + surface->name.length() % 2;
|
||||
notify(DEBUG_INFO) << " name \t'" << surface->name.c_str() << "'" << endl;
|
||||
notify(DEBUG_INFO) << " name \t'" << surface->name.c_str() << "'" << std::endl;
|
||||
|
||||
string source;
|
||||
_read_string(source);
|
||||
size -= source.length() + source.length() % 2;
|
||||
notify(DEBUG_INFO) << " source \t'" << source.c_str() << "'" << endl;
|
||||
notify(DEBUG_INFO) << " source \t'" << source.c_str() << "'" << std::endl;
|
||||
|
||||
unsigned long current_tag_name;
|
||||
unsigned short current_tag_size;
|
||||
@@ -563,7 +563,7 @@ Lwo2::_read_surface(unsigned long size)
|
||||
if (current_tag_name == tag_IMAG)
|
||||
{
|
||||
surface->image_index = _read_short();
|
||||
notify(DEBUG_INFO) << " image index\t" << surface->image_index << endl;
|
||||
notify(DEBUG_INFO) << " image index\t" << surface->image_index << std::endl;
|
||||
blok_size -= 2;
|
||||
}
|
||||
else if (current_tag_name == tag_IMAP)
|
||||
@@ -576,7 +576,7 @@ Lwo2::_read_surface(unsigned long size)
|
||||
string ordinal;
|
||||
_read_string(ordinal);
|
||||
imap_size -= ordinal.length() + ordinal.length() % 2;
|
||||
notify(DEBUG_INFO) << " ordinal \t'" << ordinal.c_str() << "'" << endl;
|
||||
notify(DEBUG_INFO) << " ordinal \t'" << ordinal.c_str() << "'" << std::endl;
|
||||
|
||||
while(imap_size > 0)
|
||||
{
|
||||
@@ -604,7 +604,7 @@ Lwo2::_read_surface(unsigned long size)
|
||||
float g = _read_float();
|
||||
float b = _read_float();
|
||||
surface->color.set(r,g,b);
|
||||
notify(DEBUG_INFO) << " color \t" << surface->color << endl;
|
||||
notify(DEBUG_INFO) << " color \t" << surface->color << std::endl;
|
||||
current_tag_size -= 12;
|
||||
size -= 12;
|
||||
|
||||
@@ -662,9 +662,9 @@ Lwo2::_generate_statesets_from_surfaces()
|
||||
// check if exist texture image for this surface
|
||||
if (surface->image_index >= 0)
|
||||
{
|
||||
notify(DEBUG_INFO) << "\tloading image '" << _images[surface->image_index] << "'" << endl;
|
||||
notify(DEBUG_INFO) << "\tloading image '" << _images[surface->image_index] << "'" << std::endl;
|
||||
Image* image = osgDB::readImageFile(_images[surface->image_index]);
|
||||
notify(DEBUG_INFO) << "\tresult - " << image << endl;
|
||||
notify(DEBUG_INFO) << "\tresult - " << image << std::endl;
|
||||
if (image)
|
||||
{
|
||||
Texture2D* texture = osgNew osg::Texture2D;
|
||||
|
||||
@@ -136,13 +136,11 @@ osgDB::ReaderWriter::ReadResult ReaderWriterLWO::readNode_LWO1(const std::string
|
||||
}
|
||||
|
||||
MaterialToGeometryCollectionMap::iterator itr;
|
||||
for(itr=mtgcm.begin();
|
||||
itr!=mtgcm.end();
|
||||
++itr)
|
||||
for(itr=mtgcm.begin(); itr!=mtgcm.end(); ++itr)
|
||||
{
|
||||
GeometryCollection& gc = itr->second;
|
||||
|
||||
if (gc._numPrimitives)
|
||||
if (gc._numPrimitives)
|
||||
{
|
||||
lwMaterial& lw_material = lw->material[itr->first];
|
||||
|
||||
@@ -165,17 +163,31 @@ osgDB::ReaderWriter::ReadResult ReaderWriterLWO::readNode_LWO1(const std::string
|
||||
// set up texture if needed.
|
||||
if (gc._numPrimitivesWithTexCoords==gc._numPrimitives)
|
||||
{
|
||||
if (strlen(lw_material.name)!=0)
|
||||
if (lw_material.ctex.flags && strlen(lw_material.ctex.name)!=0)
|
||||
{
|
||||
osg::Image* image = osgDB::readImageFile(lw_material.name);
|
||||
osg::notify(osg::INFO) << "ctex " << lw_material.ctex.name << std::endl;
|
||||
osg::Image* image = osgDB::readImageFile(lw_material.ctex.name);
|
||||
if (image)
|
||||
{
|
||||
// create state
|
||||
osg::StateSet* stateset = osgNew osg::StateSet;
|
||||
|
||||
// create texture
|
||||
osg::Texture2D* texture = osgNew osg::Texture2D;
|
||||
texture->setImage(image);
|
||||
|
||||
|
||||
// texture wrap mode
|
||||
static osg::Texture::WrapMode mode[] = {
|
||||
osg::Texture::CLAMP,
|
||||
osg::Texture::CLAMP,
|
||||
osg::Texture::REPEAT,
|
||||
osg::Texture::MIRROR
|
||||
};
|
||||
texture->setWrap(osg::Texture::WRAP_S,
|
||||
mode[lw_material.ctex.u_wrap]);
|
||||
texture->setWrap(osg::Texture::WRAP_T,
|
||||
mode[lw_material.ctex.v_wrap]);
|
||||
|
||||
stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
|
||||
gc._texturesActive=true;
|
||||
|
||||
|
||||
@@ -35,6 +35,22 @@
|
||||
#define ID_POLS MK_ID('P','O','L','S')
|
||||
#define ID_COLR MK_ID('C','O','L','R')
|
||||
|
||||
#define ID_CTEX MK_ID('C','T','E','X')
|
||||
#define ID_DTEX MK_ID('D','T','E','X')
|
||||
#define ID_STEX MK_ID('S','T','E','X')
|
||||
#define ID_RTEX MK_ID('R','T','E','X')
|
||||
#define ID_TTEX MK_ID('T','T','E','X')
|
||||
#define ID_BTEX MK_ID('B','T','E','X')
|
||||
|
||||
#define ID_TIMG MK_ID('T','I','M','G')
|
||||
#define ID_TFLG MK_ID('T','F','L','G')
|
||||
#define ID_TSIZ MK_ID('T','S','I','Z')
|
||||
#define ID_TCTR MK_ID('T','C','T','R')
|
||||
#define ID_TFAL MK_ID('T','F','A','L')
|
||||
#define ID_TVEL MK_ID('T','V','E','L')
|
||||
#define ID_TWRP MK_ID('T','W','R','P')
|
||||
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
@@ -132,6 +148,8 @@ static void read_surf(FILE *f, gint nbytes, lwObject *lwo)
|
||||
}
|
||||
g_return_if_fail(material != NULL);
|
||||
|
||||
lwTexture* tex = NULL;
|
||||
|
||||
/* read values */
|
||||
while (nbytes > 0) {
|
||||
gint id = read_long(f);
|
||||
@@ -145,6 +163,88 @@ static void read_surf(FILE *f, gint nbytes, lwObject *lwo)
|
||||
material->b = read_char(f) / 255.0f;
|
||||
read_char(f); /* dummy */
|
||||
break;
|
||||
case ID_CTEX:
|
||||
case ID_DTEX:
|
||||
case ID_STEX:
|
||||
case ID_RTEX:
|
||||
case ID_TTEX:
|
||||
case ID_BTEX:
|
||||
len -= read_string(f, name);
|
||||
if (id == ID_CTEX) {
|
||||
tex = &material->ctex;
|
||||
}
|
||||
else
|
||||
tex = NULL;
|
||||
break;
|
||||
case ID_TIMG: {
|
||||
len -= read_string(f, name);
|
||||
if (tex) {
|
||||
/* last component of path */
|
||||
char* slash = strrchr(name, '/');
|
||||
if (!slash)
|
||||
slash = strrchr(name, '\\');
|
||||
if (slash)
|
||||
strcpy(tex->name, slash+1);
|
||||
else
|
||||
strcpy(tex->name, name);
|
||||
//printf("tex name=%s\n", tex->name);
|
||||
}
|
||||
} break;
|
||||
case ID_TFLG:
|
||||
if (tex) {
|
||||
tex->flags = read_short(f);
|
||||
}
|
||||
else
|
||||
fseek(f, len+(len%2), SEEK_CUR);
|
||||
break;
|
||||
case ID_TSIZ:
|
||||
if (tex) {
|
||||
tex->sx = read_float(f);
|
||||
tex->sy = read_float(f);
|
||||
tex->sz = read_float(f);
|
||||
}
|
||||
else
|
||||
fseek(f, len+(len%2), SEEK_CUR);
|
||||
break;
|
||||
case ID_TCTR:
|
||||
if (tex) {
|
||||
tex->cx = read_float(f);
|
||||
tex->cy = read_float(f);
|
||||
tex->cz = read_float(f);
|
||||
}
|
||||
else
|
||||
fseek(f, len+(len%2), SEEK_CUR);
|
||||
break;
|
||||
case ID_TFAL:
|
||||
if (tex) {
|
||||
float vx,vy,vz;
|
||||
vx = read_float(f);
|
||||
vy = read_float(f);
|
||||
vz = read_float(f);
|
||||
//printf("fal %.2f %.2f %.2f\n", vx,vy,vz);
|
||||
}
|
||||
else
|
||||
fseek(f, len+(len%2), SEEK_CUR);
|
||||
break;
|
||||
case ID_TVEL:
|
||||
if (tex) {
|
||||
float vx,vy,vz;
|
||||
vx = read_float(f);
|
||||
vy = read_float(f);
|
||||
vz = read_float(f);
|
||||
//printf("vel %.2f %.2f %.2f\n", vx,vy,vz);
|
||||
}
|
||||
else
|
||||
fseek(f, len+(len%2), SEEK_CUR);
|
||||
break;
|
||||
case ID_TWRP:
|
||||
if (tex) {
|
||||
tex->u_wrap = (lwTextureWrap) read_short(f);
|
||||
tex->v_wrap = (lwTextureWrap) read_short(f);
|
||||
}
|
||||
else
|
||||
fseek(f, len+(len%2), SEEK_CUR);
|
||||
break;
|
||||
default:
|
||||
fseek(f, len+(len%2), SEEK_CUR);
|
||||
}
|
||||
@@ -175,7 +275,7 @@ static void read_pols(FILE *f, int nbytes, lwObject *lwo)
|
||||
|
||||
/* allocate space for points */
|
||||
face->index = (int*) g_malloc0(sizeof(int)*face->index_cnt);
|
||||
|
||||
|
||||
/* read points in */
|
||||
for (i=0; i<face->index_cnt; i++) {
|
||||
face->index[i] = read_short(f);
|
||||
@@ -271,7 +371,6 @@ lwObject *lw_object_read(const char *lw_file, std::ostream& output)
|
||||
|
||||
/* create new lwObject */
|
||||
lw_object = (lwObject*) g_malloc0(sizeof(lwObject));
|
||||
|
||||
lw_object->init();
|
||||
|
||||
/* read chunks */
|
||||
@@ -299,6 +398,45 @@ lwObject *lw_object_read(const char *lw_file, std::ostream& output)
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
for (int i = 0; i < lw_object->face_cnt; i++) {
|
||||
int mati = lw_object->face[i].material;
|
||||
if (mati == 0)
|
||||
continue;
|
||||
|
||||
/* fetch material */
|
||||
lwMaterial* mat = &lw_object->material[mati];
|
||||
unsigned int flags = mat->ctex.flags;
|
||||
if (flags == 0)
|
||||
continue;
|
||||
|
||||
/* calculate texture coordinates */
|
||||
lwFace* face = &lw_object->face[i];
|
||||
face->texcoord = (float*) g_malloc0(face->index_cnt * sizeof(float) * 2);
|
||||
for (int j = 0; j < face->index_cnt; j++) {
|
||||
int vi = face->index[j];
|
||||
GLfloat* vtx = &lw_object->vertex[vi*3];
|
||||
|
||||
GLfloat u,v;
|
||||
u = v = 0.0f;
|
||||
if (flags & X_AXIS) {
|
||||
u = (vtx[1] - mat->ctex.cy) / mat->ctex.sy;
|
||||
v = (vtx[2] - mat->ctex.cz) / mat->ctex.sz;
|
||||
}
|
||||
else if (flags & Y_AXIS) {
|
||||
u = (vtx[0] - mat->ctex.cx) / mat->ctex.sx;
|
||||
v = (vtx[2] - mat->ctex.cz) / mat->ctex.sz;
|
||||
}
|
||||
else if (flags & Z_AXIS) {
|
||||
u = (vtx[0] - mat->ctex.cx) / mat->ctex.sx;
|
||||
v = (vtx[1] - mat->ctex.cy) / mat->ctex.sy;
|
||||
}
|
||||
face->texcoord[j*2] = u + 0.5f;
|
||||
face->texcoord[j*2+1] = v + 0.5f;
|
||||
//printf("%.2f %.2f\n", u,v);
|
||||
}
|
||||
}
|
||||
|
||||
return lw_object;
|
||||
}
|
||||
|
||||
@@ -314,8 +452,11 @@ void lw_object_free(lwObject *lw_object)
|
||||
|
||||
if (lw_object->face) {
|
||||
int i;
|
||||
for (i=0; i<lw_object->face_cnt; i++)
|
||||
for (i=0; i<lw_object->face_cnt; i++) {
|
||||
g_free(lw_object->face[i].index);
|
||||
if (lw_object->face[i].texcoord)
|
||||
g_free(lw_object->face[i].texcoord);
|
||||
}
|
||||
g_free(lw_object->face);
|
||||
}
|
||||
g_free(lw_object->material);
|
||||
|
||||
@@ -26,10 +26,45 @@
|
||||
#define LW_MAX_POINTS 200
|
||||
#define LW_MAX_NAME_LEN 500
|
||||
|
||||
enum lwTextureFlags {
|
||||
X_AXIS = 0x01,
|
||||
Y_AXIS = 0x02,
|
||||
Z_AXIS = 0x04,
|
||||
WORLD_COORDS = 0x10,
|
||||
NEGATIVE_IMAGE = 0x20,
|
||||
PIXEL_BLENDING = 0x40,
|
||||
ANTIALIASING = 0x80
|
||||
};
|
||||
|
||||
enum lwTextureWrap {
|
||||
BLACK = 0,
|
||||
CLAMP = 1,
|
||||
REPEAT = 2,
|
||||
MIRROR_REPEAT = 3
|
||||
};
|
||||
|
||||
struct lwTexture
|
||||
{
|
||||
char name[LW_MAX_NAME_LEN];
|
||||
unsigned int flags;
|
||||
lwTextureWrap u_wrap, v_wrap;
|
||||
GLfloat sx,sy,sz;
|
||||
GLfloat cx,cy,cz;
|
||||
|
||||
void init() {
|
||||
name[0] = 0;
|
||||
flags = 0;
|
||||
u_wrap = v_wrap = REPEAT;
|
||||
sx = sy = sz = 0.0f;
|
||||
cx = cy = cz = 0.0f;
|
||||
}
|
||||
};
|
||||
|
||||
struct lwMaterial
|
||||
{
|
||||
char name[LW_MAX_NAME_LEN];
|
||||
GLfloat r,g,b;
|
||||
struct lwTexture ctex;
|
||||
|
||||
lwMaterial()
|
||||
{
|
||||
@@ -37,6 +72,7 @@ struct lwMaterial
|
||||
g=1.0f;
|
||||
b=1.0f;
|
||||
name[0] = 0;
|
||||
ctex.init();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -49,10 +85,10 @@ struct lwFace
|
||||
|
||||
void init()
|
||||
{
|
||||
material = 0; /* material of this face */
|
||||
index_cnt = 0; /* number of vertices */
|
||||
index = 0; /* index to vertex */
|
||||
texcoord = 0; /* u,v texture coordinates */
|
||||
material = 0; /* material of this face */
|
||||
index_cnt = 0; /* number of vertices */
|
||||
index = 0; /* index to vertex */
|
||||
texcoord = 0; /* u,v texture coordinates */
|
||||
}
|
||||
|
||||
};
|
||||
@@ -79,7 +115,6 @@ struct lwObject
|
||||
vertex_cnt=0;
|
||||
vertex = 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user