Example #1
0
void ParticleDemo::RegisterParticleGroup(const Ndk::EntityHandle& entity)
{
	NazaraAssert(entity->HasComponent<Ndk::ParticleGroupComponent>(), "Must have particle group component");

	m_particleGroups.emplace_back(entity);
}
Example #2
0
	void World::Update()
	{
		// Gestion des entités tuées depuis le dernier appel
		for (unsigned int i = m_killedEntities.FindFirst(); i != m_killedEntities.npos; i = m_killedEntities.FindNext(i))
		{
			EntityBlock& block = m_entities[i];
			Entity& entity = block.entity;

			NazaraAssert(entity.IsValid(), "Entity must be valid");

			// Remise en file d'attente de l'identifiant d'entité
			m_freeIdList.push_back(entity.GetId());

			// Destruction de l'entité (invalidation du handle par la même occasion)
			entity.Destroy();

			// Nous allons sortir le handle de la liste des entités vivantes
			// en swappant le handle avec le dernier handle, avant de pop

			NazaraAssert(block.aliveIndex < m_aliveEntities.size(), "Alive index out of range");

			if (block.aliveIndex < m_aliveEntities.size()-1) // S'il ne s'agit pas du dernier handle
			{
				EntityHandle& lastHandle = m_aliveEntities.back();
				EntityHandle& myHandle = m_aliveEntities[block.aliveIndex];

				myHandle = std::move(lastHandle);

				// On n'oublie pas de corriger l'indice associé à l'entité
				m_entities[myHandle->GetId()].aliveIndex = block.aliveIndex;
			}
			m_aliveEntities.pop_back();
		}
		m_killedEntities.Reset();

		// Gestion des entités nécessitant une mise à jour de leurs systèmes
		for (unsigned int i = m_dirtyEntities.FindFirst(); i != m_dirtyEntities.npos; i = m_dirtyEntities.FindNext(i))
		{
			NazaraAssert(i < m_entities.size(), "Entity index out of range");

			Entity* entity = &m_entities[i].entity;

			// Check entity validity (as it could have been reported as dirty and killed during the same iteration)
			if (!entity->IsValid())
				continue;

			for (auto& system : m_systems)
			{
				// Ignore non-existent systems
				if (!system)
					continue;

				// Is our entity already part of this system?
				bool partOfSystem = system->HasEntity(entity);

				// Should it be part of it?
				if (entity->IsEnabled() && system->Filters(entity))
				{
					// Yes it should, add it to the system if not already done and validate it (again)
					if (!partOfSystem)
						system->AddEntity(entity);

					system->ValidateEntity(entity, !partOfSystem);
				}
				else
				{
					// No, it shouldn't, remove it if it's part of the system
					if (partOfSystem)
						system->RemoveEntity(entity);
				}
			}
		}
		m_dirtyEntities.Reset();
	}
	/*!
	* \brief Gets the rates of sample in the music
	* \return Rate of sample in Hertz (Hz)
	*
	* \remark Music must be valid when calling this function
	*/
	UInt32 Music::GetSampleRate() const
	{
		NazaraAssert(m_impl, "Music not created");

		return m_impl->sampleRate;
	}
	/*!
	* \brief Pauses the music
	*
	* \remark Music must be valid when calling this function
	*/
	void Music::Pause()
	{
		NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");

		alSourcePause(m_source);
	}
	/*!
	* \brief Enables the looping of the music
	*
	* \param loop Should music loop
	*
	* \remark Music must be valid when calling this function
	*/
	void Music::EnableLooping(bool loop)
	{
		NazaraAssert(m_impl, "Music not created");

		m_impl->loop = loop;
	}
	/*!
	* \brief Gets the format of the music
	* \return Enumeration of type AudioFormat (mono, stereo, ...)
	*
	* \remark Music must be valid when calling this function
	*/
	AudioFormat Music::GetFormat() const
	{
		NazaraAssert(m_impl, "Music not created");

		return m_impl->stream->GetFormat();
	}
	/*!
	* \brief Sets the maximum send buffer size
	*
	* \param size The new maximum send buffer size in bytes
	*/
	void AbstractSocket::SetSendBufferSize(std::size_t size)
	{
		NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Socket must be created first");
		
		SocketImpl::SetSendBufferSize(m_handle, size);
	}
Example #8
0
	std::vector<HostnameInfo> IpAddress::ResolveHostname(NetProtocol protocol, const String& hostname, const String& service, ResolveError* error)
	{
		NazaraAssert(protocol != NetProtocol_Unknown, "Invalid protocol");

		return IpAddressImpl::ResolveHostname(protocol, hostname, service, error);
	}
Example #9
0
	void TextSprite::Update(const AbstractTextDrawer& drawer)
	{
		CallOnExit clearOnFail([this]()
		{
			Clear();
		});

		// Mark every atlas as unused...
		for (auto& pair : m_atlases)
			pair.second.used = false;

		// ... until they are marked as used by the drawer
		std::size_t fontCount = drawer.GetFontCount();
		for (std::size_t i = 0; i < fontCount; ++i)
		{
			Font* font = drawer.GetFont(i);
			const AbstractAtlas* atlas = font->GetAtlas().get();
			NazaraAssert(atlas->GetStorage() & DataStorage_Hardware, "Font uses a non-hardware atlas which cannot be used by text sprites");

			auto it = m_atlases.find(atlas);
			if (it == m_atlases.end())
			{
				it = m_atlases.insert(std::make_pair(atlas, AtlasSlots())).first;
				AtlasSlots& atlasSlots = it->second;

				atlasSlots.clearSlot.Connect(atlas->OnAtlasCleared, this, &TextSprite::OnAtlasInvalidated);
				atlasSlots.layerChangeSlot.Connect(atlas->OnAtlasLayerChange, this, &TextSprite::OnAtlasLayerChange);
				atlasSlots.releaseSlot.Connect(atlas->OnAtlasRelease, this, &TextSprite::OnAtlasInvalidated);
			}

			it->second.used = true;
		}

		// Remove unused atlas slots
		auto atlasIt = m_atlases.begin();
		while (atlasIt != m_atlases.end())
		{
			if (!atlasIt->second.used)
				m_atlases.erase(atlasIt++);
			else
				++atlasIt;
		}

		std::size_t glyphCount = drawer.GetGlyphCount();
		m_localVertices.resize(glyphCount * 4);

		// Reset glyph count for every texture to zero
		for (auto& pair : m_renderInfos)
			pair.second.count = 0;

		// Count glyph count for each texture
		Texture* lastTexture = nullptr;
		unsigned int* count = nullptr;
		for (std::size_t i = 0; i < glyphCount; ++i)
		{
			const AbstractTextDrawer::Glyph& glyph = drawer.GetGlyph(i);

			Texture* texture = static_cast<Texture*>(glyph.atlas);
			if (lastTexture != texture)
			{
				auto it = m_renderInfos.find(texture);
				if (it == m_renderInfos.end())
					it = m_renderInfos.insert(std::make_pair(texture, RenderIndices{0U, 0U})).first;

				count = &it->second.count;
				lastTexture = texture;
			}

			(*count)++;
		}

		// Attributes indices and reinitialize glyph count to zero to use it as a counter in the next loop
		// This is because the 1st glyph can use texture A, the 2nd glyph can use texture B and the 3th glyph C can use texture A again
		// so we need a counter to know where to write informations
		// also remove unused render infos
		unsigned int index = 0;
		auto infoIt = m_renderInfos.begin();
		while (infoIt != m_renderInfos.end())
		{
			RenderIndices& indices = infoIt->second;
			if (indices.count == 0)
				m_renderInfos.erase(infoIt++); //< No glyph uses this texture, remove from indices
			else
			{
				indices.first = index;

				index += indices.count;
				indices.count = 0;
				++infoIt;
			}
		}

		lastTexture = nullptr;
		RenderIndices* indices = nullptr;
		for (unsigned int i = 0; i < glyphCount; ++i)
		{
			const AbstractTextDrawer::Glyph& glyph = drawer.GetGlyph(i);

			Texture* texture = static_cast<Texture*>(glyph.atlas);
			if (lastTexture != texture)
			{
				indices = &m_renderInfos[texture]; //< We changed texture, adjust the pointer
				lastTexture = texture;
			}

			// First, compute the uv coordinates from our atlas rect
			Vector2ui size(texture->GetSize());
			float invWidth = 1.f / size.x;
			float invHeight = 1.f / size.y;

			Rectf uvRect(glyph.atlasRect);
			uvRect.x *= invWidth;
			uvRect.y *= invHeight;
			uvRect.width *= invWidth;
			uvRect.height *= invHeight;

			// Our glyph may be flipped in the atlas, to render it correctly we need to change the uv coordinates accordingly
			const RectCorner normalCorners[4] = {RectCorner_LeftTop, RectCorner_RightTop, RectCorner_LeftBottom, RectCorner_RightBottom};
			const RectCorner flippedCorners[4] = {RectCorner_LeftBottom, RectCorner_LeftTop, RectCorner_RightBottom, RectCorner_RightTop};

			// Set the position, color and UV of our vertices
			for (unsigned int j = 0; j < 4; ++j)
			{
				// Remember that indices->count is a counter here, not a count value
				m_localVertices[indices->count * 4 + j].color = glyph.color;
				m_localVertices[indices->count * 4 + j].position.Set(glyph.corners[j]);
				m_localVertices[indices->count * 4 + j].uv.Set(uvRect.GetCorner((glyph.flipped) ? flippedCorners[j] : normalCorners[j]));
			}

			// Increment the counter, go to next glyph
			indices->count++;
		}

		m_localBounds = drawer.GetBounds();

		InvalidateBoundingVolume();
		InvalidateInstanceData(0);

		clearOnFail.Reset();
	}
	/*!
	* \brief Queries the maximum socket send buffer size
	* \return The size of the send buffer in bytes.
	*/
	std::size_t AbstractSocket::QuerySendBufferSize() const
	{
		NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Socket must be created first");

		return SocketImpl::QuerySendBufferSize(m_handle);
	}
Example #11
0
	void ParticleGroup::AddController(ParticleControllerRef controller)
	{
		NazaraAssert(controller, "Invalid particle controller");

		m_controllers.emplace_back(std::move(controller));
	}
Example #12
0
	void ParticleGroup::AddGenerator(ParticleGeneratorRef generator)
	{
		NazaraAssert(generator, "Invalid particle generator");

		m_generators.emplace_back(std::move(generator));
	}
Example #13
0
	bool TcpClient::ReceivePacket(NetPacket* packet)
	{
		//TODO: Every packet requires at least two Receive call, using an internal buffer of a fixed size would prevent this
		NazaraAssert(packet, "Invalid packet");

		if (!m_pendingPacket.headerReceived)
		{
			m_pendingPacket.data.Resize(NetPacket::HeaderSize);

			std::size_t received;
			if (!Receive(&m_pendingPacket.data[m_pendingPacket.received], NetPacket::HeaderSize - m_pendingPacket.received, &received))
				return false;

			m_pendingPacket.received += received;

			//TODO: Should never happen in production !
			NazaraAssert(m_pendingPacket.received <= NetPacket::HeaderSize, "Received more data than header size");
			if (m_pendingPacket.received >= NetPacket::HeaderSize)
			{
				UInt16 size;
				if (!NetPacket::DecodeHeader(m_pendingPacket.data.GetConstBuffer(), &size, &m_pendingPacket.netcode))
				{
					m_lastError = SocketError_Packet;
					NazaraWarning("Invalid header data");
					return false;
				}

				m_pendingPacket.data.Resize(size - NetPacket::HeaderSize);
				m_pendingPacket.headerReceived = true;
				m_pendingPacket.received = 0;
			}
		}

		// We may have just received the header now
		if (m_pendingPacket.headerReceived)
		{
			UInt16 packetSize = static_cast<UInt16>(m_pendingPacket.data.GetSize()); //< Total packet size
			if (packetSize == 0)
			{
				// Special case: our packet carry no data
				packet->Reset(m_pendingPacket.netcode);

				// And reset every state
				m_pendingPacket.data.Clear();
				m_pendingPacket.headerReceived = false;
				m_pendingPacket.received = 0;
				return true;
			}

			std::size_t received;
			if (!Receive(&m_pendingPacket.data[m_pendingPacket.received], packetSize - m_pendingPacket.received, &received))
				return false;

			m_pendingPacket.received += received;

			//TODO: Should never happen in production !
			NazaraAssert(m_pendingPacket.received <= packetSize, "Received more data than packet size");
			if (m_pendingPacket.received >= packetSize)
			{
				// Okay we received the whole packet, copy it
				packet->Reset(m_pendingPacket.netcode, m_pendingPacket.data.GetConstBuffer(), m_pendingPacket.data.GetSize());

				// And reset every state
				m_pendingPacket.data.Clear();
				m_pendingPacket.headerReceived = false;
				m_pendingPacket.received = 0;
				return true;
			}
		}

		return false;
	}
Example #14
0
	const Primitive& PrimitiveList::GetPrimitive(std::size_t i) const
	{
		NazaraAssert(i < m_primitives.size(), "Primitive index out of range");

		return m_primitives[i];
	}
	void ConditionVariable::Wait(Mutex* mutex)
	{
		NazaraAssert(mutex != nullptr, "Mutex must be valid");
		m_impl->Wait(mutex->m_impl);
	}
Example #16
0
	String IpAddress::ToString() const
	{
		StringStream stream;

		if (m_isValid)
		{
			NazaraAssert(m_protocol <= NetProtocol_Max, "Protocol has value out of enum");
			switch (m_protocol)
			{
				case NetProtocol_Any:
				case NetProtocol_Unknown:
					break;

				case NetProtocol_IPv4:
					for (unsigned int i = 0; i < 4; ++i)
					{
						stream << int(m_ipv4[i]);
						if (i != 3)
							stream << '.';
					}
					break;

				case NetProtocol_IPv6:
					// Canonical representation of an IPv6
					// https://tools.ietf.org/html/rfc5952

					// Find the longest zero sequence
					unsigned int f0 = std::numeric_limits<unsigned int>::max();
					unsigned int l0 = std::numeric_limits<unsigned int>::max();

					for (unsigned int i = 0; i < 8; ++i)
					{
						if (m_ipv6[i] == 0)
						{
							unsigned int j;
							for (j = i + 1; j < 8; ++j)
							{
								if (m_ipv6[j] != 0)
									break;
							}

							if (j - i > std::max<unsigned int>(l0 - f0, 1))
							{
								f0 = i;
								l0 = j;
							}
						}
					}

					// We need brackets around our IPv6 address if we have a port
					if (m_port != 0)
						stream << '[';

					for (unsigned int i = 0; i < 8; ++i)
					{
						if (i == f0)
						{
							stream << "::";
							i = l0;
							if (i >= 8)
								break;
						}
						else if (i != 0)
							stream << ':';

						stream << String::Number(m_ipv6[i], 16).ToLower();
					}

					if (m_port != 0)
						stream << ']';
					break;
			}

			if (m_port != 0)
				stream << ':' << m_port;
		}

		return stream;
	}
	bool ConditionVariable::Wait(Mutex* mutex, UInt32 timeout)
	{
		NazaraAssert(mutex != nullptr, "Mutex must be valid");
		return m_impl->Wait(mutex->m_impl, timeout);
	}
	std::size_t UdpSocket::QueryMaxDatagramSize()
	{
		NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Socket hasn't been created");

		return SocketImpl::QueryMaxDatagramSize(m_handle, &m_lastError);
	}
	bool DeferredPhongLightingPass::Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned secondWorkTexture) const
	{
		NazaraAssert(sceneData.viewer, "Invalid viewer");
		NazaraUnused(secondWorkTexture);

		m_workRTT->SetColorTarget(firstWorkTexture);
		Renderer::SetTarget(m_workRTT);
		Renderer::SetViewport(Recti(0, 0, m_dimensions.x, m_dimensions.y));

		Renderer::SetTexture(0, m_GBuffer[0]);
		Renderer::SetTextureSampler(0, m_pointSampler);

		Renderer::SetTexture(1, m_GBuffer[1]);
		Renderer::SetTextureSampler(1, m_pointSampler);

		Renderer::SetTexture(2, m_GBuffer[2]);
		Renderer::SetTextureSampler(2, m_pointSampler);

		Renderer::SetClearColor(Color::Black);
		Renderer::Clear(RendererBuffer_Color);

		RenderStates lightStates;
		lightStates.dstBlend = BlendFunc_One;
		lightStates.srcBlend = BlendFunc_One;
		lightStates.parameters[RendererParameter_Blend] = true;
		lightStates.parameters[RendererParameter_DepthBuffer] = false;
		lightStates.parameters[RendererParameter_DepthWrite] = false;

		// Directional lights
		if (!m_renderQueue->directionalLights.empty())
		{
			Renderer::SetRenderStates(lightStates);
			Renderer::SetShader(m_directionalLightShader);
			m_directionalLightShader->SendColor(m_directionalLightShaderSceneAmbientLocation, sceneData.ambientColor);
			m_directionalLightShader->SendVector(m_directionalLightShaderEyePositionLocation, sceneData.viewer->GetEyePosition());

			for (auto& light : m_renderQueue->directionalLights)
			{
				m_directionalLightShader->SendColor(m_directionalLightUniforms.locations.color, light.color);
				m_directionalLightShader->SendVector(m_directionalLightUniforms.locations.factors, Vector2f(light.ambientFactor, light.diffuseFactor));
				m_directionalLightShader->SendVector(m_directionalLightUniforms.locations.parameters1, Vector4f(light.direction));

				Renderer::DrawFullscreenQuad();
			}
		}

		// Point lights/Spot lights
		if (!m_renderQueue->pointLights.empty() || !m_renderQueue->spotLights.empty())
		{
			// http://www.altdevblogaday.com/2011/08/08/stencil-buffer-optimisation-for-deferred-lights/
			lightStates.parameters[RendererParameter_StencilTest] = true;
			lightStates.faceCulling = FaceSide_Front;
			lightStates.backFace.stencilMask = 0xFF;
			lightStates.backFace.stencilReference = 0;
			lightStates.backFace.stencilFail = StencilOperation_Keep;
			lightStates.backFace.stencilPass = StencilOperation_Keep;
			lightStates.backFace.stencilZFail = StencilOperation_Invert;
			lightStates.frontFace.stencilMask = 0xFF;
			lightStates.frontFace.stencilReference = 0;
			lightStates.frontFace.stencilFail = StencilOperation_Keep;
			lightStates.frontFace.stencilPass = StencilOperation_Keep;
			lightStates.frontFace.stencilZFail = StencilOperation_Invert;

			Renderer::SetRenderStates(lightStates);

			Renderer::SetShader(m_pointSpotLightShader);
			m_pointSpotLightShader->SendColor(m_pointSpotLightShaderSceneAmbientLocation, sceneData.ambientColor);
			m_pointSpotLightShader->SendVector(m_pointSpotLightShaderEyePositionLocation, sceneData.viewer->GetEyePosition());

			Matrix4f lightMatrix;
			lightMatrix.MakeIdentity();
			if (!m_renderQueue->pointLights.empty())
			{
				const IndexBuffer* indexBuffer = m_sphereMesh->GetIndexBuffer();
				Renderer::SetIndexBuffer(indexBuffer);
				Renderer::SetVertexBuffer(m_sphereMesh->GetVertexBuffer());

				m_pointSpotLightShader->SendInteger(m_pointSpotLightUniforms.locations.type, LightType_Point);
				for (const auto& light : m_renderQueue->pointLights)
				{
					m_pointSpotLightShader->SendColor(m_pointSpotLightUniforms.locations.color, light.color);
					m_pointSpotLightShader->SendVector(m_pointSpotLightUniforms.locations.factors, Vector2f(light.ambientFactor, light.diffuseFactor));
					m_pointSpotLightShader->SendVector(m_pointSpotLightUniforms.locations.parameters1, Vector4f(light.position, light.attenuation));
					m_pointSpotLightShader->SendVector(m_pointSpotLightUniforms.locations.parameters2, Vector4f(0.f, 0.f, 0.f, light.invRadius));

					lightMatrix.SetScale(Vector3f(light.radius * 1.1f)); // Pour corriger les imperfections liées à la sphère
					lightMatrix.SetTranslation(light.position);

					Renderer::SetMatrix(MatrixType_World, lightMatrix);

					// Rendu de la sphère dans le stencil buffer
					Renderer::Enable(RendererParameter_ColorWrite, false);
					Renderer::Enable(RendererParameter_DepthBuffer, true);
					Renderer::Enable(RendererParameter_FaceCulling, false);
					Renderer::SetStencilCompareFunction(RendererComparison_Always);

					m_pointSpotLightShader->SendBoolean(m_pointSpotLightShaderDiscardLocation, true);

					Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());

					// Rendu de la sphère comme zone d'effet
					Renderer::Enable(RendererParameter_ColorWrite, true);
					Renderer::Enable(RendererParameter_DepthBuffer, false);
					Renderer::Enable(RendererParameter_FaceCulling, true);
					Renderer::SetStencilCompareFunction(RendererComparison_NotEqual, FaceSide_Back);
					Renderer::SetStencilPassOperation(StencilOperation_Zero, FaceSide_Back);

					m_pointSpotLightShader->SendBoolean(m_pointSpotLightShaderDiscardLocation, false);

					Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());
				}

				if (m_lightMeshesDrawing)
				{
					Renderer::Enable(RendererParameter_DepthBuffer, true);
					Renderer::Enable(RendererParameter_DepthWrite, true);
					Renderer::Enable(RendererParameter_FaceCulling, false);
					Renderer::Enable(RendererParameter_StencilTest, false);
					Renderer::SetFaceFilling(FaceFilling_Line);

					const Shader* shader = ShaderLibrary::Get("DebugSimple");
					static int colorLocation = shader->GetUniformLocation("Color");

					Renderer::SetShader(shader);
					for (const auto& light : m_renderQueue->pointLights)
					{
						lightMatrix.SetScale(Vector3f(light.radius * 1.1f)); // Pour corriger les imperfections liées à la sphère
						lightMatrix.SetTranslation(light.position);

						Renderer::SetMatrix(MatrixType_World, lightMatrix);

						shader->SendColor(colorLocation, light.color);

						Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());
					}

					Renderer::Enable(RendererParameter_DepthBuffer, false);
					Renderer::Enable(RendererParameter_DepthWrite, false);
					Renderer::Enable(RendererParameter_FaceCulling, true);
					Renderer::Enable(RendererParameter_StencilTest, true);
					Renderer::SetFaceFilling(FaceFilling_Fill);
				}
			}

			if (!m_renderQueue->spotLights.empty())
			{
				const IndexBuffer* indexBuffer = m_coneMesh->GetIndexBuffer();
				Renderer::SetIndexBuffer(indexBuffer);
				Renderer::SetVertexBuffer(m_coneMesh->GetVertexBuffer());

				m_pointSpotLightShader->SendInteger(m_pointSpotLightUniforms.locations.type, LightType_Spot);
				for (const auto& light : m_renderQueue->spotLights)
				{
					m_pointSpotLightShader->SendColor(m_pointSpotLightUniforms.locations.color, light.color);
					m_pointSpotLightShader->SendVector(m_pointSpotLightUniforms.locations.factors, Vector2f(light.ambientFactor, light.diffuseFactor));
					m_pointSpotLightShader->SendVector(m_pointSpotLightUniforms.locations.parameters1, Vector4f(light.position, light.attenuation));
					m_pointSpotLightShader->SendVector(m_pointSpotLightUniforms.locations.parameters2, Vector4f(light.direction, light.invRadius));
					m_pointSpotLightShader->SendVector(m_pointSpotLightUniforms.locations.parameters3, Vector2f(light.innerAngleCosine, light.outerAngleCosine));

					float baseRadius = light.radius * light.outerAngleTangent * 1.1f;
					lightMatrix.MakeTransform(light.position, Quaternionf::RotationBetween(Vector3f::Forward(), light.direction), Vector3f(baseRadius, baseRadius, light.radius));

					Renderer::SetMatrix(MatrixType_World, lightMatrix);

					// Rendu de la sphère dans le stencil buffer
					Renderer::Enable(RendererParameter_ColorWrite, false);
					Renderer::Enable(RendererParameter_DepthBuffer, true);
					Renderer::Enable(RendererParameter_FaceCulling, false);
					Renderer::SetStencilCompareFunction(RendererComparison_Always);

					m_pointSpotLightShader->SendBoolean(m_pointSpotLightShaderDiscardLocation, true);

					Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());

					// Rendu de la sphère comme zone d'effet
					Renderer::Enable(RendererParameter_ColorWrite, true);
					Renderer::Enable(RendererParameter_DepthBuffer, false);
					Renderer::Enable(RendererParameter_FaceCulling, true);
					Renderer::SetFaceCulling(FaceSide_Front);
					Renderer::SetStencilCompareFunction(RendererComparison_NotEqual, FaceSide_Back);
					Renderer::SetStencilPassOperation(StencilOperation_Zero, FaceSide_Back);

					m_pointSpotLightShader->SendBoolean(m_pointSpotLightShaderDiscardLocation, false);

					Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());
				}

				if (m_lightMeshesDrawing)
				{
					Renderer::Enable(RendererParameter_DepthBuffer, true);
					Renderer::Enable(RendererParameter_DepthWrite, true);
					Renderer::Enable(RendererParameter_FaceCulling, false);
					Renderer::Enable(RendererParameter_StencilTest, false);
					Renderer::SetFaceFilling(FaceFilling_Line);

					const Shader* shader = ShaderLibrary::Get("DebugSimple");
					static int colorLocation = shader->GetUniformLocation("Color");

					Renderer::SetShader(shader);
					for (const auto& light : m_renderQueue->spotLights)
					{
						float baseRadius = light.radius * light.outerAngleTangent * 1.1f;
						lightMatrix.MakeTransform(light.position, Quaternionf::RotationBetween(Vector3f::Forward(), light.direction), Vector3f(baseRadius, baseRadius, light.radius));

						Renderer::SetMatrix(MatrixType_World, lightMatrix);

						shader->SendColor(colorLocation, light.color);

						Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());
					}

					Renderer::Enable(RendererParameter_DepthBuffer, false);
					Renderer::Enable(RendererParameter_DepthWrite, false);
					Renderer::Enable(RendererParameter_FaceCulling, true);
					Renderer::Enable(RendererParameter_StencilTest, true);
					Renderer::SetFaceFilling(FaceFilling_Fill);
				}
			}

			Renderer::Enable(RendererParameter_StencilTest, false);
		}

		return true;
	}
	/*!
	* \brief Gets the duration of the music
	* \return Duration of the music in milliseconds
	*
	* \remark Music must be valid when calling this function
	*/
	UInt32 Music::GetDuration() const
	{
		NazaraAssert(m_impl, "Music not created");

		return m_impl->stream->GetDuration();
	}
Example #21
0
	/*!
	* \brief Plays the music
	*
	* \remark Produces a NazaraError if the sound is not playable with NAZARA_AUDIO_SAFE defined
	*/
	void Sound::Play()
	{
		NazaraAssert(IsPlayable(), "Music is not playable");

		alSourcePlay(m_source);
	}
	/*!
	* \brief Gets the number of samples in the music
	* \return Count of samples (number of seconds * sample rate * channel count)
	*
	* \remark Music must be valid when calling this function
	*/
	UInt64 Music::GetSampleCount() const
	{
		NazaraAssert(m_impl, "Music not created");

		return m_impl->stream->GetSampleCount();
	}
Example #23
0
	/*!
	* \brief Gets the duration of the sound
	* \return Duration of the music in milliseconds
	*
	* \remark Produces a NazaraError if there is no buffer
	*/
	UInt32 Sound::GetDuration() const
	{
		NazaraAssert(m_buffer, "Invalid sound buffer");

		return m_buffer->GetDuration();
	}
	/*!
	* \brief Checks whether the music is looping
	* \return true if it is the case
	*
	* \remark Music must be valid when calling this function
	*/
	bool Music::IsLooping() const
	{
		NazaraAssert(m_impl, "Music not created");

		return m_impl->loop;
	}
Example #25
0
	/*!
	* \brief Changes the debugging name associated to the calling thread
	*
	* Changes the debugging name associated with the calling thread, and may helps with debugging tools.
	*
	* \param name The new name associated with this thread
	*
	* \remark Due to system limitations, thread name cannot exceed 15 characters (excluding null-terminator)
	*
	* \see SetName
	*/
	void Thread::SetCurrentThreadName(const String& name)
	{
		NazaraAssert(name.GetSize() < 16, "Thread name is too long");

		ThreadImpl::SetCurrentName(name);
	}
	void DepthRenderQueue::AddPointLight(const PointLight& light)
	{
		NazaraAssert(false, "Depth render queue doesn't handle lights");
		NazaraUnused(light);
	}
	void PhysicsSystem3D::CreatePhysWorld() const
	{
		NazaraAssert(!m_world, "Physics world should not be created twice");

		m_world = std::make_unique<Nz::PhysWorld3D>();
	}