From 444a6eaf97f175fbbd3d38214d3727a9d56d61e4 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 20 Sep 2002 15:54:17 +0000 Subject: [PATCH] From Ulrich Hertlien, supported add to textures in the .lwo format. --- src/osgPlugins/lwo/Lwo2.cpp | 56 +++++----- src/osgPlugins/lwo/ReaderWriterLWO.cpp | 26 +++-- src/osgPlugins/lwo/lw.cpp | 147 ++++++++++++++++++++++++- src/osgPlugins/lwo/lw.h | 45 +++++++- 4 files changed, 231 insertions(+), 43 deletions(-) diff --git a/src/osgPlugins/lwo/Lwo2.cpp b/src/osgPlugins/lwo/Lwo2.cpp index c8eb43520..3de9b4c85 100644 --- a/src/osgPlugins/lwo/Lwo2.cpp +++ b/src/osgPlugins/lwo/Lwo2.cpp @@ -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; diff --git a/src/osgPlugins/lwo/ReaderWriterLWO.cpp b/src/osgPlugins/lwo/ReaderWriterLWO.cpp index dcb1a53a6..f3117c82d 100644 --- a/src/osgPlugins/lwo/ReaderWriterLWO.cpp +++ b/src/osgPlugins/lwo/ReaderWriterLWO.cpp @@ -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; diff --git a/src/osgPlugins/lwo/lw.cpp b/src/osgPlugins/lwo/lw.cpp index 435c651cb..b7ce50510 100644 --- a/src/osgPlugins/lwo/lw.cpp +++ b/src/osgPlugins/lwo/lw.cpp @@ -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; iindex_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; iface_cnt; i++) + for (i=0; iface_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); diff --git a/src/osgPlugins/lwo/lw.h b/src/osgPlugins/lwo/lw.h index 8db6760f1..7198b52c9 100644 --- a/src/osgPlugins/lwo/lw.h +++ b/src/osgPlugins/lwo/lw.h @@ -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; } - };