void CCullingSystem::initializeOccluders() { static core::array<SOccluderEntry> occluders_tmp; occluders_tmp.set_used(0); m_Occluders.sort(); for (u32 i=0; i<m_Occluders.size(); i++) { bool occluded = false; for (u32 j=i+1; j<m_Occluders.size(); j++) { if (m_Occluders[j].isOccludeByPlanes(m_Occluders[i].tbbox)) { occluded = true; break; } } if (!occluded) { occluders_tmp.push_back(m_Occluders[i]); } } m_Occluders.set_used(0); m_Occluders = occluders_tmp; }
static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3, v3f p, v3s16 dir, v3f scale, u8 light_source, core::array<FastFace> &dest) { FastFace face; // Position is at the center of the cube. v3f pos = p * BS; v3f vertex_pos[4]; v3s16 vertex_dirs[4]; getNodeVertexDirs(dir, vertex_dirs); for(u16 i=0; i<4; i++) { vertex_pos[i] = v3f( BS/2*vertex_dirs[i].X, BS/2*vertex_dirs[i].Y, BS/2*vertex_dirs[i].Z ); } for(u16 i=0; i<4; i++) { vertex_pos[i].X *= scale.X; vertex_pos[i].Y *= scale.Y; vertex_pos[i].Z *= scale.Z; vertex_pos[i] += pos; } f32 abs_scale = 1.; if (scale.X < 0.999 || scale.X > 1.001) abs_scale = scale.X; else if(scale.Y < 0.999 || scale.Y > 1.001) abs_scale = scale.Y; else if(scale.Z < 0.999 || scale.Z > 1.001) abs_scale = scale.Z; v3f normal(dir.X, dir.Y, dir.Z); u8 alpha = tile.alpha; float x0 = tile.texture.pos.X; float y0 = tile.texture.pos.Y; float w = tile.texture.size.X; float h = tile.texture.size.Y; face.vertices[0] = video::S3DVertex(vertex_pos[0], normal, MapBlock_LightColor(alpha, li0, light_source), core::vector2d<f32>(x0+w*abs_scale, y0+h)); face.vertices[1] = video::S3DVertex(vertex_pos[1], normal, MapBlock_LightColor(alpha, li1, light_source), core::vector2d<f32>(x0, y0+h)); face.vertices[2] = video::S3DVertex(vertex_pos[2], normal, MapBlock_LightColor(alpha, li2, light_source), core::vector2d<f32>(x0, y0)); face.vertices[3] = video::S3DVertex(vertex_pos[3], normal, MapBlock_LightColor(alpha, li3, light_source), core::vector2d<f32>(x0+w*abs_scale, y0)); face.tile = tile; dest.push_back(face); }
void MapSector::getBlocks(core::array<MapBlock*> &dest) { core::map<s16, MapBlock*>::Iterator bi; bi = m_blocks.getIterator(); for(; bi.atEnd() == false; bi++) { MapBlock *b = bi.getNode()->getValue(); dest.push_back(b); } }
bool CIrrDeviceWin32::activateJoysticks(core::array<SJoystickInfo> & joystickInfo) { #if defined _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ joystickInfo.clear(); ActiveJoysticks.clear(); const u32 numberOfJoysticks = ::joyGetNumDevs(); JOYINFOEX info; info.dwSize = sizeof(info); info.dwFlags = JOY_RETURNALL; JoystickInfo activeJoystick; SJoystickInfo returnInfo; joystickInfo.reallocate(numberOfJoysticks); ActiveJoysticks.reallocate(numberOfJoysticks); u32 joystick = 0; for(; joystick < numberOfJoysticks; ++joystick) { if(JOYERR_NOERROR == joyGetPosEx(joystick, &info) && JOYERR_NOERROR == joyGetDevCaps(joystick, &activeJoystick.Caps, sizeof(activeJoystick.Caps))) { activeJoystick.Index = joystick; ActiveJoysticks.push_back(activeJoystick); returnInfo.Joystick = (u8)joystick; returnInfo.Axes = activeJoystick.Caps.wNumAxes; returnInfo.Buttons = activeJoystick.Caps.wNumButtons; returnInfo.Name = activeJoystick.Caps.szPname; returnInfo.PovHat = ((activeJoystick.Caps.wCaps & JOYCAPS_HASPOV) == JOYCAPS_HASPOV) ? SJoystickInfo::POV_HAT_PRESENT : SJoystickInfo::POV_HAT_ABSENT; joystickInfo.push_back(returnInfo); } } for(joystick = 0; joystick < joystickInfo.size(); ++joystick) { char logString[256]; (void)sprintf(logString, "Found joystick %d, %d axes, %d buttons '%s'", joystick, joystickInfo[joystick].Axes, joystickInfo[joystick].Buttons, joystickInfo[joystick].Name.c_str()); os::Printer::log(logString, ELL_INFORMATION); } return true; #else return false; #endif // _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ }
// Create a tower of the specified number of boxes void createBoxTower(IPhysxManager* physxManager, scene::ISceneManager* smgr, video::IVideoDriver* driver, core::array<SPhysxAndNodePair*>& objects, f32 towerSize, f32 density, const core::vector3df& position) { const core::vector3df scale(4,4,4); const f32 spacing = -2.0f*physxManager->getSkinWidth(); core::vector3df pos = position + core::vector3df(0.0f, scale.Y/2.0f, 0.0f); while (towerSize > 0) { objects.push_back(createBox(physxManager, smgr, driver, pos, scale, density)); pos.Y += (scale.Y + spacing); towerSize--; } }
//! read indices void CIrrMeshFileLoader::readIndices(io::IXMLReader* reader, int indexCount, core::array<u16>& indices) { indices.reallocate(indexCount); core::stringc data = reader->getNodeData(); const c8* p = &data[0]; for (int i=0; i<indexCount && *p; ++i) { findNextNoneWhiteSpace(&p); indices.push_back((u16)readInt(&p)); } }
void Surface::load(BinaryFileReader* pReader) { flags = pReader->readLong(); textureName = pReader->readString(); lightMapId = pReader->readLong(); pReader->readVec2f(&uvOffset); pReader->readVec2f(&uvScale); uvRotation = pReader->readFloat(); s32 vtxCount = pReader->readLong(); s32 triCount = pReader->readLong(); s32 lineCount = pReader->readLong(); for(s32 v = 0; v < vtxCount; v++) { Vertex *vtx = new Vertex(); vtx->load(pReader); vertices.push_back(vtx); } for(s32 t = 0; t < triCount; t++) { Triangle tri; pReader->readBuffer(&tri, sizeof(tri)); triangles.push_back(tri); } for(s32 l = 0; l < lineCount; l++) { Line line; pReader->readBuffer(&line,sizeof(line)); lines.push_back(line); } }
/* Here is an example traditional set-up sequence for a DrawSpec list: std::string furnace_inv_id = "nodemetadata:0,1,2"; core::array<GUIInventoryMenu::DrawSpec> draw_spec; draw_spec.push_back(GUIInventoryMenu::DrawSpec( "list", furnace_inv_id, "fuel", v2s32(2, 3), v2s32(1, 1))); draw_spec.push_back(GUIInventoryMenu::DrawSpec( "list", furnace_inv_id, "src", v2s32(2, 1), v2s32(1, 1))); draw_spec.push_back(GUIInventoryMenu::DrawSpec( "list", furnace_inv_id, "dst", v2s32(5, 1), v2s32(2, 2))); draw_spec.push_back(GUIInventoryMenu::DrawSpec( "list", "current_player", "main", v2s32(0, 5), v2s32(8, 4))); setDrawSpec(draw_spec); Here is the string for creating the same DrawSpec list (a single line, spread to multiple lines here): GUIInventoryMenu::makeDrawSpecArrayFromString( draw_spec, "nodemetadata:0,1,2", "invsize[8,9;]" "list[current_name;fuel;2,3;1,1;]" "list[current_name;src;2,1;1,1;]" "list[current_name;dst;5,1;2,2;]" "list[current_player;main;0,5;8,4;]"); Returns inventory menu size defined by invsize[]. */ v2s16 GUIInventoryMenu::makeDrawSpecArrayFromString( core::array<GUIInventoryMenu::DrawSpec> &draw_spec, const std::string &data, const std::string ¤t_name) { v2s16 invsize(8,9); Strfnd f(data); while(f.atend() == false) { std::string type = trim(f.next("[")); //infostream<<"type="<<type<<std::endl; if(type == "list") { std::string name = f.next(";"); if(name == "current_name") name = current_name; std::string subname = f.next(";"); s32 pos_x = stoi(f.next(",")); s32 pos_y = stoi(f.next(";")); s32 geom_x = stoi(f.next(",")); s32 geom_y = stoi(f.next(";")); infostream<<"list name="<<name<<", subname="<<subname <<", pos=("<<pos_x<<","<<pos_y<<")" <<", geom=("<<geom_x<<","<<geom_y<<")" <<std::endl; draw_spec.push_back(GUIInventoryMenu::DrawSpec( type, name, subname, v2s32(pos_x,pos_y),v2s32(geom_x,geom_y))); f.next("]"); } else if(type == "invsize") { invsize.X = stoi(f.next(",")); invsize.Y = stoi(f.next(";")); infostream<<"invsize ("<<invsize.X<<","<<invsize.Y<<")"<<std::endl; f.next("]"); } else { // Ignore others std::string ts = f.next("]"); infostream<<"Unknown DrawSpec: type="<<type<<", data=\""<<ts<<"\"" <<std::endl; } } return invsize; }
void MapBlockObjectList::getObjects(v3f origin, f32 max_d, core::array<DistanceSortedObject> &dest) { for(core::map<s16, MapBlockObject*>::Iterator i = m_objects.getIterator(); i.atEnd() == false; i++) { MapBlockObject *obj = i.getNode()->getValue(); f32 d = (obj->getRelativeShowPos() - origin).getLength(); if(d > max_d) continue; DistanceSortedObject dso(obj, d); dest.push_back(dso); } }
// Create a stack of meshes, with the bottom row having the specified number of cubes void createMeshStack(IPhysxManager* physxManager, scene::ISceneManager* smgr, video::IVideoDriver* driver, core::array<SPhysxAndNodePair*>& objects, scene::IMesh* mesh, f32 stackSize, f32 density) { const core::vector3df meshSize = mesh->getBoundingBox().getExtent(); const f32 spacing = -2.0f*physxManager->getSkinWidth(); core::vector3df pos(0.0f, meshSize.Y/2.0f, 0.0f); f32 offset = -stackSize * (meshSize.X + spacing) * 0.5f; while (stackSize > 0) { for (s32 i = 0 ; i < stackSize ; ++i) { pos.X = offset + (f32)i * (meshSize.X + spacing); objects.push_back(createMeshBoundingBox(physxManager, smgr, driver, mesh, pos, core::vector3df(1,1,1), density)); } offset += meshSize.X / 2.0f; pos.Y += (meshSize.Y + spacing); stackSize--; } }
// Create a stack of boxes, with the bottom row having the specified number of boxes void createBoxStack(IPhysxManager* physxManager, scene::ISceneManager* smgr, video::IVideoDriver* driver, core::array<SPhysxAndNodePair*>& objects, f32 stackSize, f32 density, const core::vector3df& position) { const core::vector3df scale(4,4,4); const f32 spacing = -2.0f*physxManager->getSkinWidth(); core::vector3df pos = position + core::vector3df(0.0f, scale.Y/2.0f, 0.0f); f32 offset = -stackSize * (scale.X + spacing) * 0.5f; while (stackSize > 0) { for (s32 i = 0 ; i < stackSize ; ++i) { pos.X = offset + (f32)i * (scale.X + spacing); objects.push_back(createBox(physxManager, smgr, driver, pos, scale, density)); } offset += scale.X / 2.0f; pos.Y += (scale.Y + spacing); stackSize--; } }
void ClientEnvironment::getActiveObjects(v3f origin, f32 max_d, core::array<DistanceSortedActiveObject> &dest) { for(core::map<u16, ClientActiveObject*>::Iterator i = m_active_objects.getIterator(); i.atEnd()==false; i++) { ClientActiveObject* obj = i.getNode()->getValue(); f32 d = (obj->getPosition() - origin).getLength(); if(d > max_d) continue; DistanceSortedActiveObject dso(obj, d); dest.push_back(dso); } }
//! Activate any joysticks, and generate events for them. bool CIrrDeviceSDL::activateJoysticks(core::array<SJoystickInfo> & joystickInfo) { #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) joystickInfo.clear(); // we can name up to 256 different joysticks const int numJoysticks = core::min_(SDL_NumJoysticks(), 256); Joysticks.reallocate(numJoysticks); joystickInfo.reallocate(numJoysticks); int joystick = 0; for (; joystick<numJoysticks; ++joystick) { Joysticks.push_back(SDL_JoystickOpen(joystick)); SJoystickInfo info; info.Joystick = joystick; info.Axes = SDL_JoystickNumAxes(Joysticks[joystick]); info.Buttons = SDL_JoystickNumButtons(Joysticks[joystick]); info.Name = SDL_JoystickName(joystick); info.PovHat = (SDL_JoystickNumHats(Joysticks[joystick]) > 0) ? SJoystickInfo::POV_HAT_PRESENT : SJoystickInfo::POV_HAT_ABSENT; joystickInfo.push_back(info); } for(joystick = 0; joystick < (int)joystickInfo.size(); ++joystick) { char logString[256]; (void)sprintf(logString, "Found joystick %d, %d axes, %d buttons '%s'", joystick, joystickInfo[joystick].Axes, joystickInfo[joystick].Buttons, joystickInfo[joystick].Name.c_str()); os::Printer::log(logString, ELL_INFORMATION); } return true; #endif // _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ return false; }
void Mesh::load(BinaryFileReader* pReader, bool bReadVisGroups) { flags = pReader->readLong(); groupId = pReader->readLong(); props = pReader->readString(); pReader->readColorRGB(&color); pReader->readVec3f(&position); if(bReadVisGroups) visgroupId = pReader->readLong(); else visgroupId = 0; s32 count = pReader->readLong(); for(s32 i = 0; i < count; i++) { Surface* surf = new Surface(); surf->load(pReader); surfaces.push_back(surf); } }
/* This method generates all the textures */ u32 TextureSource::getTextureIdDirect(const std::string &name) { //infostream<<"getTextureIdDirect(): name=\""<<name<<"\""<<std::endl; // Empty name means texture 0 if(name == "") { infostream<<"getTextureIdDirect(): name is empty"<<std::endl; return 0; } /* Calling only allowed from main thread */ if(get_current_thread_id() != m_main_thread) { errorstream<<"TextureSource::getTextureIdDirect() " "called not from main thread"<<std::endl; return 0; } /* See if texture already exists */ { JMutexAutoLock lock(m_atlaspointer_cache_mutex); core::map<std::string, u32>::Node *n; n = m_name_to_id.find(name); if(n != NULL) { /*infostream<<"getTextureIdDirect(): \""<<name <<"\" found in cache"<<std::endl;*/ return n->getValue(); } } /*infostream<<"getTextureIdDirect(): \""<<name <<"\" NOT found in cache. Creating it."<<std::endl;*/ /* Get the base image */ char separator = '^'; /* This is set to the id of the base image. If left 0, there is no base image and a completely new image is made. */ u32 base_image_id = 0; // Find last meta separator in name s32 last_separator_position = -1; for(s32 i=name.size()-1; i>=0; i--) { if(name[i] == separator) { last_separator_position = i; break; } } /* If separator was found, construct the base name and make the base image using a recursive call */ std::string base_image_name; if(last_separator_position != -1) { // Construct base name base_image_name = name.substr(0, last_separator_position); /*infostream<<"getTextureIdDirect(): Calling itself recursively" " to get base image of \""<<name<<"\" = \"" <<base_image_name<<"\""<<std::endl;*/ base_image_id = getTextureIdDirect(base_image_name); } //infostream<<"base_image_id="<<base_image_id<<std::endl; video::IVideoDriver* driver = m_device->getVideoDriver(); assert(driver); video::ITexture *t = NULL; /* An image will be built from files and then converted into a texture. */ video::IImage *baseimg = NULL; // If a base image was found, copy it to baseimg if(base_image_id != 0) { JMutexAutoLock lock(m_atlaspointer_cache_mutex); SourceAtlasPointer ap = m_atlaspointer_cache[base_image_id]; video::IImage *image = ap.atlas_img; if(image == NULL) { infostream<<"getTextureIdDirect(): WARNING: NULL image in " <<"cache: \""<<base_image_name<<"\"" <<std::endl; } else { core::dimension2d<u32> dim = ap.intsize; baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); core::position2d<s32> pos_to(0,0); core::position2d<s32> pos_from = ap.intpos; image->copyTo( baseimg, // target v2s32(0,0), // position in target core::rect<s32>(pos_from, dim) // from ); /*infostream<<"getTextureIdDirect(): Loaded \"" <<base_image_name<<"\" from image cache" <<std::endl;*/ } } /* Parse out the last part of the name of the image and act according to it */ std::string last_part_of_name = name.substr(last_separator_position+1); //infostream<<"last_part_of_name=\""<<last_part_of_name<<"\""<<std::endl; // Generate image according to part of name if(!generate_image(last_part_of_name, baseimg, m_device, &m_sourcecache)) { errorstream<<"getTextureIdDirect(): " "failed to generate \""<<last_part_of_name<<"\"" <<std::endl; } // If no resulting image, print a warning if(baseimg == NULL) { errorstream<<"getTextureIdDirect(): baseimg is NULL (attempted to" " create texture \""<<name<<"\""<<std::endl; } if(baseimg != NULL) { // Create texture from resulting image t = driver->addTexture(name.c_str(), baseimg); } /* Add texture to caches (add NULL textures too) */ JMutexAutoLock lock(m_atlaspointer_cache_mutex); u32 id = m_atlaspointer_cache.size(); AtlasPointer ap(id); ap.atlas = t; ap.pos = v2f(0,0); ap.size = v2f(1,1); ap.tiled = 0; core::dimension2d<u32> baseimg_dim(0,0); if(baseimg) baseimg_dim = baseimg->getDimension(); SourceAtlasPointer nap(name, ap, baseimg, v2s32(0,0), baseimg_dim); m_atlaspointer_cache.push_back(nap); m_name_to_id.insert(name, id); /*infostream<<"getTextureIdDirect(): " <<"Returning id="<<id<<" for name \""<<name<<"\""<<std::endl;*/ return id; }
void CCombatNPC::writeOutXMLDescription(core::array<core::stringw>& names, core::array<core::stringw>& values) const { IAIEntity::writeOutXMLDescription(names, values); core::stringw strw; names.push_back(core::stringw(L"waypointGroupName")); values.push_back(core::stringw(WaypointGroup->getName()).c_str()); names.push_back(core::stringw(L"startWaypointID")); strw = (CurrentWaypoint ? core::stringw(CurrentWaypoint->getID()) : core::stringw(0)); values.push_back(strw); names.push_back(core::stringw(L"fovDimensions")); core::vector3df dim = (FieldOfView ? FieldOfView->getDimensions() : core::vector3df(0,0,0)); strw = core::stringw(dim.X); strw += ","; strw += dim.Y; strw += ","; strw += dim.Z; values.push_back(strw); names.push_back(core::stringw(L"range")); strw = core::stringw(Range); values.push_back(strw); names.push_back(core::stringw(L"moveSpeed")); strw = core::stringw(MoveSpeed); values.push_back(strw); names.push_back(core::stringw(L"atDestinationThreshold")); strw = core::stringw(AtDestinationThreshold); values.push_back(strw); names.push_back(core::stringw(L"fovOcclusionCheck")); strw = core::stringw(FovOcclusionCheck); values.push_back(strw); names.push_back(core::stringw(L"checkFovForEnemies")); strw = core::stringw(CheckFovForEnemies); values.push_back(strw); names.push_back(core::stringw(L"checkFovForAllies")); strw = core::stringw(CheckFovForAllies); values.push_back(strw); }
void CTreeGenerator::appendBranch( const core::matrix4& transform, SBranch* branch, f32 lengthScale, f32 radiusScale, s32 level, SMeshBuffer* buffer, core::array<STreeLeaf>& leaves ) { if ( level <= 0 ) return; // Do nothing, this branch is invisible. // Add this branch f32 length = lengthScale * getFloatFromValueRange( branch->Length, Seed++ ); f32 radius = getFloatFromValueRange( branch->Radius, Seed++ ); f32 radiusEndScale = radiusScale * getFloatFromValueRange( branch->RadiusEnd, Seed++ ); f32 radiusEnd = radius * radiusEndScale; radius = radiusScale * radius; if ( level == 1 ) radiusEnd = 0; s32 radialSegments = (level*(RadialSegments-3))/Levels + 3; if ( level > CutoffLevel ) { BuildCylinder( buffer->Vertices, buffer->Indices, buffer->BoundingBox, length, radius, radiusEnd, radialSegments, transform ); } // Add children if ( level > 1 ) { core::list<SBranchChild>::Iterator it = branch->Children.begin(); while ( it != branch->Children.end() ) { SBranchChild* child = &(*it); it++; SBranch* childBranch = getBranchWithId( child->IdRef ); if ( childBranch == 0 ) continue; if ( !isValueInRange( level, child->LevelRange ) ) continue; s32 childLevel = level + getIntFromValueRange( child->RelativeLevel, Seed++ ); // RelativeLevel is usually negative, -1 in particular. s32 numChildren = getIntFromValueRange( child->Count, Seed++ ); f32 positionRange = child->Position.Max - child->Position.Min; positionRange /= (f32)numChildren; f32 orientation = getRandomFloat( Seed++, 0, 360.0f ); for ( s32 i=0; i<numChildren; i++ ) { f32 childLengthScale = lengthScale * getFloatFromValueRange( child->LengthScale, Seed++ ); orientation += getFloatFromValueRange( child->Orientation, Seed++ ); // Clamp value between 0 and 360. This is needed for gravity to work properly if ( orientation < 0.0f ) orientation += 360.0f; else if ( orientation > 360.0f ) orientation -= 360.0f; f32 childOrientation = orientation; f32 gravity = getFloatFromValueRange( child->GravityInfluence, Seed++ ); f32 childPitch = getFloatFromValueRange( child->Pitch, Seed++ ); f32 childPosition = getFloatFromValueRange( child->Position, Seed++ ); f32 position; if ( child->Position.IsValue ) position = child->Position.Value; else position = (child->Position.Min + positionRange * i + positionRange * getRandomFloat( Seed++, 0, 1 )); f32 childRadiusScale = (radiusScale*(1.0f-position) + radiusEndScale*position) * getFloatFromValueRange( child->RadiusScale, Seed++ ); // Build transformation matrix core::matrix4 mat; mat.setRotationDegrees( core::vector3df(childPitch, childOrientation, 0.0f) ); mat[13] = length * position; mat = transform * mat; if ( gravity != 0.0f ) { // Do some extra work core::vector3df vDown = core::vector3df( 0, -1, 0 ); core::vector3df vBranch = core::vector3df( 0, 1, 0 ); mat.rotateVect(vBranch); core::vector3df vSide; if ( fabs( vBranch.Y ) >= 0.9f ) { vSide = core::vector3df( 1, 0, 0 ); mat.rotateVect(vSide); } else { vSide = vBranch.crossProduct(vDown); vSide.normalize(); } vDown = vSide.crossProduct(vBranch); vDown.normalize(); setMatrixVec( mat, 0, vSide ); setMatrixVec( mat, 2, vDown ); f32 dot = -vBranch.Y; if ( gravity < 0.0f ) dot = -dot; f32 angle = acos( dot ); angle *= gravity; core::matrix4 mat2; mat2.setRotationRadians( core::vector3df( angle,0,0 ) ); mat = mat * mat2; } // Add the branch appendBranch( mat, childBranch, childLengthScale, childRadiusScale, childLevel, buffer, leaves ); } } } // Add leaves if ( AddLeaves ) { core::list<SLeaf>::Iterator lit = branch->Leaves.begin(); while ( lit != branch->Leaves.end() ) { SLeaf* leaf = &(*lit); lit++; if ( !isValueInRange( level, leaf->LevelRange ) ) continue; s32 count = getIntFromValueRange( leaf->Count, LeafSeed++ ); for ( s32 i=0; i<count; i++ ) { f32 width = getFloatFromValueRange( leaf->Width, LeafSeed++ ); f32 height = getFloatFromValueRange( leaf->Height, LeafSeed++ ); f32 scale = getFloatFromValueRange( leaf->Scale, LeafSeed++ ); f32 position = getFloatFromValueRange( leaf->Position, LeafSeed++ ); f32 roll = getFloatFromValueRange( leaf->Roll, LeafSeed++ ); f32 anchor = getFloatFromValueRange( leaf->Anchor, LeafSeed++ ); core::matrix4 mat; mat[13] = length * position; mat = transform * mat; STreeLeaf treeLeaf; treeLeaf.Position = mat.getTranslation(); treeLeaf.Color.setRed( getIntFromValueRange( leaf->Red, LeafSeed++ ) ); treeLeaf.Color.setGreen( getIntFromValueRange( leaf->Green, LeafSeed++ ) ); treeLeaf.Color.setBlue( getIntFromValueRange( leaf->Blue, LeafSeed++ ) ); treeLeaf.Color.setAlpha( getIntFromValueRange( leaf->Alpha, LeafSeed++ ) ); treeLeaf.Size = core::dimension2df(scale*width, scale*height); treeLeaf.Roll = roll; if ( leaf->HasAxis ) { treeLeaf.HasAxis = true; treeLeaf.Axis = leaf->Axis; treeLeaf.Position += leaf->Axis * height * scale * anchor / 2.0f; } else { treeLeaf.HasAxis = false; } leaves.push_back( treeLeaf ); } } } }
void BuildCylinder( core::array<video::S3DVertex>& vertexArray, core::array<u16>& indexArray, core::aabbox3d<f32>& boundingBox, f32 height, f32 startRadius, f32 endRadius, s32 radialSegments, const core::matrix4& transform, f32 startTCoordY = 0.0f, f32 endTCoordY = 1.0f, video::SColor startColor = video::SColor(255,255,255,255), video::SColor endColor = video::SColor(255,255,255,255) ) { u16 vertexIndex = vertexArray.size(); s32 radialVertices = radialSegments + 1; // We want one additional vertex to make the texture wraps correctly // Place bottom cap for ( s32 i=0; i<radialVertices; i++ ) { f32 angle = 2.0f * core::PI * i / (f32)( radialSegments ); core::vector3df dir; dir.X = cos(angle); dir.Z = sin(angle); core::vector3df pos; core::vector3df normal = dir; pos = dir * startRadius; // Place bottom vertex transform.transformVect( pos ); transform.rotateVect( normal ); core::vector2df tcoord; tcoord.X = (f32)( i ) / (f32)( radialSegments ); tcoord.Y = startTCoordY; vertexArray.push_back( video::S3DVertex( pos, normal, startColor, tcoord ) ); boundingBox.addInternalPoint( pos ); } // Place top cap and indices for ( s32 i=0; i<radialVertices; i++ ) { f32 angle = 2.0f * core::PI * i / (f32)( radialSegments ); core::vector3df dir; dir.X = cos(angle); dir.Z = sin(angle); core::vector3df normal = dir; core::vector3df pos = dir * endRadius; pos.Y = height; transform.transformVect( pos ); transform.rotateVect( normal ); core::vector2df tcoord; tcoord.X = (f32)( i ) / (f32)( radialSegments ); tcoord.Y = endTCoordY; vertexArray.push_back( video::S3DVertex( pos, normal, endColor, tcoord ) ); boundingBox.addInternalPoint(pos); // Add indices if ( i != radialVertices-1 ) { s32 i2 = (i+1)%radialVertices; // Place the indices indexArray.push_back ( vertexIndex + i ); indexArray.push_back ( vertexIndex + radialVertices + i ); indexArray.push_back ( vertexIndex + i2 ); indexArray.push_back ( vertexIndex + radialVertices + i ); indexArray.push_back ( vertexIndex + radialVertices + i2 ); indexArray.push_back ( vertexIndex + i2 ); } } }
void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p, v3s16 dir, v3f scale, v3f posRelative_f, core::array<FastFace> &dest) { FastFace face; // Position is at the center of the cube. v3f pos = p * BS; posRelative_f *= BS; v3f vertex_pos[4]; v3s16 vertex_dirs[4]; getNodeVertexDirs(dir, vertex_dirs); for(u16 i=0; i<4; i++) { vertex_pos[i] = v3f( BS/2*vertex_dirs[i].X, BS/2*vertex_dirs[i].Y, BS/2*vertex_dirs[i].Z ); } for(u16 i=0; i<4; i++) { vertex_pos[i].X *= scale.X; vertex_pos[i].Y *= scale.Y; vertex_pos[i].Z *= scale.Z; vertex_pos[i] += pos + posRelative_f; } f32 abs_scale = 1.; if (scale.X < 0.999 || scale.X > 1.001) abs_scale = scale.X; else if(scale.Y < 0.999 || scale.Y > 1.001) abs_scale = scale.Y; else if(scale.Z < 0.999 || scale.Z > 1.001) abs_scale = scale.Z; v3f zerovector = v3f(0,0,0); u8 alpha = tile.alpha; /*u8 alpha = 255; if(tile.id == TILE_WATER) alpha = WATER_ALPHA;*/ float x0 = tile.texture.pos.X; float y0 = tile.texture.pos.Y; float w = tile.texture.size.X; float h = tile.texture.size.Y; /*video::SColor c = lightColor(alpha, li); face.vertices[0] = video::S3DVertex(vertex_pos[0], v3f(0,1,0), c, core::vector2d<f32>(x0+w*abs_scale, y0+h)); face.vertices[1] = video::S3DVertex(vertex_pos[1], v3f(0,1,0), c, core::vector2d<f32>(x0, y0+h)); face.vertices[2] = video::S3DVertex(vertex_pos[2], v3f(0,1,0), c, core::vector2d<f32>(x0, y0)); face.vertices[3] = video::S3DVertex(vertex_pos[3], v3f(0,1,0), c, core::vector2d<f32>(x0+w*abs_scale, y0));*/ face.vertices[0] = video::S3DVertex(vertex_pos[0], v3f(0,1,0), lightColor(alpha, li0), core::vector2d<f32>(x0+w*abs_scale, y0+h)); face.vertices[1] = video::S3DVertex(vertex_pos[1], v3f(0,1,0), lightColor(alpha, li1), core::vector2d<f32>(x0, y0+h)); face.vertices[2] = video::S3DVertex(vertex_pos[2], v3f(0,1,0), lightColor(alpha, li2), core::vector2d<f32>(x0, y0)); face.vertices[3] = video::S3DVertex(vertex_pos[3], v3f(0,1,0), lightColor(alpha, li3), core::vector2d<f32>(x0+w*abs_scale, y0)); face.tile = tile; //DEBUG //f->tile = TILE_STONE; dest.push_back(face); }
void CSMFile::load(BinaryFileReader* pReader) { clear(); header.load(pReader); //groups { const s32 count = pReader->readLong(); #ifdef _IRR_DEBUG_CSM_LOADER_ os::Printer::log("CSM Version", core::stringc(header.getVersion()).c_str()); os::Printer::log("Loading groups. Count", core::stringc(count)); #endif groups.reallocate(count); for (s32 i = 0; i < count; i++) { Group* grp = new Group(); grp->load(pReader); groups.push_back(grp); } } const bool bHasVGroups = (header.getVersion() == Header::VERSION_4_1); if (bHasVGroups) { //visgroups const s32 count = pReader->readLong(); #ifdef _IRR_DEBUG_CSM_LOADER_ os::Printer::log("Loading visgroups. Count", core::stringc(count)); #endif visgroups.reallocate(count); for (s32 i = 0; i < count; i++) { VisGroup* grp = new VisGroup(); grp->load(pReader); visgroups.push_back(grp); } } //lightmaps { const s32 count = pReader->readLong(); #ifdef _IRR_DEBUG_CSM_LOADER_ os::Printer::log("Loading lightmaps. Count", core::stringc(count)); #endif lightmaps.reallocate(count); for(s32 i = 0; i < count; i++) { LightMap* lm = new LightMap(); lm->load(pReader); lightmaps.push_back(lm); } } //meshes { const s32 count = pReader->readLong(); #ifdef _IRR_DEBUG_CSM_LOADER_ os::Printer::log("Loading meshes. Count", core::stringc(count)); #endif meshes.reallocate(count); for(s32 i = 0; i < count; i++) { Mesh* mesh = new Mesh(); mesh->load(pReader,bHasVGroups); meshes.push_back(mesh); } } //entities { const s32 count = pReader->readLong(); #ifdef _IRR_DEBUG_CSM_LOADER_ os::Printer::log("Loading entitites. Count", core::stringc(count)); #endif entities.reallocate(count); for(s32 i = 0; i < count; i++) { Entity* ent = new Entity(); ent->load(pReader); entities.push_back(ent); } } //camera data #ifdef _IRR_DEBUG_CSM_LOADER_ os::Printer::log("Loading camera data."); #endif cameraData.load(pReader); }
void CSMFile::load(BinaryFileReader* pReader) { clear(); header.load(pReader); //groups { s32 count = pReader->readLong(); for (s32 i = 0; i < count; i++) { Group* grp = new Group(); grp->load(pReader); groups.push_back(grp); } } bool bHasVGroups = (header.getVersion() == Header::VERSION_4_1); if (bHasVGroups) { //visgroups s32 count = pReader->readLong(); for (s32 i = 0; i < count; i++) { VisGroup* grp = new VisGroup(); grp->load(pReader); visgroups.push_back(grp); } } //lightmaps { s32 count = pReader->readLong(); for(s32 i = 0; i < count; i++) { LightMap* grp = new LightMap(); grp->load(pReader); lightmaps.push_back(grp); } } //meshes { s32 count = pReader->readLong(); for(s32 i = 0; i < count; i++) { Mesh* grp = new Mesh(); grp->load(pReader,bHasVGroups); meshes.push_back(grp); } } //entities { s32 count = pReader->readLong(); for(s32 i = 0; i < count; i++) { Entity* grp = new Entity(); grp->load(pReader); entities.push_back(grp); } } //camera data cameraData.load(pReader); }
u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols, core::array<ChatFormattedLine>& destination) const { u32 num_added = 0; core::array<ChatFormattedFragment> next_frags; ChatFormattedLine next_line; ChatFormattedFragment temp_frag; u32 out_column = 0; u32 in_pos = 0; u32 hanging_indentation = 0; // Format the sender name and produce fragments if (!line.name.empty()) { temp_frag.text = L"<"; temp_frag.column = 0; //temp_frag.bold = 0; next_frags.push_back(temp_frag); temp_frag.text = line.name; temp_frag.column = 0; //temp_frag.bold = 1; next_frags.push_back(temp_frag); temp_frag.text = L"> "; temp_frag.column = 0; //temp_frag.bold = 0; next_frags.push_back(temp_frag); } // Choose an indentation level if (line.name.empty()) { // Server messages hanging_indentation = 0; } else if (line.name.size() + 3 <= cols/2) { // Names shorter than about half the console width hanging_indentation = line.name.size() + 3; } else { // Very long names hanging_indentation = 2; } next_line.first = true; bool text_processing = false; // Produce fragments and layout them into lines while (!next_frags.empty() || in_pos < line.text.size()) { // Layout fragments into lines while (!next_frags.empty()) { ChatFormattedFragment& frag = next_frags[0]; if (frag.text.size() <= cols - out_column) { // Fragment fits into current line frag.column = out_column; next_line.fragments.push_back(frag); out_column += frag.text.size(); next_frags.erase(0, 1); } else { // Fragment does not fit into current line // So split it up temp_frag.text = frag.text.substr(0, cols - out_column); temp_frag.column = out_column; //temp_frag.bold = frag.bold; next_line.fragments.push_back(temp_frag); frag.text = frag.text.substr(cols - out_column); out_column = cols; } if (out_column == cols || text_processing) { // End the current line destination.push_back(next_line); num_added++; next_line.fragments.clear(); next_line.first = false; out_column = text_processing ? hanging_indentation : 0; } } // Produce fragment if (in_pos < line.text.size()) { u32 remaining_in_input = line.text.size() - in_pos; u32 remaining_in_output = cols - out_column; // Determine a fragment length <= the minimum of // remaining_in_{in,out}put. Try to end the fragment // on a word boundary. u32 frag_length = 1, space_pos = 0; while (frag_length < remaining_in_input && frag_length < remaining_in_output) { if (isspace(line.text[in_pos + frag_length])) space_pos = frag_length; ++frag_length; } if (space_pos != 0 && frag_length < remaining_in_input) frag_length = space_pos + 1; temp_frag.text = line.text.substr(in_pos, frag_length); temp_frag.column = 0; //temp_frag.bold = 0; next_frags.push_back(temp_frag); in_pos += frag_length; text_processing = true; } } // End the last line if (num_added == 0 || !next_line.fragments.empty()) { destination.push_back(next_line); num_added++; } return num_added; }
void TextureSource::buildMainAtlas(class IGameDef *gamedef) { assert(gamedef->tsrc() == this); INodeDefManager *ndef = gamedef->ndef(); infostream<<"TextureSource::buildMainAtlas()"<<std::endl; //return; // Disable (for testing) video::IVideoDriver* driver = m_device->getVideoDriver(); assert(driver); JMutexAutoLock lock(m_atlaspointer_cache_mutex); // Create an image of the right size core::dimension2d<u32> atlas_dim(1024,1024); video::IImage *atlas_img = driver->createImage(video::ECF_A8R8G8B8, atlas_dim); //assert(atlas_img); if(atlas_img == NULL) { errorstream<<"TextureSource::buildMainAtlas(): Failed to create atlas " "image; not building texture atlas."<<std::endl; return; } /* Grab list of stuff to include in the texture atlas from the main content features */ core::map<std::string, bool> sourcelist; for(u16 j=0; j<MAX_CONTENT+1; j++) { if(j == CONTENT_IGNORE || j == CONTENT_AIR) continue; const ContentFeatures &f = ndef->get(j); for(u32 i=0; i<6; i++) { std::string name = f.tname_tiles[i]; sourcelist[name] = true; } } infostream<<"Creating texture atlas out of textures: "; for(core::map<std::string, bool>::Iterator i = sourcelist.getIterator(); i.atEnd() == false; i++) { std::string name = i.getNode()->getKey(); infostream<<"\""<<name<<"\" "; } infostream<<std::endl; // Padding to disallow texture bleeding s32 padding = 16; s32 column_width = 256; s32 column_padding = 16; /* First pass: generate almost everything */ core::position2d<s32> pos_in_atlas(0,0); pos_in_atlas.Y = padding; for(core::map<std::string, bool>::Iterator i = sourcelist.getIterator(); i.atEnd() == false; i++) { std::string name = i.getNode()->getKey(); // Generate image by name video::IImage *img2 = generate_image_from_scratch(name, m_device, &m_sourcecache); if(img2 == NULL) { errorstream<<"TextureSource::buildMainAtlas(): " <<"Couldn't generate image \""<<name<<"\""<<std::endl; continue; } core::dimension2d<u32> dim = img2->getDimension(); // Don't add to atlas if image is large core::dimension2d<u32> max_size_in_atlas(32,32); if(dim.Width > max_size_in_atlas.Width || dim.Height > max_size_in_atlas.Height) { infostream<<"TextureSource::buildMainAtlas(): Not adding " <<"\""<<name<<"\" because image is large"<<std::endl; continue; } // Wrap columns and stop making atlas if atlas is full if(pos_in_atlas.Y + dim.Height > atlas_dim.Height) { if(pos_in_atlas.X > (s32)atlas_dim.Width - 256 - padding){ errorstream<<"TextureSource::buildMainAtlas(): " <<"Atlas is full, not adding more textures." <<std::endl; break; } pos_in_atlas.Y = padding; pos_in_atlas.X += column_width + column_padding; } /*infostream<<"TextureSource::buildMainAtlas(): Adding \""<<name <<"\" to texture atlas"<<std::endl;*/ // Tile it a few times in the X direction u16 xwise_tiling = column_width / dim.Width; if(xwise_tiling > 16) // Limit to 16 (more gives no benefit) xwise_tiling = 16; for(u32 j=0; j<xwise_tiling; j++) { // Copy the copy to the atlas /*img2->copyToWithAlpha(atlas_img, pos_in_atlas + v2s32(j*dim.Width,0), core::rect<s32>(v2s32(0,0), dim), video::SColor(255,255,255,255), NULL);*/ img2->copyTo(atlas_img, pos_in_atlas + v2s32(j*dim.Width,0), core::rect<s32>(v2s32(0,0), dim), NULL); } // Copy the borders a few times to disallow texture bleeding for(u32 side=0; side<2; side++) // top and bottom for(s32 y0=0; y0<padding; y0++) for(s32 x0=0; x0<(s32)xwise_tiling*(s32)dim.Width; x0++) { s32 dst_y; s32 src_y; if(side==0) { dst_y = y0 + pos_in_atlas.Y + dim.Height; src_y = pos_in_atlas.Y + dim.Height - 1; } else { dst_y = -y0 + pos_in_atlas.Y-1; src_y = pos_in_atlas.Y; } s32 x = x0 + pos_in_atlas.X; video::SColor c = atlas_img->getPixel(x, src_y); atlas_img->setPixel(x,dst_y,c); } img2->drop(); /* Add texture to caches */ bool reuse_old_id = false; u32 id = m_atlaspointer_cache.size(); // Check old id without fetching a texture core::map<std::string, u32>::Node *n; n = m_name_to_id.find(name); // If it exists, we will replace the old definition if(n){ id = n->getValue(); reuse_old_id = true; /*infostream<<"TextureSource::buildMainAtlas(): " <<"Replacing old AtlasPointer"<<std::endl;*/ } // Create AtlasPointer AtlasPointer ap(id); ap.atlas = NULL; // Set on the second pass ap.pos = v2f((float)pos_in_atlas.X/(float)atlas_dim.Width, (float)pos_in_atlas.Y/(float)atlas_dim.Height); ap.size = v2f((float)dim.Width/(float)atlas_dim.Width, (float)dim.Width/(float)atlas_dim.Height); ap.tiled = xwise_tiling; // Create SourceAtlasPointer and add to containers SourceAtlasPointer nap(name, ap, atlas_img, pos_in_atlas, dim); if(reuse_old_id) m_atlaspointer_cache[id] = nap; else m_atlaspointer_cache.push_back(nap); m_name_to_id[name] = id; // Increment position pos_in_atlas.Y += dim.Height + padding * 2; } /* Make texture */ video::ITexture *t = driver->addTexture("__main_atlas__", atlas_img); assert(t); /* Second pass: set texture pointer in generated AtlasPointers */ for(core::map<std::string, bool>::Iterator i = sourcelist.getIterator(); i.atEnd() == false; i++) { std::string name = i.getNode()->getKey(); if(m_name_to_id.find(name) == NULL) continue; u32 id = m_name_to_id[name]; //infostream<<"id of name "<<name<<" is "<<id<<std::endl; m_atlaspointer_cache[id].a.atlas = t; } /* Write image to file so that it can be inspected */ /*std::string atlaspath = porting::path_user + DIR_DELIM + "generated_texture_atlas.png"; infostream<<"Removing and writing texture atlas for inspection to " <<atlaspath<<std::endl; fs::RecursiveDelete(atlaspath); driver->writeImageToFile(atlas_img, atlaspath.c_str());*/ }