NzVertexMapper::NzVertexMapper(NzSubMesh* subMesh, nzBufferAccess access) { NzErrorFlags flags(nzErrorFlag_ThrowException, true); NzVertexBuffer* buffer = nullptr; switch (subMesh->GetAnimationType()) { case nzAnimationType_Skeletal: { NzSkeletalMesh* skeletalMesh = static_cast<NzSkeletalMesh*>(subMesh); buffer = skeletalMesh->GetVertexBuffer(); break; } case nzAnimationType_Static: { NzStaticMesh* staticMesh = static_cast<NzStaticMesh*>(subMesh); buffer = staticMesh->GetVertexBuffer(); break; } } if (!buffer) { NazaraInternalError("Animation type not handled (0x" + NzString::Number(subMesh->GetAnimationType(), 16) + ')'); } m_mapper.Map(buffer, access); }
const NzLight* NzLightManager::GetLight(unsigned int index) const { #if NAZARA_GRAPHICS_SAFE if (index >= m_lightCount) { NazaraError("Light index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_lightCount) + ')'); return nullptr; } #endif for (unsigned int i = 0; i < m_lights.size(); ++i) { unsigned int lightCount = m_lights[i].second; if (index > lightCount) index -= lightCount; else { const NzLight** lights = m_lights[i].first; return lights[i]; } } #if NAZARA_GRAPHICS_SAFE NazaraInternalError("Light not found"); #else NazaraError("Light not found"); #endif return nullptr; }
UInt8* ConvertPixels(const UInt8* start, const UInt8* end, UInt8* dst) { NazaraUnused(start); NazaraUnused(dst); NazaraUnused(end); NazaraInternalError("Conversion from " + PixelFormat::ToString(from) + " to " + PixelFormat::ToString(to) + " is not supported"); return nullptr; }
void NzStaticMesh::OnResourceReleased(const NzResource* resource, int index) { NazaraUnused(index); if (resource == m_indexBuffer) m_indexBuffer = nullptr; else if (resource == m_vertexBuffer) m_vertexBuffer = nullptr; else NazaraInternalError("Not listening to " + NzString::Pointer(resource)); }
unsigned int SoundBuffer::GetOpenALBuffer() const { #ifdef NAZARA_DEBUG if (!m_impl) { NazaraInternalError("Sound buffer not created"); return AL_NONE; } #endif return m_impl->buffer; }
void TextSprite::OnAtlasInvalidated(const AbstractAtlas* atlas) { #ifdef NAZARA_DEBUG if (m_atlases.find(atlas) == m_atlases.end()) { NazaraInternalError("Not listening to " + String::Pointer(atlas)); return; } #endif NazaraWarning("TextSprite " + String::Pointer(this) + " has been cleared because atlas " + String::Pointer(atlas) + " has been invalidated (cleared or released)"); Clear(); }
/*! * \brief Gets a parameter as a string * \return true if the parameter could be represented as a string * * \param name Name of the parameter * \param value Pointer to a pointer to hold the retrieved value * * \remark value must be a valid pointer * \remark In case of failure, the variable pointed by value keep its value * \remark If the parameter is not a string, a conversion will be performed, all types are compatibles: Boolean: Conversion obeys the rules of String::Boolean Color: Conversion obeys the rules of Color::ToString Double: Conversion obeys the rules of String::Number Integer: Conversion obeys the rules of String::Number None: An empty string is returned Pointer: Conversion obeys the rules of String::Pointer Userdata: Conversion obeys the rules of String::Pointer */ bool ParameterList::GetStringParameter(const String& name, String* value) const { NazaraAssert(value, "Invalid pointer"); ErrorFlags flags(ErrorFlag_Silent | ErrorFlag_ThrowExceptionDisabled); auto it = m_parameters.find(name); if (it == m_parameters.end()) { NazaraError("Parameter \"" + name + "\" is not present"); return false; } switch (it->second.type) { case ParameterType_Boolean: *value = String::Boolean(it->second.value.boolVal); return true; case ParameterType_Color: *value = it->second.value.colorVal.ToString(); return true; case ParameterType_Double: *value = String::Number(it->second.value.doubleVal); return true; case ParameterType_Integer: *value = String::Number(it->second.value.intVal); return true; case ParameterType_String: *value = it->second.value.stringVal; return true; case ParameterType_Pointer: *value = String::Pointer(it->second.value.ptrVal); return true; case ParameterType_Userdata: *value = String::Pointer(it->second.value.userdataVal->ptr); return true; case ParameterType_None: *value = String(); return true; } NazaraInternalError("Parameter value is not valid"); return false; }
bool TcpClient::WaitForConnected(UInt64 msTimeout) { switch (m_state) { case SocketState_Bound: case SocketState_Resolving: break; case SocketState_Connected: return true; case SocketState_Connecting: { NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Invalid handle"); CallOnExit restoreBlocking; if (m_isBlockingEnabled) { SocketImpl::SetBlocking(m_handle, false); restoreBlocking.Reset([this] () { SocketImpl::SetBlocking(m_handle, true); }); } SocketState newState = SocketImpl::Connect(m_handle, m_peerAddress, msTimeout, &m_lastError); NazaraAssert(newState != SocketState_Connecting, "Invalid internal return"); //< Connect cannot return Connecting is a timeout was specified // Prevent valid peer address in non-connected state if (newState == SocketState_NotConnected) m_peerAddress = IpAddress::Invalid; UpdateState(newState); return newState == SocketState_Connected; } case SocketState_NotConnected: return false; } NazaraInternalError("Unhandled socket state (0x" + String::Number(m_state, 16) + ')'); return false; }
void TextSprite::OnAtlasLayerChange(const AbstractAtlas* atlas, AbstractImage* oldLayer, AbstractImage* newLayer) { NazaraUnused(atlas); #ifdef NAZARA_DEBUG if (m_atlases.find(atlas) == m_atlases.end()) { NazaraInternalError("Not listening to " + String::Pointer(atlas)); return; } #endif // The texture of an atlas have just been recreated (size change) // we have to adjust the coordinates of the texture and the rendering texture Texture* oldTexture = static_cast<Texture*>(oldLayer); Texture* newTexture = static_cast<Texture*>(newLayer); // It is possible that we don't use the texture (the atlas warning us for each of its layers) auto it = m_renderInfos.find(oldTexture); if (it != m_renderInfos.end()) { // We indeed use this texture, we have to update its coordinates RenderIndices indices = std::move(it->second); Vector2ui oldSize(oldTexture->GetSize()); Vector2ui newSize(newTexture->GetSize()); Vector2f scale = Vector2f(oldSize) / Vector2f(newSize); // ratio of the old one to the new one // Now we will iterate through each coordinates of the concerned texture to multiply them by the ratio SparsePtr<Vector2f> texCoordPtr(&m_localVertices[indices.first].uv, sizeof(VertexStruct_XYZ_Color_UV)); for (unsigned int i = 0; i < indices.count; ++i) { for (unsigned int j = 0; j < 4; ++j) m_localVertices[i*4 + j].uv *= scale; } // We get rid off the old texture and we set the new one at the place (same for indices) m_renderInfos.erase(it); m_renderInfos.insert(std::make_pair(newTexture, std::move(indices))); } }
bool IpAddress::IsLoopback() const { if (!m_isValid) return false; NazaraAssert(m_protocol <= NetProtocol_Max, "Protocol has value out of enum"); switch (m_protocol) { case NetProtocol_Any: case NetProtocol_Unknown: break; case NetProtocol_IPv4: return m_ipv4[0] == 127; case NetProtocol_IPv6: return m_ipv6 == LoopbackIpV6.m_ipv6; // Only compare the ip value } NazaraInternalError("Invalid protocol for IpAddress (0x" + String::Number(m_protocol) + ')'); return false; }
SoundStatus SoundEmitter::GetInternalStatus() const { ALint state; alGetSourcei(m_source, AL_SOURCE_STATE, &state); switch (state) { case AL_INITIAL: case AL_STOPPED: return SoundStatus_Stopped; case AL_PAUSED: return SoundStatus_Paused; case AL_PLAYING: return SoundStatus_Playing; default: NazaraInternalError("Source state unrecognized"); } return SoundStatus_Stopped; }
std::unique_ptr<AbstractHash> AbstractHash::Get(HashType type) { NazaraAssert(type <= HashType_Max, "Hash type value out of enum"); switch (type) { case HashType_Fletcher16: return std::unique_ptr<AbstractHash>(new HashFletcher16); case HashType_CRC32: return std::unique_ptr<AbstractHash>(new HashCRC32); case HashType_MD5: return std::unique_ptr<AbstractHash>(new HashMD5); case HashType_SHA1: return std::unique_ptr<AbstractHash>(new HashSHA1); case HashType_SHA224: return std::unique_ptr<AbstractHash>(new HashSHA224); case HashType_SHA256: return std::unique_ptr<AbstractHash>(new HashSHA256); case HashType_SHA384: return std::unique_ptr<AbstractHash>(new HashSHA384); case HashType_SHA512: return std::unique_ptr<AbstractHash>(new HashSHA512); case HashType_Whirlpool: return std::unique_ptr<AbstractHash>(new HashWhirlpool); } NazaraInternalError("Hash type not handled (0x" + String::Number(type, 16) + ')'); return std::unique_ptr<AbstractHash>(); }
bool GuillotineImageAtlas::Insert(const Image& image, Rectui* rect, bool* flipped, unsigned int* layerIndex) { if (m_layers.empty()) // On créé une première couche s'il n'y en a pas m_layers.resize(1); // Cette fonction ne fait qu'insérer un rectangle de façon virtuelle, l'insertion des images se fait après for (unsigned int i = 0; i < m_layers.size(); ++i) { Layer& layer = m_layers[i]; // Une fois qu'un certain nombre de rectangles ont étés libérés d'une couche, on fusionne les rectangles libres if (layer.freedRectangles > 10) // Valeur totalement arbitraire { while (layer.binPack.MergeFreeRectangles()); // Tant qu'une fusion est possible layer.freedRectangles = 0; // Et on repart de zéro } if (layer.binPack.Insert(rect, flipped, 1, false, m_rectChoiceHeuristic, m_rectSplitHeuristic)) { // Insertion réussie dans l'une des couches, on place le glyphe en file d'attente layer.queuedGlyphs.resize(layer.queuedGlyphs.size()+1); QueuedGlyph& glyph = layer.queuedGlyphs.back(); glyph.flipped = *flipped; glyph.image = image; // Merci le Copy-On-Write glyph.rect = *rect; *layerIndex = i; return true; } else if (i == m_layers.size() - 1) // Dernière itération ? { // Dernière couche, et le glyphe ne rentre pas, peut-on agrandir la taille de l'image ? Vector2ui newSize = layer.binPack.GetSize()*2; if (newSize == Vector2ui::Zero()) newSize.Set(s_atlasStartSize); if (ResizeLayer(layer, newSize)) { // Oui on peut ! layer.binPack.Expand(newSize); // On ajuste l'atlas virtuel // Et on relance la boucle sur la nouvelle dernière couche i--; } else { // On ne peut plus agrandir la dernière couche, il est temps d'en créer une nouvelle newSize.Set(s_atlasStartSize); Layer newLayer; if (!ResizeLayer(newLayer, newSize)) { // Impossible d'allouer une nouvelle couche, nous manquons probablement de mémoire (ou le glyphe est trop grand) NazaraError("Failed to allocate new layer, we are probably out of memory"); return false; } newLayer.binPack.Reset(newSize); m_layers.emplace_back(std::move(newLayer)); // Insertion du layer // On laisse la boucle insérer toute seule le rectangle à la prochaine itération } } } NazaraInternalError("Unknown error"); // Normalement on ne peut pas arriver ici return false; }
void RenderSystem::UpdatePointSpotShadowMaps() { if (!m_shadowRT.IsValid()) m_shadowRT.Create(); Nz::SceneData dummySceneData; dummySceneData.ambientColor = Nz::Color(0, 0, 0); dummySceneData.background = nullptr; dummySceneData.viewer = nullptr; //< Depth technique doesn't require any viewer for (const Ndk::EntityHandle& light : m_pointSpotLights) { LightComponent& lightComponent = light->GetComponent<LightComponent>(); NodeComponent& lightNode = light->GetComponent<NodeComponent>(); if (!lightComponent.IsShadowCastingEnabled()) continue; Nz::Vector2ui shadowMapSize(lightComponent.GetShadowMap()->GetSize()); switch (lightComponent.GetLightType()) { case Nz::LightType_Directional: NazaraInternalError("Directional lights included in point/spot light list"); break; case Nz::LightType_Point: { static Nz::Quaternionf rotations[6] = { Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), Nz::Vector3f::UnitX()), // CubemapFace_PositiveX Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), -Nz::Vector3f::UnitX()), // CubemapFace_NegativeX Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), -Nz::Vector3f::UnitY()), // CubemapFace_PositiveY Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), Nz::Vector3f::UnitY()), // CubemapFace_NegativeY Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), -Nz::Vector3f::UnitZ()), // CubemapFace_PositiveZ Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), Nz::Vector3f::UnitZ()) // CubemapFace_NegativeZ }; for (unsigned int face = 0; face < 6; ++face) { m_shadowRT.AttachTexture(Nz::AttachmentPoint_Depth, 0, lightComponent.GetShadowMap(), face); Nz::Renderer::SetTarget(&m_shadowRT); Nz::Renderer::SetViewport(Nz::Recti(0, 0, shadowMapSize.x, shadowMapSize.y)); ///TODO: Cache the matrices in the light? Nz::Renderer::SetMatrix(Nz::MatrixType_Projection, Nz::Matrix4f::Perspective(Nz::FromDegrees(90.f), 1.f, 0.1f, lightComponent.GetRadius())); Nz::Renderer::SetMatrix(Nz::MatrixType_View, Nz::Matrix4f::ViewMatrix(lightNode.GetPosition(), rotations[face])); Nz::AbstractRenderQueue* renderQueue = m_shadowTechnique.GetRenderQueue(); renderQueue->Clear(); ///TODO: Culling for (const Ndk::EntityHandle& drawable : m_drawables) { GraphicsComponent& graphicsComponent = drawable->GetComponent<GraphicsComponent>(); graphicsComponent.AddToRenderQueue(renderQueue); } m_shadowTechnique.Clear(dummySceneData); m_shadowTechnique.Draw(dummySceneData); } break; } case Nz::LightType_Spot: { m_shadowRT.AttachTexture(Nz::AttachmentPoint_Depth, 0, lightComponent.GetShadowMap()); Nz::Renderer::SetTarget(&m_shadowRT); Nz::Renderer::SetViewport(Nz::Recti(0, 0, shadowMapSize.x, shadowMapSize.y)); ///TODO: Cache the matrices in the light? Nz::Renderer::SetMatrix(Nz::MatrixType_Projection, Nz::Matrix4f::Perspective(lightComponent.GetOuterAngle()*2.f, 1.f, 0.1f, lightComponent.GetRadius())); Nz::Renderer::SetMatrix(Nz::MatrixType_View, Nz::Matrix4f::ViewMatrix(lightNode.GetPosition(), lightNode.GetRotation())); Nz::AbstractRenderQueue* renderQueue = m_shadowTechnique.GetRenderQueue(); renderQueue->Clear(); ///TODO: Culling for (const Ndk::EntityHandle& drawable : m_drawables) { GraphicsComponent& graphicsComponent = drawable->GetComponent<GraphicsComponent>(); graphicsComponent.AddToRenderQueue(renderQueue); } m_shadowTechnique.Clear(dummySceneData); m_shadowTechnique.Draw(dummySceneData); break; } } } }
bool NzRenderTexture::IsComplete() const { #if NAZARA_RENDERER_SAFE if (!m_impl) { NazaraError("Render texture not created"); return false; } #endif if (!m_impl->checked) { if (!Lock()) { NazaraError("Failed to lock render texture"); return false; } GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); Unlock(); m_impl->complete = false; switch (status) { case GL_FRAMEBUFFER_COMPLETE: m_impl->complete = true; break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: NazaraError("Incomplete attachment"); break; case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: NazaraInternalError("Incomplete draw buffer"); break; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: NazaraInternalError("Incomplete read buffer"); break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: NazaraError("Incomplete missing attachment"); break; case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: NazaraError("Incomplete multisample"); break; case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: NazaraError("Incomplete layer targets"); break; case GL_FRAMEBUFFER_UNSUPPORTED: NazaraError("Render texture has unsupported attachments"); break; default: NazaraInternalError("Unknown error"); } m_impl->checked = true; } return m_impl->complete; }
void NzSceneRoot::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const { NazaraUnused(renderQueue); NazaraInternalError("SceneNode::AddToRenderQueue() called on SceneRoot"); }
void NzSceneRoot::Unregister() { NazaraInternalError("SceneNode::Unregister() called on SceneRoot"); }