diff --git a/TODO b/TODO index 2b072c2df70..475a3648015 100644 --- a/TODO +++ b/TODO @@ -2,7 +2,7 @@ Residual TODO list (in rough order of priority): ------------------------------------------------ Assigned tasks: * Add LAF font and text drawing support (aquadran) - * Implement drawing 2D objects (frob) + * Implement FadeInChore and FadeOutChore (frob) Unassigned (help wanted): * Add OpenGL lighting (ender, possibly) diff --git a/bitmap.cpp b/bitmap.cpp index a5627c521f5..3b4cfc5fb55 100644 --- a/bitmap.cpp +++ b/bitmap.cpp @@ -41,7 +41,7 @@ Resource(filename) { format_ = READ_LE_UINT32(data + 32); width_ = READ_LE_UINT32(data + 128); height_ = READ_LE_UINT32(data + 132); - curr_image_ = 0; + curr_image_ = 1; data_ = new char*[num_images_]; int pos = 0x88; @@ -65,76 +65,98 @@ Resource(filename) { if (format_ == 1) { hasTransparency_ = false; - - // Convert data to 32-bit RGBA format - char *texData = new char[4 * width_ * height_]; - char *texDataPtr = texData; - uint16 *bitmapData = reinterpret_cast(data_[0]); - for (int i = 0; i < width_ * height_; - i++, texDataPtr += 4, bitmapData++) { - uint16 pixel = *bitmapData; - int r = pixel >> 11; - texDataPtr[0] = (r << 3) | (r >> 2); - int g = (pixel >> 5) & 0x3f; - texDataPtr[1] = (g << 2) | (g >> 4); - int b = pixel & 0x1f; - texDataPtr[2] = (b << 3) | (b >> 2); - if (pixel == 0xf81f) { // transparent - texDataPtr[3] = 0; - hasTransparency_ = true; - } - else - texDataPtr[3] = 255; - } - num_tex_ = ((width_ + (BITMAP_TEXTURE_SIZE - 1)) / BITMAP_TEXTURE_SIZE) * ((height_ + (BITMAP_TEXTURE_SIZE - 1)) / BITMAP_TEXTURE_SIZE); - tex_ids_ = new GLuint[num_tex_]; - glGenTextures(num_tex_, tex_ids_); - for (int i = 0; i < num_tex_; i++) { - glBindTexture(GL_TEXTURE_2D, tex_ids_[i]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - BITMAP_TEXTURE_SIZE, BITMAP_TEXTURE_SIZE, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); - } + tex_ids_ = new GLuint[num_tex_ * num_images_]; + glGenTextures(num_tex_ * num_images_, tex_ids_); - glPixelStorei(GL_UNPACK_ALIGNMENT, 2); - glPixelStorei(GL_UNPACK_ROW_LENGTH, width_); + char *texData = new char[4 * width_ * height_]; - int cur_tex_idx = 0; - for (int y = 0; y < height_; y += BITMAP_TEXTURE_SIZE) { - for (int x = 0; x < width_; x += BITMAP_TEXTURE_SIZE) { - int width = (x + BITMAP_TEXTURE_SIZE >= width_) ? (width_ - x) : BITMAP_TEXTURE_SIZE; - int height = (y + BITMAP_TEXTURE_SIZE >= height_) ? (height_ - y) : BITMAP_TEXTURE_SIZE; - glBindTexture(GL_TEXTURE_2D, tex_ids_[cur_tex_idx]); - glTexSubImage2D(GL_TEXTURE_2D, - 0, - 0, 0, - width, height, - GL_RGBA, - GL_UNSIGNED_BYTE, - texData + (y * 4 * width_) + (4 * x)); - cur_tex_idx++; + for (int pic = 0; pic < num_images_; pic++) { + // Convert data to 32-bit RGBA format + char *texDataPtr = texData; + uint16 *bitmapData = reinterpret_cast(data_[pic]); + for (int i = 0; i < width_ * height_; + i++, texDataPtr += 4, bitmapData++) { + uint16 pixel = *bitmapData; + int r = pixel >> 11; + texDataPtr[0] = (r << 3) | (r >> 2); + int g = (pixel >> 5) & 0x3f; + texDataPtr[1] = (g << 2) | (g >> 4); + int b = pixel & 0x1f; + texDataPtr[2] = (b << 3) | (b >> 2); + if (pixel == 0xf81f) { // transparent + texDataPtr[3] = 0; + hasTransparency_ = true; + } + else + texDataPtr[3] = 255; + } + + for (int i = 0; i < num_tex_; i++) { + glBindTexture(GL_TEXTURE_2D, tex_ids_[num_tex_ * pic + i]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + BITMAP_TEXTURE_SIZE, BITMAP_TEXTURE_SIZE, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + } + + glPixelStorei(GL_UNPACK_ALIGNMENT, 2); + glPixelStorei(GL_UNPACK_ROW_LENGTH, width_); + + int cur_tex_idx = num_tex_ * pic; + + for (int y = 0; y < height_; y += BITMAP_TEXTURE_SIZE) { + for (int x = 0; x < width_; x += BITMAP_TEXTURE_SIZE) { + int width = (x + BITMAP_TEXTURE_SIZE >= width_) ? (width_ - x) : BITMAP_TEXTURE_SIZE; + int height = (y + BITMAP_TEXTURE_SIZE >= height_) ? (height_ - y) : BITMAP_TEXTURE_SIZE; + glBindTexture(GL_TEXTURE_2D, tex_ids_[cur_tex_idx]); + glTexSubImage2D(GL_TEXTURE_2D, + 0, + 0, 0, + width, height, + GL_RGBA, + GL_UNSIGNED_BYTE, + texData + (y * 4 * width_) + (4 * x)); + cur_tex_idx++; + } } } + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); delete [] texData; } else { - for (int i = 0; i < (width_ * height_); i++) { - uint16 val = READ_LE_UINT16(data_[curr_image_] + 2 * i); - ((uint16 *) data_[curr_image_])[i] = - 0xffff - ((uint32) val) * 0x10000 / 100 / (0x10000 - val); + for (int pic = 0; pic < num_images_; pic++) { + uint16 *zbufPtr = reinterpret_cast(data_[pic]); + for (int i = 0; i < (width_ * height_); i++) { + uint16 val = READ_LE_UINT16(data_[pic] + 2 * i); + zbufPtr[i] = 0xffff - ((uint32) val) * 0x10000 / 100 / (0x10000 - val); + } + + // Flip the zbuffer image to match what GL expects + for (int y = 0; y < height_ / 2; y++) { + uint16 *ptr1 = zbufPtr + y * width_; + uint16 *ptr2 = zbufPtr + (height_ - 1 - y) * width_; + for (int x = 0; x < width_; x++, ptr1++, ptr2++) { + uint16 tmp = *ptr1; + *ptr1 = *ptr2; + *ptr2 = tmp; + } + } } + tex_ids_ = NULL; } } void Bitmap::draw() const { + if (curr_image_ == 0) + return; + glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, 640, 480, 0, 0, 1); @@ -153,18 +175,13 @@ void Bitmap::draw() const { glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); if (format_ == 1) { // Normal image - if (curr_image_ != 0) { - warning("Animation not handled yet in GL texture path !\n"); - } glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); glEnable(GL_SCISSOR_TEST); glScissor(x_, 480 - (y_ + height_), width_, height_); - int cur_tex_idx = 0; + int cur_tex_idx = num_tex_ * (curr_image_ - 1); for (int y = y_; y < (y_ + height_); y += BITMAP_TEXTURE_SIZE) { for (int x = x_; x < (x_ + width_); x += BITMAP_TEXTURE_SIZE) { - int width = (x + BITMAP_TEXTURE_SIZE >= (x_ + width_)) ? ((x_ + width_) - x) : BITMAP_TEXTURE_SIZE; - int height = (y + BITMAP_TEXTURE_SIZE >= (y_ + height_)) ? ((y_ + height_) - y) : BITMAP_TEXTURE_SIZE; glBindTexture(GL_TEXTURE_2D, tex_ids_[cur_tex_idx]); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); @@ -190,7 +207,7 @@ void Bitmap::draw() const { if ((ZBUFFER_GLOBAL == 0) || (SCREENBLOCKS_GLOBAL == 1)) return; - g_driver->drawDepthBitmap(curr_image_, x_, y_, width_, height_, data_); + g_driver->drawDepthBitmap(x_, y_, width_, height_, data_[curr_image_ - 1]); } } @@ -199,7 +216,7 @@ Bitmap::~Bitmap() { delete[] data_[i]; delete[] data_; if (tex_ids_) { - glDeleteTextures(num_tex_, tex_ids_); + glDeleteTextures(num_tex_ * num_images_, tex_ids_); delete[] tex_ids_; } } diff --git a/costume.cpp b/costume.cpp index fbb53589aa8..84fa36352ac 100644 --- a/costume.cpp +++ b/costume.cpp @@ -91,8 +91,6 @@ public: private: std::string filename_; - std::string zbuf_filename_; - ResPtr bitmap_; }; class ModelComponent : public Costume::Component { @@ -154,13 +152,16 @@ private: BitmapComponent::BitmapComponent(Costume::Component *parent, int parentID, const char *filename) : Costume::Component(parent, parentID), filename_(filename) { - - bitmap_ = ResourceLoader::instance()->loadBitmap(filename); - warning("Instanced BitmapComponenet from Costume renderer with filename %s: NOT IMPLEMENTED YET", filename); } void BitmapComponent::setKey(int val) { - // bitmap_->setNumber(val); + ObjectState *state = + Engine::instance()->currScene()->findState(filename_.c_str()); + if (state != NULL) + state->setNumber(val); + else + warning("Couldn't find bitmap %s in current scene\n", + filename_.c_str()); } ModelComponent::ModelComponent(Costume::Component *parent, int parentID, diff --git a/driver_gl.cpp b/driver_gl.cpp index a47a838486a..3da7808e73b 100644 --- a/driver_gl.cpp +++ b/driver_gl.cpp @@ -123,24 +123,26 @@ void Driver::finishActorDraw() { glPopMatrix(); } -void Driver::drawDepthBitmap(int num, int x, int y, int w, int h, char **data) { - if (num != 0) { - warning("Animation not handled yet in GL texture path !\n"); - } +void Driver::drawDepthBitmap(int x, int y, int w, int h, char *data) { + // if (num != 0) { + // warning("Animation not handled yet in GL texture path !\n"); + // } - glRasterPos2i(x, y); + if (y + h == 480) { + glRasterPos2i(x, 479); + glBitmap(0, 0, 0, 0, 0, -1, NULL); + } + else + glRasterPos2i(x, y + h); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDepthMask(GL_TRUE); - // This loop here is to prevent using PixelZoom that may be unoptimized for the 1.0 / -1.0 case - // in some drivers... + glPixelStorei(GL_UNPACK_ALIGNMENT, 2); + glDrawPixels(w, h, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, data); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - for (int row = 0; row < h; row++) { - glRasterPos2i(x, y + row + 1); - //glDrawPixels(w, 1, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, data[num] + (2 * row * w)); - } glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthFunc(GL_LESS); } diff --git a/driver_gl.h b/driver_gl.h index b0512ce5a16..ebe7b414ad1 100644 --- a/driver_gl.h +++ b/driver_gl.h @@ -39,7 +39,7 @@ class Driver { void startActorDraw(Vector3d pos, float yaw, float pitch, float roll); void finishActorDraw(); - void drawDepthBitmap(int num, int x, int y, int w, int h, char **data); + void drawDepthBitmap(int x, int y, int w, int h, char *data); void drawBitmap(); void drawHackFont(int x, int y, const char *text, Color &fgColor); diff --git a/lua.cpp b/lua.cpp index 40ffbd22452..f7d430a7e40 100644 --- a/lua.cpp +++ b/lua.cpp @@ -1095,18 +1095,12 @@ static void NewObjectState() { ObjectState::Position pos = check_objstate_pos(2); // When to draw char *bitmap = luaL_check_string(3); // Bitmap char *zbitmap = NULL; // Zbuffer Bitmap - bool unk1 = getbool(5); // ? - bool unk2 = getbool(6); + bool visible = getbool(5); // Starts visible? if (!lua_isnil(lua_getparam(4))) zbitmap = luaL_check_string(4); -#ifndef OSX - warning("Stub: newObjectState(%d, %d, %s, %s)", setupID, pos, bitmap, zbitmap); -#endif - - object = new ObjectState(setupID, pos, bitmap, zbitmap, - unk1, unk2); + object = new ObjectState(setupID, pos, bitmap, zbitmap, visible); Engine::instance()->currScene()->addObjectState(object); lua_pushusertag(object, object_tag); } diff --git a/objectstate.cpp b/objectstate.cpp index ff283b2a742..cb9807027c9 100644 --- a/objectstate.cpp +++ b/objectstate.cpp @@ -2,9 +2,16 @@ ObjectState::ObjectState(int setupID, ObjectState::Position pos, const char *bitmap, const char *zbitmap, - bool unk1, bool unk2) : - setupID_(setupID), pos_(pos), unk1_(unk1), unk2_(unk2) { + bool visible) : + setupID_(setupID), pos_(pos) { bitmap_ = ResourceLoader::instance()->loadBitmap(bitmap); if (zbitmap) zbitmap_ = ResourceLoader::instance()->loadBitmap(zbitmap); + + int initialImage = 0; + if (visible) + initialImage = 1; + bitmap_->setNumber(initialImage); + if (zbitmap_) + zbitmap_->setNumber(initialImage); } diff --git a/objectstate.h b/objectstate.h index a6367104371..5e069d0e5d0 100644 --- a/objectstate.h +++ b/objectstate.h @@ -18,7 +18,7 @@ class ObjectState { ObjectState(int setupID, ObjectState::Position pos, const char *bitmap, const char *zbitmap, - bool unk1, bool unk2); + bool visible); int setupID() const { return setupID_; } Position pos() const { return pos_; } @@ -26,6 +26,11 @@ class ObjectState { return bitmap_->filename(); } + void setNumber(int val) { + bitmap_->setNumber(val); + if (zbitmap_) + zbitmap_->setNumber(val); + } void draw() { bitmap_->draw(); if (zbitmap_) @@ -36,7 +41,6 @@ class ObjectState { int setupID_; Position pos_; ResPtr bitmap_, zbitmap_; - bool unk1_, unk2_; }; diff --git a/scene.cpp b/scene.cpp index d6f9dc13f2b..64aff26012f 100644 --- a/scene.cpp +++ b/scene.cpp @@ -169,3 +169,12 @@ void Scene::drawBitmaps(ObjectState::Position stage) { (*i)->draw(); } } + +ObjectState *Scene::findState(const char *filename) { + for (StateList::iterator i = states_.begin(); i != states_.end(); + i++) { + if (strcmp((*i)->bitmapFilename(), filename) == 0) + return *i; + } + return NULL; +} diff --git a/scene.h b/scene.h index d712f133f2a..9600321c856 100644 --- a/scene.h +++ b/scene.h @@ -70,6 +70,7 @@ public: void addObjectState(ObjectState *s) { states_.push_back(s); } + ObjectState *findState(const char *filename); private: struct Setup { // Camera setup data