void csMeshGeneratorGeometry::SetFadeParams (csMGGeom& geom, float opaqueDist, float scale) { float fadeInM, fadeInN, fadeOutM, fadeOutN; float max_opaque_dist = csMin (this->max_opaque_dist, opaqueDist); float max_draw_dist = csMin (total_max_dist, (fabsf (scale) > EPSILON ? 1.0f/scale : 0) + opaqueDist); float min_fade_dist = min_opaque_dist-min_draw_dist; if (fabsf (min_fade_dist) > EPSILON) { fadeInM = 1.0f/(min_fade_dist); fadeInN = -min_draw_dist * fadeInM; } else { fadeInM = 0; fadeInN = 1; } float max_fade_dist = max_opaque_dist-max_draw_dist; if (fabsf (max_fade_dist) > EPSILON) { fadeOutM = 1.0f/(max_fade_dist); fadeOutN = -max_opaque_dist*fadeOutM + 1; } else { fadeOutM = 0; fadeOutN = 1; } geom.fadeInfoVar->SetValue (csVector4 (fadeInM, fadeInN, fadeOutM, fadeOutN)); }
void TileHelper::GetTileRect (size_t n, csRect& r) const { int x = int (n) % tx; int y = int (n) / tx; r.xmin = x * tileSizeX; r.ymin = y * tileSizeY; r.xmax = csMin ((x+1) * tileSizeX, w); r.ymax = csMin ((y+1) * tileSizeY, h); }
void pawsBorder::Draw() { if ( !draw ) return; frame = parent->GetScreenFrame(); if (title.Length()) DrawTitle(frame); // This adjusts the frame to preserve the title bar if present. if ( !usingGraphics ) { //if ( !justTitle ) // DrawFrame(frame); return; } ///////////////////////////// // Draw tiles across the top and bottom ///////////////////////////// borderImages[PAWS_BORDER_TOPLEFT]->Draw( frame.xmin - borderImages[PAWS_BORDER_TOPLEFT]->GetWidth(), frame.ymin - borderImages[PAWS_BORDER_TOPLEFT]->GetHeight() ); borderImages[PAWS_BORDER_BOTTOMLEFT]->Draw( frame.xmin - borderImages[PAWS_BORDER_BOTTOMLEFT]->GetWidth(), frame.ymax ); int locX, locY = frame.ymin - borderImages[PAWS_BORDER_TOPMIDDLE]->GetHeight(); for (locX = frame.xmin; locX < frame.xmax; locX += borderImages[PAWS_BORDER_TOPMIDDLE]->GetWidth() ) { borderImages[PAWS_BORDER_TOPMIDDLE]->Draw( locX, locY, csMin(borderImages[PAWS_BORDER_TOPMIDDLE]->GetWidth(),frame.xmax-locX), 0 ); borderImages[PAWS_BORDER_BOTTOMMIDDLE]->Draw( locX, frame.ymax, csMin(borderImages[PAWS_BORDER_BOTTOMMIDDLE]->GetWidth(),frame.xmax-locX), 0 ); } ///////////////////////////// // Draw tiles down the left and right ///////////////////////////// locX = frame.xmin - borderImages[PAWS_BORDER_LEFTMIDDLE]->GetWidth(); for (locY = frame.ymin; locY < frame.ymax; locY += borderImages[PAWS_BORDER_LEFTMIDDLE]->GetHeight() ) { borderImages[PAWS_BORDER_LEFTMIDDLE]->Draw( locX, locY, 0, csMin(borderImages[PAWS_BORDER_LEFTMIDDLE]->GetHeight(), frame.ymax-locY) ); borderImages[PAWS_BORDER_RIGHTMIDDLE]->Draw( frame.xmax, locY, 0, csMin(borderImages[PAWS_BORDER_RIGHTMIDDLE]->GetHeight(), frame.ymax-locY) ); } borderImages[PAWS_BORDER_TOPRIGHT]->Draw( frame.xmax, frame.ymin - borderImages[PAWS_BORDER_TOPRIGHT]->GetHeight() ); borderImages[PAWS_BORDER_BOTTOMRIGHT]->Draw( frame.xmax, frame.ymax ); }
void DirectionMap::AddFromLightInfluences (const LightInfluences& influences) { ScopedSwapLock<DirectionMap> l (*this); ScopedSwapLock<LightInfluences> l2 (influences); uint inflW = csMin (influences.GetWidth(), width-influences.GetXOffset()); uint inflH = csMin (influences.GetHeight(), height-influences.GetYOffset()); for (uint y = 0; y < inflH; y++) { for (uint x = 0; x < inflW; x++) { mapData[(x+influences.GetXOffset())+width*(y+influences.GetYOffset())] += influences.GetDirectionForLocalCoord (x, y); } } }
void pawsWritingWindow::OnStringEntered(const char* /*name*/, int /*param*/, const char* value) { const unsigned int MAX_BOOK_FILE_SIZE = 60000; csString fileName; iVFS* vfs = psengine->GetVFS(); if (!value) return; fileName.Format("/planeshift/userdata/books/%s", value); if (!vfs->Exists(fileName)) { psSystemMessage msg(0, MSG_ERROR, "File %s not found!", fileName.GetDataSafe()); msg.FireEvent(); return; } csRef<iDataBuffer> data = vfs->ReadFile(fileName); if (data->GetSize() > MAX_BOOK_FILE_SIZE) { psSystemMessage msg(0, MSG_ERROR, "File too big, data trimmed to %d chars.", MAX_BOOK_FILE_SIZE ); msg.FireEvent(); } csString book(data->GetData(), csMin(data->GetSize(), (size_t)MAX_BOOK_FILE_SIZE)); book.ReplaceAll("\r\n", "\n"); lefttext->SetText(book, true); psSystemMessage msg(0, MSG_ACK, "Book Loaded Successfully!" ); msg.FireEvent(); }
void PositionMap::InsertNewArea (const csBox2& areaBox) { float side1 = areaBox.MaxX() - areaBox.MinX(); float side2 = areaBox.MaxY() - areaBox.MinY(); float minSide = csMin (side1, side2); /* Insert area into bucket with the largest radius smaller or equal to minSide */ for (size_t b = 0; b < buckets.GetSize(); b++) { Bucket& bucket = buckets[b]; if (minSide >= bucket.minSide) { Bucket::Area newArea; newArea.area = side1*side2; newArea.box = GetBoxAlloc()->Alloc (areaBox); size_t index = bucket.freeAreas.Push (newArea); if (index > 0) { size_t parent = (index-1) / 2; if (bucket.freeAreas[parent].box) { // 'Parent' node is a leaf, turn it into a node bucket.freeAreas.Push (bucket.freeAreas[parent]); bucket.freeAreas[parent].box = nullptr; } } BubbleAreaIncrease (bucket, index, newArea.area); break; } } }
bool csWrappedDocumentNode::InvokeTemplate (Template* templ, const Template::Params& params, Template::Nodes& templatedNodes) { if (!templ) return false; csRef<Substitutions> newSubst; { Substitutions paramSubst; for (size_t i = 0; i < csMin (params.GetSize (), templ->paramMap.GetSize ()); i++) { shared->DebugProcessing (" %s -> %s\n", templ->paramMap[i].GetData(), params[i].GetData()); paramSubst.Put (templ->paramMap[i], params[i]); } newSubst.AttachNew (new Substitutions (paramSubst)); } for (size_t i = 0; i < templ->nodes.GetSize (); i++) { csRef<iDocumentNode> newNode = shared->replacerFactory.CreateWrapper (templ->nodes.Get (i), 0, newSubst); templatedNodes.Push (newNode); } return true; }
bool psLinearMovement::InitCD (const csVector3& body, const csVector3& legs, const csVector3& shift, iMeshWrapper* meshWrap) { mesh = meshWrap; topSize = body; bottomSize = legs; if (bottomSize.x * bottomSize.y > (0.8f * 1.4f + 0.1f)) hugGround = true; intervalSize.x = csMin(topSize.x, bottomSize.x); intervalSize.y = csMin(topSize.y, bottomSize.y); intervalSize.z = csMin(topSize.z, bottomSize.z); float maxX = csMax(body.x, legs.x)+shift.x; float maxZ = csMax(body.z, legs.z)+shift.z; float bX2 = body.x / 2.0f; float bZ2 = body.z / 2.0f; float bYbottom = legs.y; float bYtop = legs.y + body.y; csBox3 top (csVector3 (-bX2, bYbottom, -bZ2) + shift, csVector3 (bX2, bYtop, bZ2) + shift); float lX2 = legs.x / 2.0f; float lZ2 = legs.z / 2.0f; csBox3 bot (csVector3 (-lX2, 0, -lZ2) + shift, csVector3 (lX2, 0 + legs.y, lZ2) + shift); boundingBox.Set(csVector3(-maxX / 2.0f, 0, -maxZ / 2.0f) + shift, csVector3(maxX / 2.0f, bYtop, maxZ / 2.0f) + shift); psLinearMovement::shift = shift; cdsys = csQueryRegistry<iCollideSystem> (object_reg); if (colldet) delete colldet; colldet = new psCollisionDetection(object_reg); return colldet->Init (topSize, bottomSize, shift, mesh); }
void AddPoly (const csPoly2D& poly2D, const csPoly3D& poly3D) { size_t numVertsToCopy = csMin (vertsSize, poly2D.GetVertexCount()); memcpy (verts2D, poly2D.GetVertices(), numVertsToCopy * sizeof (csVector2)); memcpy (verts3D, poly3D.GetVertices(), numVertsToCopy * sizeof (csVector3)); vertsSize -= numVertsToCopy; verts2D += numVertsToCopy; verts3D += numVertsToCopy; *numVerts++ = numVertsToCopy; }
void GenmeshAnimationPDL::UpdateBuffer (ColorBuffer& buffer, csTicks current, const csColor4* colors, int num_colors, uint32 version_id) { if (buffer.lightsDirty || (buffer.lastMeshVersion != version_id)) { size_t numUpdate = csMin (buffer.staticColors->GetElementCount(), (size_t)num_colors); csDirtyAccessArray<csColor4>& combinedColors = buffer.combinedColors; combinedColors.SetSize (num_colors); { csVertexListWalker<float, csColor> color (buffer.staticColors, 3); if (colors) { for (size_t n = 0; n < numUpdate; n++) { combinedColors[n].Set ((*color).red, (*color).green, (*color).blue, colors[n].alpha); ++color; } } else { for (size_t n = 0; n < numUpdate; n++) { combinedColors[n].Set ((*color).red, (*color).green, (*color).blue, 1.0f); ++color; } } } ColorBuffer::LightsHash::GlobalIterator iter (buffer.lights.GetIterator()); while (iter.HasNext()) { csPtrKey<iLight> l; ColorBuffer::MappedLight& light = iter.Next (l); csVertexListWalker<float, csColor> color (light.colors, 3); csColor lightColor = l->GetColor(); for (size_t n = 0; n < numUpdate; n++) { combinedColors[n] += *color * lightColor; ++color; } light.lastUpdateColor = lightColor; } buffer.lightsDirty = false; buffer.lastMeshVersion = version_id; } }
void ProctexPDLight::PDMap::UpdateTiles (const TileHelper& helper) { for (size_t t = 0; t < tiles.GetSize(); t++) { Tile& tile = tiles[t]; csRect tileRect; helper.GetTileRect (t, tileRect); const csRect& lightInTile (nonNullAreas[t]); tile.tilePartX = (lightInTile.xmin - tileRect.xmin); tile.tilePartY = (lightInTile.ymin - tileRect.ymin); tile.tilePartW = csMin (lightInTile.xmax, imageX + imageW) - csMax (lightInTile.xmin, imageX); tile.tilePartH = csMin (lightInTile.ymax, imageY + imageH) - csMax (lightInTile.ymin, imageY); tile.tilePartPitch = imageW - tile.tilePartW; if (imageData->IsGray()) { tile.tilePartData = static_cast<LumelBufferGray*> ( (LumelBufferBase*)imageData)->GetData() + (lightInTile.ymin - imageY) * imageW + (lightInTile.xmin - imageX); } else { tile.tilePartData = static_cast<LumelBufferRGB*> ( (LumelBufferBase*)imageData)->GetData() + (lightInTile.ymin - imageY) * imageW + (lightInTile.xmin - imageX); } } tiles.ShrinkBestFit (); nonNullAreas.DeleteAll (); }
static size_t cs_ogg_read (void *ptr, size_t size, size_t nmemb, void *datasource) { OggStreamData *streamdata = (OggStreamData *)datasource; OggDataStore *ds = streamdata->datastore; // size_t is unsigned, be careful with subtraction. A 0 return indicates end of stream. if (ds->length <= (size_t)streamdata->position) return 0; size_t br = csMin (size*nmemb, ds->length - streamdata->position); memcpy (ptr, ds->data+streamdata->position, br); streamdata->position += br; return br; }
csBasicString<CharT> csBasicString<CharT>::mid(const int pos, const int n) const { if( empty() || pos < 0 || (size_t)pos >= size() ) { csBasicString<CharT>(); } const size_t len = n < 1 ? size() - (size_t)pos : csMin((size_t)n, size() - (size_t)pos); csBasicString<CharT> res(len+1); for(size_t i = 0; i < len; i++) { res[i] = operator[]((size_t)pos+i); } return res; }
void csConsoleOutput::SetPosition(int x, int y, int width, int height) { if (!font) return; if (x >= 0) size.xmin = x; if (y >= 0) size.ymin = y; if (width >= 0) size.xmax = size.xmin + width; if (height >= 0) size.ymax = size.ymin + height; // Make sure we don't go off the current screen if (size.xmax >= G2D->GetWidth ()) size.xmax = G2D->GetWidth () - 1; if (size.ymax >= G2D->GetHeight ()) size.ymax = G2D->GetHeight () - 1; // Calculate the number of lines on the console int fw, fh; font->GetMaxSize (fw, fh); buffer->SetPageSize (size.Height () / (fh + 2)); // Invalidate the entire new area of the console invalid.Set (size); // Update cursor coordinates cy = csMin (cy, buffer->GetPageSize ()); // now check how many chars do fit in the current width const csString *text = buffer->GetLine (cy); if (!text) cx = 0; else { csString curText (*text); curText.Truncate (cx); while (cx) { int fw, fh; font->GetDimensions (curText.GetData (), fw, fh); if (fw <= size.Width ()) break; curText.Truncate (--cx); } } }
void pawsScrollBar::MoveThumbToMouse() { psPoint mousePos; int relMouseCoord, // coordinate of mouse cursor relative to the rectangle that constraints thumb movement rectBegin, // coordinate of the constraint rectangle rectSize, // size of the constraint rectangle thumbPos; // coordinate of thumb relative to the constraint rectangle int scrollBarSize = GetScrollBarSize(); mousePos = PawsManager::GetSingleton().GetMouse()->GetPosition(); if(horizontal) { rectBegin = screenFrame.xmin + scrollBarSize; relMouseCoord = mousePos.x - rectBegin; } else { rectBegin = screenFrame.ymin + scrollBarSize; relMouseCoord = mousePos.y - rectBegin; } rectSize = GetThumbScaleLength(); if(mouseIsDraggingThumb) thumbPos = relMouseCoord - thumbDragPoint; else thumbPos = relMouseCoord - (scrollBarSize - 2*THUMB_MARGIN) / 2; thumbPos = csMax(thumbPos, 0); thumbPos = csMin(thumbPos, rectSize); if(horizontal) thumb->MoveTo(rectBegin+thumbPos, thumb->GetScreenFrame().ymin); else thumb->MoveTo(thumb->GetScreenFrame().xmin, rectBegin+thumbPos); currentValue = minValue + (float(thumbPos) / rectSize * (maxValue-minValue)); if(limited) LimitCurrentValue(); if(parent != NULL) parent->OnScroll(SCROLL_THUMB, this); }
bool LightingSorter::GetNextLight (LightInfo& out) { csArray<LightInfo>& putBackLights = persist.putBackLights; size_t i = 0; if (i >= lightLimit + putBackLights.GetSize()) return false; if (i < putBackLights.GetSize()) { size_t j = putBackLights.GetSize()-1-i; out = putBackLights[j]; putBackLights.DeleteIndex (j); } else { out = persist.lightTypeScratch[i]; persist.lightTypeScratch.DeleteIndex (i); } lightLimit = csMin (persist.lightTypeScratch.GetSize(), lightLimit); return true; }
mng_bool ImageJngFile::cb_readdata (mng_handle hHandle, mng_ptr pBuf, mng_uint32 iBuflen, mng_uint32 *pRead) { ImageJngFile *this_; this_ = (ImageJngFile *)mng_get_userdata (hHandle); // determine amount of data to read; 0 if EOF *pRead = (mng_uint32)csMin ((size_t)iBuflen, this_->bufferSize - (this_->bufptr - this_->buffer)); if (*pRead > 0) { memcpy (pBuf, this_->bufptr, *pRead); this_->bufptr += *pRead; } else *pRead = 0; return MNG_TRUE; }
void psLinearMovement::TickEveryFrame () { if (!mesh) { return; } csTicks elapsed_time = vc->GetElapsedTicks (); if (!elapsed_time) return; float delta = elapsed_time / 1000.0f; // Compensate for offset OffsetSprite (delta); if (fabsf (deltaLimit) > SMALL_EPSILON) delta = csMin(delta, deltaLimit); // Adjust the properties. ExtrapolatePosition (delta); }
void csTerrainCell::UnlockHeightData () { Touch(); minHeight = FLT_MAX; maxHeight = -FLT_MAX; for (size_t i = 0; i < heightmap.GetSize (); ++i) { minHeight = csMin (minHeight, heightmap[i]); maxHeight = csMax (maxHeight, heightmap[i]); } const csVector3 size01 = size * 0.1f; boundingBox.Set (position.x - size01.x, minHeight - size01.y, position.y - size01.z, position.x + size.x + size01.x, maxHeight + size01.y, position.y + size.z + size01.z); terrain->CellSizeUpdate (this); terrain->FireHeightUpdateCallbacks (this, lockedHeightRect); }
bool Location::CheckWithinBounds(iEngine* engine,const csVector3 &p,const iSector* sector) { if(!IsRegion()) return false; if(GetSector(engine) != sector) return false; // Thanks to http://astronomy.swin.edu.au/~pbourke/geometry/insidepoly/ // for this example code. int counter = 0; size_t i,N=locs.GetSize(); float xinters; csVector3 p1,p2; p1 = locs[0]->pos; for(i=1; i<=N; i++) { p2 = locs[i % N]->pos; if(p.z > csMin(p1.z,p2.z)) { if(p.z <= csMax(p1.z,p2.z)) { if(p.x <= csMax(p1.x,p2.x)) { if(p1.z != p2.z) { xinters = (p.z-p1.z)*(p2.x-p1.x)/(p2.z-p1.z)+p1.x; if(p1.x == p2.x || p.x <= xinters) counter++; } } } } p1 = p2; } return (counter % 2 != 0); }
bool LightingSorter::GetNextLight (const LightSettings& settings, LightInfo& out) { csArray<LightInfo>& putBackLights = persist.putBackLights; size_t i = 0; while (i < lightLimit + putBackLights.GetSize()) { if (i < putBackLights.GetSize()) { size_t j = putBackLights.GetSize()-1-i; if (putBackLights[j].settings == settings) break; } else { size_t j = i-putBackLights.GetSize(); if (persist.lightTypeScratch[j].settings == settings) break; } i++; } if (i >= lightLimit + putBackLights.GetSize()) return false; if (i < putBackLights.GetSize()) { size_t j = putBackLights.GetSize()-1-i; out = putBackLights[j]; putBackLights.DeleteIndex (j); } else { out = persist.lightTypeScratch[i]; persist.lightTypeScratch.DeleteIndex (i); } lightLimit = csMin (persist.lightTypeScratch.GetSize(), lightLimit); return true; }
void NavGen::Run() { csPrintf("Navmesh Generator.\n\n"); csRef<iCommandLineParser> cmdline = csQueryRegistry<iCommandLineParser>(object_reg); if (csCommandLineHelper::CheckHelp (object_reg)) { PrintHelp(); return; } csString basePath = "/planeshift/"; csString materials = cmdline->GetOption("materials"); if(materials.IsEmpty()) materials = config->GetStr("NavGen.MaterialDir", basePath+"materials/"); csString meshes = cmdline->GetOption("meshes"); if(meshes.IsEmpty()) meshes = config->GetStr("NavGen.MeshDir", basePath+"meshes/"); csString world = cmdline->GetOption("world"); if(world.IsEmpty()) world = config->GetStr("NavGen.WorldDir", basePath+"world/"); csString output = cmdline->GetOption("output"); if(output.IsEmpty()) output = config->GetStr("NavGen.OutputDir", basePath+"navmesh"); float height = config->GetFloat("NavGen.Agent.Height", 2.f); float width = config->GetFloat("NavGen.Agent.Width", 0.5f); float slope = config->GetFloat("NavGen.Agent.Slope", 45.f); float step = config->GetFloat("NavGen.Agent.MaxStepSize", 0.5f); float cellSize = config->GetFloat("NavGen.CellSize", width/2); float cellHeight = config->GetFloat("NavGen.CellHeight", cellSize/2); int tileSize = config->GetInt("NavGen.TileSize", 64) / cellSize; int borderSize = csMin(config->GetInt("NavGen.BorderSize", width+1),1); csRef<iEventQueue> queue = csQueryRegistry<iEventQueue>(object_reg); csRef<iVirtualClock> vc = csQueryRegistry<iVirtualClock>(object_reg); // Disable threaded loading. csRef<iThreadManager> tman = csQueryRegistry<iThreadManager>(object_reg); tman->SetAlwaysRunNow(true); // output execution parameters csPrintf("-- INPUT Parameters --\n"); csPrintf("Materials: %s\n", materials.GetData()); csPrintf("Meshes: %s\n", meshes.GetData()); csPrintf("World: %s\n", world.GetData()); csPrintf("NavGen.Agent.Height: %f\n", height); csPrintf("NavGen.Agent.Width: %f\n", width); csPrintf("NavGen.Agent.Slope: %f\n", slope); csPrintf("NavGen.Agent.MaxStepSize: %f\n", step); csPrintf("NavGen.CellSize: %f\n", cellSize); csPrintf("NavGen.CellHeight: %f\n", cellHeight); csPrintf("NavGen.TileSize: %d\n", tileSize); csPrintf("NavGen.BorderSize: %d\n", borderSize); csPrintf("---\n"); vc->Advance(); queue->Process(); // precache materials { csPrintf("Caching materials...\n"); csRef<iThreadReturn> ret = loader->PrecacheDataWait(materials+"materials.cslib"); if(!ret->IsFinished() || !ret->WasSuccessful()) { csPrintf("Failed to cache materials\n"); return; } } vc->Advance(); queue->Process(); // precache world { csPrintf("Finding meshes and world...\n"); csRef<iStringArray> meshFiles = vfs->FindFiles(meshes); csRef<iStringArray> worldFiles = vfs->FindFiles(world); size_t progress = 0; csPrintf("Caching meshes...\n"); csRefArray<iThreadReturn> returns; for(size_t i = 0; i < meshFiles->GetSize(); i++) { returns.Push(loader->PrecacheData(meshFiles->Get(i))); } csPrintf("Finishing mesh cache...\n"); while(!returns.IsEmpty()) { for(size_t i = 0; i < returns.GetSize(); i++) { csRef<iThreadReturn> ret = returns.Get(i); if(ret->IsFinished()) { if(!ret->WasSuccessful()) { } returns.DeleteIndex(i); i--; progress++; } } // print progress vc->Advance(); queue->Process(); csSleep(100); // wait a bit before checking again } csPrintf("Caching world...\n"); for(size_t i = 0; i < worldFiles->GetSize(); i++) { returns.Push(loader->PrecacheData(worldFiles->Get(i))); } csPrintf("Finishing world cache...\n"); while(!returns.IsEmpty()) { for(size_t i = 0; i < returns.GetSize(); i++) { csRef<iThreadReturn> ret = returns.Get(i); if(ret->IsFinished()) { if(!ret->WasSuccessful()) { } returns.DeleteIndex(i); i--; progress++; } } // print progress vc->Advance(); queue->Process(); csSleep(100); // wait a bit before checking again } } // load world { csPrintf("Loading world...\n"); if(!loader->LoadZones()) { csPrintf("failed to load world\n"); return; } csPrintf("Finishing world load...\n"); while(loader->GetLoadingCount()) { loader->ContinueLoading(true); // print progress vc->Advance(); queue->Process(); csSleep(100); } } // process navmesh { csPrintf("Loading meshes from sectors...\n"); // set creation parameters csRef<iCelNavMeshParams> parameters; parameters.AttachNew(builder->GetNavMeshParams()->Clone()); parameters->SetSuggestedValues(height, width, slope); parameters->SetAgentMaxClimb(step); parameters->SetTileSize(tileSize); parameters->SetCellSize(cellSize); parameters->SetCellHeight(cellHeight); parameters->SetBorderSize(borderSize); builder->SetNavMeshParams(parameters); // get list of loaded sectors csRefArray<iSector> sectors; csRef<iSectorList> sectorList = engine->GetSectors(); for(int i = 0; i < sectorList->GetCount(); i++) { sectors.Push(sectorList->Get(i)); } // set sectors in navigation mesh if(!builder->SetSectors(§ors)) { csPrintf("failed to set sector on navigation mesh builder\n"); return; } // build navmesh csPrintf("Building navmesh...\n"); csRef<iCelHNavStruct> navMesh = builder->BuildHNavStruct(); if(!navMesh.IsValid()) { csPrintf("failed to build navigation mesh\n"); return; } csPrintf("Done generating, writing navmesh\n"); // save navmesh if(!navMesh->SaveToFile(vfs, output)) { csPrintf("failed to save navigation data"); return; } } csPrintf("Done writing, closing up.\n"); loader.Invalidate(); builder.Invalidate(); config.Invalidate(); vfs.Invalidate(); csRef<iThreadReturn> ret = engine->DeleteAll(); while(!ret->IsFinished()) { vc->Advance(); queue->Process(); csSleep(100); } }
void csVProcStandardProgram::SetupState (const csRenderMesh* mesh, csRenderMeshModes& modes, const csShaderVariableStack& stack) { bool skin_updated = false;// @@@ FIXME - time related detection if vertices are not already updated if (doVertexSkinning || doNormalSkinning || doTangentSkinning || doBiTangentSkinning) { skin_updated = UpdateSkinnedVertices (modes, stack); } if (numLights > 0) { int lightsActive = 0; CS::ShaderVarStringID id; id = shaderPlugin->lsvCache.GetDefaultSVId ( csLightShaderVarCache::varLightCount); csShaderVariable* sv; if ((stack.GetSize () > id) && ((sv = stack[id]) != 0)) sv->GetValue (lightsActive); iRenderBuffer *vbuf = doVertexSkinning && skin_updated ? modes.buffers->GetRenderBuffer (skinnedPositionOutputBuffer) : GetBuffer (positionBuffer, modes, stack); iRenderBuffer *nbuf = doNormalSkinning && skin_updated ? modes.buffers->GetRenderBuffer (skinnedNormalOutputBuffer) : GetBuffer (normalBuffer, modes, stack); iRenderBuffer *cbuf = GetBuffer (colorBuffer, modes, stack); if (vbuf == 0 || nbuf == 0) return; csReversibleTransform camtrans; if ((stack.GetSize () > shaderPlugin->string_world2camera) && ((sv = stack[shaderPlugin->string_world2camera]) != 0)) sv->GetValue (camtrans); csVector3 eyePos (camtrans.GetT2OTranslation ()); csVector3 eyePosObject (mesh->object2world.Other2This (eyePos)); bool hasAlpha = cbuf && cbuf->GetComponentCount() >= 4; //copy output size_t elementCount = vbuf->GetElementCount (); csRef<iRenderBuffer> clbuf; if (doDiffuse) { clbuf = csRenderBuffer::CreateRenderBuffer (elementCount, CS_BUF_STREAM, CS_BUFCOMP_FLOAT, hasAlpha ? 4 : 3); // @@@ FIXME: should probably get rid of the multiple locking/unlocking... csRenderBufferLock<float> tmpColor (clbuf); memset (tmpColor, 0, sizeof(float) * (hasAlpha?4:3) * elementCount); } csRef<iRenderBuffer> specBuf; if (doSpecular) { specBuf = csRenderBuffer::CreateRenderBuffer (elementCount, CS_BUF_STREAM, CS_BUFCOMP_FLOAT, 3); csRenderBufferLock<float> tmpColor (specBuf); memset (tmpColor, 0, sizeof(csColor) * elementCount); } float shininess = GetParamFloatVal (stack, shininessParam, 0.0f); if (lightsActive > 0) { if (lightMixMode == LIGHTMIXMODE_NONE) { //only calculate last, other have no effect const size_t lightNum = csMin((size_t)lightsActive, numLights)-1; if ((disableMask.GetSize() <= lightNum) || !disableMask.IsBitSet (lightNum)) { csLightProperties light (lightNum, shaderPlugin->lsvCache, stack, mesh->object2world); iVertexLightCalculator *calc = shaderPlugin->GetLightCalculator (light, useAttenuation); calc->CalculateLighting (light, eyePosObject, shininess, elementCount, vbuf, nbuf, clbuf, specBuf); } } else { LightMixmode useMixMode = LIGHTMIXMODE_ADD; for (size_t i = 0; i < (csMin((size_t)lightsActive, numLights)); i++) { if ((disableMask.GetSize() > i) && disableMask.IsBitSet (i)) { useMixMode = lightMixMode; continue; } csLightProperties light (i, shaderPlugin->lsvCache, stack, mesh->object2world); iVertexLightCalculator *calc = shaderPlugin->GetLightCalculator (light, useAttenuation); switch (useMixMode) { case LIGHTMIXMODE_ADD: { calc->CalculateLightingAdd (light, eyePosObject, shininess, elementCount, vbuf, nbuf, clbuf, specBuf); break; } case LIGHTMIXMODE_MUL: { calc->CalculateLightingMul (light, eyePosObject, shininess, elementCount, vbuf, nbuf, clbuf, specBuf); break; } case LIGHTMIXMODE_NONE: break; } useMixMode = lightMixMode; } } } if (doDiffuse && cbuf) { switch (colorMixMode) { case LIGHTMIXMODE_NONE: if (!hasAlpha) break; { csVertexListWalker<float> cbufWalker (cbuf, 4); csRenderBufferLock<csVector4, iRenderBuffer*> tmpColor (clbuf); for (size_t i = 0; i < elementCount; i++) { const float* c = cbufWalker; tmpColor[i].w = c[3]; ++cbufWalker; } } break; case LIGHTMIXMODE_ADD: { csVertexListWalker<float> cbufWalker (cbuf, 4); csRenderBufferLock<csVector4, iRenderBuffer*> tmpColor (clbuf); for (size_t i = 0; i < elementCount; i++) { csVector4& t = tmpColor[i]; const float* c = cbufWalker; for (int j = 0; j < 3; j++) t[j] += c[j]; if (hasAlpha) t[3] = c[3]; ++cbufWalker; } } break; case LIGHTMIXMODE_MUL: { csVertexListWalker<float> cbufWalker (cbuf, 4); csRenderBufferLock<csVector4, iRenderBuffer*> tmpColor (clbuf); for (size_t i = 0; i < elementCount; i++) { csVector4& t = tmpColor[i]; const float* c = cbufWalker; for (int j = 0; j < 3; j++) t[j] *= c[j]; if (hasAlpha) t[3] = c[3]; ++cbufWalker; } } break; default: CS_ASSERT (false); } if (doSpecular && specularOnDiffuse) { csRenderBufferLock<csColor> tmpColor (clbuf); csRenderBufferLock<csColor> tmpColor2 (specBuf); for (size_t i = 0; i < elementCount; i++) { tmpColor[i] += tmpColor2[i]; } } } float finalLightFactorReal = GetParamFloatVal (stack, finalLightFactor, 1.0f); if (doDiffuse) { { csRenderBufferLock<csColor> tmpColor (clbuf); for (size_t i = 0; i < elementCount; i++) { tmpColor[i] *= finalLightFactorReal; } } modes.buffers->SetAccessor (modes.buffers->GetAccessor(), modes.buffers->GetAccessorMask() & ~CS_BUFFER_COLOR_MASK); modes.buffers->SetRenderBuffer (CS_BUFFER_COLOR, clbuf); } if (doSpecular && !specularOnDiffuse) { csRenderBufferLock<csColor> tmpColor (specBuf); for (size_t i = 0; i < elementCount; i++) { tmpColor[i] *= finalLightFactorReal; } modes.buffers->SetAccessor (modes.buffers->GetAccessor(), modes.buffers->GetAccessorMask() & ~(1 << specularOutputBuffer)); modes.buffers->SetRenderBuffer (specularOutputBuffer, specBuf); } } }
void ZoneHandler::OnDrawingFinished() { if(loading) { if(psengine->GetLoader()->GetLoadingCount() == 0 && csGetTicks() >= forcedLoadingEndTime) { // This is a bit of a hack. The problem is that we want to // stop movement while the loading screen is visible but not // restore the saved velocity if the player has changed movement // keys. if (celclient->GetMainPlayer() && psengine->GetCharControl()->GetMovementManager()->MoveStateChanged(moveState)) { newVel = celclient->GetMainPlayer()->GetVelocity(); } // move player to new pos MovePlayerTo(newPos, newyrot, sectorToLoad, newVel); if(psengine->HasLoadedMap()) loadWindow->Hide(); loading = false; loadProgressBar->Completed(); psengine->SetLoadedMap(true); // Move all entities which belong in these new sectors to them. psengine->GetCelClient()->OnMapsLoaded(); // Reset camera clip distance. psCamera* cam = psengine->GetPSCamera(); if(cam && !cam->GetDistanceCfg().adaptive) cam->UseFixedDistanceClipping(cam->GetFixedDistClip()); psengine->GetPSCamera()->ResetCameraPositioning(); // Update the lighting. psengine->GetModeHandler()->FinishLightFade(); psengine->GetModeHandler()->DoneLoading(sectorToLoad); //Update delay data forcedBackgroundImg.Empty(); forcedLoadingEndTime = 0; //restore the previous load window if any if(forcedWidgetName.Length()) ForceLoadWindowWidget(false, forcedWidgetName); } else { float timeProgress = 1.0f; if(forcedLoadingEndTime) { timeProgress = (float)(csGetTicks() - forcedLoadingStartTime)/(forcedLoadingEndTime-forcedLoadingStartTime); } float loadProgress = 1.0f; if(loadCount) { loadProgress = (float)(loadCount-psengine->GetLoader()->GetLoadingCount())/loadCount; psengine->GetLoader()->ContinueLoading(false); } loadProgressBar->SetCurrentValue(csMin(loadProgress,timeProgress)); } } }
int psLinearMovement::MoveSprite (float delta) { int ret = PS_MOVE_SUCCEED; csReversibleTransform fulltransf = mesh->GetMovable () ->GetFullTransform (); // const csMatrix3& transf = fulltransf.GetT2O (); // Calculate the total velocity (body and world) in OBJECT space. csVector3 bodyVel (fulltransf.Other2ThisRelative (velWorld) + velBody); float local_max_interval = csMin(csMin((bodyVel.y==0.0f) ? MAX_CD_INTERVAL : ABS (intervalSize.y/bodyVel.y), (bodyVel.x==0.0f) ? MAX_CD_INTERVAL : ABS (intervalSize.x/bodyVel.x) ),(bodyVel.z==0.0f) ? MAX_CD_INTERVAL : ABS (intervalSize.z/bodyVel.z) ); // Err on the side of safety (95% error margin) local_max_interval *= 0.95f; //printf("local_max_interval=%f, bodyVel is %1.2f, %1.2f, %1.2f\n",local_max_interval, bodyVel.x, bodyVel.y, bodyVel.z); //printf("velWorld is %1.2f, %1.2f, %1.2f\n", velWorld.x, velWorld.y, velWorld.z); //printf("velBody is %1.2f, %1.2f, %1.2f\n", velBody.x, velBody.y, velBody.z); // Sanity check on time interval here. Something is messing it up. -KWF //local_max_interval = csMax(local_max_interval, 0.1F); if (colldet) { while (delta > local_max_interval) { csVector3 oldpos(mesh->GetMovable ()->GetFullTransform ().GetOrigin()); // Perform brutal optimisation here for falling with no obstacles if(velWorld.y < -20.0f && mesh->GetMovable()->GetSectors()->GetCount() > 0) { csVector3 worldVel (fulltransf.This2OtherRelative (velBody) + velWorld); bool hit = false; // We check for other meshes at the start and end of the box with radius * 2 to be on the safe side { csRef<iMeshWrapperIterator> objectIter = engine->GetNearbyMeshes(mesh->GetMovable()->GetSectors()->Get(0), oldpos + boundingBox.GetCenter(), boundingBox.GetSize().Norm() * 2); if(objectIter->HasNext()) hit = true; } if(!hit) { csRef<iMeshWrapperIterator> objectIter = engine->GetNearbyMeshes(mesh->GetMovable()->GetSectors()->Get(0), oldpos + worldVel * delta + boundingBox.GetCenter(), boundingBox.GetSize().Norm() * 2); if(objectIter->HasNext()) hit = true; } if(!hit) { csOrthoTransform transform_newpos(csMatrix3(), oldpos + worldVel * delta); csBox3 fullBox(fulltransf.This2OtherRelative(boundingBox.Min()), fulltransf.This2OtherRelative(boundingBox.Max())); csBox3 newBox( transform_newpos.This2OtherRelative(boundingBox.Min()), transform_newpos.This2OtherRelative(boundingBox.Max())); fullBox.AddBoundingBox(newBox); csRef<iMeshWrapperIterator> objectIter = engine->GetNearbyMeshes(mesh->GetMovable()->GetSectors()->Get(0), fullBox); if(objectIter->HasNext()) hit = true; } if(!hit) local_max_interval = delta; } ret = MoveV (local_max_interval); csVector3 displacement(fulltransf.GetOrigin() - oldpos); displacement = fulltransf.Other2ThisRelative(displacement); // Check the invariants still hold otherwise we may jump walls if(!(fabs(displacement.x) <= intervalSize.x)) { printf("X (%g) out of bounds when performing CD > %g!\n", fabs(displacement.x), intervalSize.x); CS_ASSERT(false); } if(!(fabs(displacement.z) <= intervalSize.z)) { printf("Z (%g) out of bounds when performing CD > %g!\n", fabs(displacement.y), intervalSize.y); CS_ASSERT(false); } if(!(fabs(displacement.y) <= intervalSize.y)) { printf("Y (%g) out of bounds when performing CD > %g!\n", fabs(displacement.z), intervalSize.z); CS_ASSERT(false); } RotateV (local_max_interval); // We must update the transform after every rotation! fulltransf = mesh->GetMovable ()->GetFullTransform (); if (ret == PS_MOVE_FAIL) return ret; // The velocity may have changed by now bodyVel = fulltransf.Other2ThisRelative(velWorld) + velBody; delta -= local_max_interval; local_max_interval = csMin(csMin((bodyVel.y==0.0f) ? MAX_CD_INTERVAL : ABS (intervalSize.y/bodyVel.y), (bodyVel.x==0.0f) ? MAX_CD_INTERVAL : ABS (intervalSize.x/bodyVel.x)), (bodyVel.z==0.0f) ? MAX_CD_INTERVAL : ABS (intervalSize.z/bodyVel.z)); // Err on the side of safety (95% error margin) local_max_interval *= 0.95f; // Sanity check on time interval here. Something is messing it up. -KWF // local_max_interval = csMax(local_max_interval, 0.1F); } } if (!colldet || delta) { ret = MoveV (delta); RotateV(delta); } return ret; }
bool DistFieldGen::Run () { csRef<iImageIO> imageio = csQueryRegistry<iImageIO> (object_reg); csRef<iCommandLineParser> cmdline = csQueryRegistry<iCommandLineParser> (object_reg); const char* lowResImageFN = cmdline->GetName (0); const char* hiResImageFN = cmdline->GetName (1); if ((lowResImageFN == 0) || (hiResImageFN == 0)) { PrintHelp (); return false; } const char* outFile = cmdline->GetOption ("output"); if (outFile == 0) outFile = lowResImageFN; const char* mimeType = cmdline->GetOption ("format"); if (mimeType == 0) mimeType = "image/png"; // Read images csRef<iImage> loResImage; { csPhysicalFile file (lowResImageFN, "rb"); if (file.GetStatus() != VFS_STATUS_OK) return false; csRef<iDataBuffer> buf = file.GetAllData(); if (!buf.IsValid()) return false; loResImage = imageio->Load (buf, CS_IMGFMT_TRUECOLOR | CS_IMGFMT_ALPHA); if (!loResImage.IsValid()) return false; } csRef<iImage> hiResImage; { csPhysicalFile file (hiResImageFN, "rb"); if (file.GetStatus() != VFS_STATUS_OK) return false; csRef<iDataBuffer> buf = file.GetAllData(); if (!buf.IsValid()) return false; hiResImage = imageio->Load (buf, CS_IMGFMT_TRUECOLOR | CS_IMGFMT_ALPHA); if (!hiResImage.IsValid()) return false; } // Actual computation { ImageWrapper loImage (loResImage); ImageWrapper hiImage (hiResImage); int lheight = loImage.height; ComputationProgress progress (lheight); uint numThreads = CS::Platform::GetProcessorCount(); if (numThreads > 1) { if (numThreads > (uint)lheight) numThreads = (uint)lheight; int linesPerThread = (lheight + numThreads - 1) / numThreads; int y1 = 0; csPDelArray<DistFieldComputer> computers; csPDelArray<CS::Threading::Thread> threads; CS::Threading::Barrier barrier (numThreads+1); for (uint t = 0; t <numThreads; t++) { DistFieldComputer* computer = new DistFieldComputer (loImage, hiImage, y1, csMin (y1 + linesPerThread, lheight), progress, &barrier); computers.Push (computer); threads.Push (new CS::Threading::Thread (computer, true)); y1 += linesPerThread; } barrier.Wait (); bool status = true; for (uint t = 0; t <numThreads; t++) status &= computers[t]->runStatus; if (!status) return false; } else { DistFieldComputer computer (loImage, hiImage, 0, lheight, progress); if (!computer.Compute ()) return false; } } // Write output { csRef<iDataBuffer> outData = imageio->Save (loResImage, mimeType); if (!outData.IsValid()) return false; /* @@@ FIXME: csPhysicalFile can't open nonexisting files. * Needs to be fixed there ... */ FILE* fp = fopen (outFile, "wb"); csPhysicalFile file (fp, true); if (file.GetStatus() != VFS_STATUS_OK) return false; if (file.Write (outData->GetData(), outData->GetSize()) != outData->GetSize()) return false; } return true; }
bool Compute() { int lwidth = loResImage.width; int lheight = loResImage.height; int hwidth = hiResImage.width; int hheight = hiResImage.height; if ((lwidth > hwidth) && (lheight > hheight)) return false; float scaleXToHiRes = (float)hwidth/(float)lwidth; float scaleYToHiRes = (float)hheight/(float)lheight; /* Radius around a pixel to search for closest pixel of the opposite state * ("spread factor" in the paper) */ int searchRadius = (int)ceilf (csMax (scaleXToHiRes, scaleYToHiRes) * 0.707106781); const csRGBpixel* hiData = hiResImage.data; csRGBpixel* loData = loResImage.data; for (int y = y1; y < y2; y++) { for (int x = 0; x < lwidth; x++) { int hiResX = (int)((x + 0.5f) * scaleXToHiRes); int hiResY = (int)((y + 0.5f) * scaleYToHiRes); bool state = hiData[hiResY * hwidth + hiResX].alpha > 0.5f; float minRadius = searchRadius; int search_x1 = hiResX-searchRadius; int search_x2 = hiResX+searchRadius; int search_y1 = hiResY-searchRadius; int search_y2 = hiResY+searchRadius; for (int sy = search_y1; sy <= search_y2; sy++) { int real_y = sy; if (real_y < 0) real_y += hheight; else if (real_y >= hheight) real_y -= hheight; for (int sx = search_x1; sx <= search_x2; sx++) { int real_x = sx; if (real_x < 0) real_x += hwidth; else if (real_x >= hwidth) real_x -= hwidth; bool search_state = hiData[real_y * hwidth + real_x].alpha > 0.5f; if (search_state != state) { int dx = sx - hiResX; int dy = sy - hiResY; minRadius = csMin (minRadius, sqrtf (dx*dx + dy*dy)); } } } uint8 distNorm; if (state) distNorm = int (127.5f + 127.5f*(minRadius/(float)searchRadius)); else distNorm = int (127.5f - 127.5f*(minRadius/(float)searchRadius)); loData[y * lwidth + x].alpha = distNorm; } progress.Step (); } return true; }
void AnimationNode::SetPlaybackPosition (float time) { playbackPosition = csMin (time, GetDuration ()); }
void NetBase::CheckResendPkts() { // NOTE: Globaliterators on csHash do not retrieve keys contiguously. csHash<csRef<psNetPacketEntry> , PacketKey>::GlobalIterator it(awaitingack.GetIterator()); csRef<psNetPacketEntry> pkt; csArray<csRef<psNetPacketEntry> > pkts; csArray<Connection*> resentConnections; csTicks currenttime = csGetTicks(); unsigned int resentCount = 0; while(it.HasNext()) { pkt = it.Next(); // Check the connection packet timeout if (pkt->timestamp + csMin((csTicks)PKTMAXRTO, pkt->RTO) < currenttime) pkts.Push(pkt); } for (size_t i = 0; i < pkts.GetSize(); i++) { pkt = pkts.Get(i); #ifdef PACKETDEBUG Debug2(LOG_NET,0,"Resending nonacked HIGH packet (ID %d).\n", pkt->packet->pktid); #endif Connection* connection = GetConnByNum(pkt->clientnum); if (connection) { if (resentConnections.Find(connection) == csArrayItemNotFound) resentConnections.Push(connection); // This indicates a bug in the netcode. if (pkt->RTO == 0) { Error1("Unexpected 0 packet RTO."); abort(); } pkt->RTO *= 2; connection->resends++; } resentCount++; pkt->timestamp = currenttime; // update stamp on packet pkt->retransmitted = true; // re-add to send queue if(NetworkQueue->Add(pkt)) { //printf("pkt=%p, pkt->packet=%p\n",pkt,pkt->packet); // take out of awaiting ack pool. // This does NOT delete the pkt mem block itself. if (!awaitingack.Delete(PacketKey(pkt->clientnum, pkt->packet->pktid), pkt)) { #ifdef PACKETDEBUG Debug2(LOG_NET,0,"No packet in ack queue :%d\n", pkt->packet->pktid); #endif } else if(connection) { connection->RemoveFromWindow(pkt->packet->GetPacketSize()); } } } if(resentCount > 0) { resends[resendIndex] = resentCount; resendIndex = (resendIndex + 1) % RESENDAVGCOUNT; csTicks timeTaken = csGetTicks() - currenttime; if(resentCount > 300 || resendIndex == 1 || timeTaken > 50) { size_t peakResend = 0; float resendAvg = 0.0f; // Calculate averages data here for(int i = 0; i < RESENDAVGCOUNT; i++) { resendAvg += resends[i]; peakResend = csMax(peakResend, resends[i]); } resendAvg /= RESENDAVGCOUNT; csString status; if(timeTaken > 50) { status.Format("Resending high priority packets has taken %u time to process, for %u packets.", timeTaken, resentCount); CPrintf(CON_WARNING, "%s\n", (const char *) status.GetData()); } status.AppendFmt("Resending non-acked packet statistics: %g average resends, peak of %zu resent packets", resendAvg, peakResend); if(LogCSV::GetSingletonPtr()) LogCSV::GetSingleton().Write(CSV_STATUS, status); } } }
void csGLRender2TextureFramebuf::GrabFramebuffer (const RTAttachment<>& target, InternalFormatClass fmtClass) { csGLBasicTextureHandle* tex_mm = static_cast<csGLBasicTextureHandle*> ((iTextureHandle*)target.texture); tex_mm->Precache (); // Texture is in tha cache, update texture directly. G3D->ActivateTexture (tex_mm); GLenum internalFormat = 0; /* Texture has a keycolor - so we need to deal specially with it * to make sure the keycolor gets transparent. */ if (tex_mm->GetKeyColor ()) { // @@@ Processing sucks, but how else to handle keycolor? const size_t numPix = txt_w * txt_h; pixelScratch.SetSize (numPix * 4); glReadPixels (0, 0, txt_w, txt_h, GL_RGBA, GL_UNSIGNED_BYTE, pixelScratch.GetArray()); csRGBpixel key; tex_mm->GetKeyColor (key.red, key.green, key.blue); csBakeKeyColor::RGBA2D (pixelScratch.GetArray(), pixelScratch.GetArray(), txt_w, txt_h, key); tex_mm->Blit (0, 0, txt_w, txt_h, pixelScratch.GetArray()); } else { GLenum textarget = tex_mm->GetGLTextureTarget(); if ((textarget != GL_TEXTURE_2D) && (textarget != GL_TEXTURE_3D) && (textarget != GL_TEXTURE_RECTANGLE_ARB) && (textarget != GL_TEXTURE_CUBE_MAP)) return; bool handle_subtexture = (textarget == GL_TEXTURE_CUBE_MAP); bool handle_3d = (textarget == GL_TEXTURE_3D); /* Reportedly, some drivers crash if using CopyTexImage on a texture * size larger than the framebuffer. Use CopyTexSubImage then. */ bool needSubImage = (txt_w > viewportHelper.GetVPWidth()) || (txt_h > viewportHelper.GetVPHeight()); // Texture was not used as a render target before. // Make some necessary adjustments. if (needSubImage) { if (!tex_mm->IsWasRenderTarget()) { internalFormat = GetInternalFormat (fmtClass, tex_mm); GLenum baseFormat = GetBaseFormat (fmtClass, tex_mm); tex_mm->SetupAutoMipping(); tex_mm->SetWasRenderTarget (true); tex_mm->texFormat = iTextureHandle::RGBA8888; // Gah. Turn target texture to required storage. if (handle_subtexture) { for (int i = 0; i < 6; i++) glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, 0, internalFormat, txt_w, txt_h,0, baseFormat, GL_UNSIGNED_BYTE, 0); } else if (handle_3d) { G3D->ext->glTexImage3D (textarget, 0, internalFormat, txt_w, txt_h, txt_d, 0, baseFormat, GL_UNSIGNED_BYTE, 0); } else glTexImage2D (textarget, 0, internalFormat, txt_w, txt_h, 0, baseFormat, GL_UNSIGNED_BYTE, 0); } int orgX = viewportHelper.GetVPOfsX(); int orgY = viewportHelper.GetOriginalFramebufferHeight() - (viewportHelper.GetVPOfsY() + csMin (txt_h, viewportHelper.GetVPHeight())); if (handle_subtexture) glCopyTexSubImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + target.subtexture, 0, 0, 0, orgX, orgY, csMin (txt_w, viewportHelper.GetVPWidth()), csMin (txt_h, viewportHelper.GetVPHeight())); else if (handle_3d) G3D->ext->glCopyTexSubImage3D (textarget, 0, 0, 0, orgX, orgY, target.subtexture, csMin (txt_w, viewportHelper.GetVPWidth()), csMin (txt_h, viewportHelper.GetVPHeight())); else glCopyTexSubImage2D (textarget, 0, 0, 0, orgX, orgY, csMin (txt_w, viewportHelper.GetVPWidth()), csMin (txt_h, viewportHelper.GetVPHeight())); } else { int orgX = viewportHelper.GetVPOfsX(); int orgY = viewportHelper.GetOriginalFramebufferHeight() - (viewportHelper.GetVPOfsY() + txt_h); if (!tex_mm->IsWasRenderTarget()) { internalFormat = GetInternalFormat (fmtClass, tex_mm); tex_mm->SetupAutoMipping(); tex_mm->SetWasRenderTarget (true); tex_mm->texFormat = iTextureHandle::RGBA8888; if (handle_subtexture) glCopyTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + target.subtexture, 0, internalFormat, orgX, orgY, txt_w, txt_h, 0); else if (handle_3d) { // Gah. Turn target texture to required storage. GLenum baseFormat = GetBaseFormat (fmtClass, tex_mm); G3D->ext->glTexImage3D (textarget, 0, internalFormat, txt_w, txt_h, txt_d, 0, baseFormat, GL_UNSIGNED_BYTE, 0); G3D->ext->glCopyTexSubImage3D (textarget, 0, 0, 0, orgX, orgY, target.subtexture, txt_w, txt_h); } else glCopyTexImage2D (textarget, 0, internalFormat, orgX, orgY, txt_w, txt_h, 0); } else { glGetTexLevelParameteriv ((textarget == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB : textarget, 0, GL_TEXTURE_INTERNAL_FORMAT, (GLint*)&internalFormat); if (handle_subtexture) glCopyTexSubImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + target.subtexture, 0, 0, 0, orgX, orgY, txt_w, txt_h); else if (handle_3d) G3D->ext->glCopyTexSubImage3D (textarget, 0, 0, 0, orgX, orgY, target.subtexture, txt_w, txt_h); else glCopyTexSubImage2D (textarget, 0, 0, 0, orgX, orgY, txt_w, txt_h); } } tex_mm->RegenerateMipmaps(); } }