Przeglądaj źródła

render only enlighted blocks

Kolja Strohm 2 lat temu
rodzic
commit
3ab376f9ab

+ 10 - 6
FactoryCraft/Block.cpp

@@ -14,7 +14,7 @@ Block::Block(const BlockType* zType, Framework::Vec3<int> pos, Model3DData* mode
 {
 	transparent = 0;
 	hp = (float)maxHP;
-	memset(sideVisible, 1, 6);
+	memset(sideVisible, 0, 6);
 	Model3D::setPosition((Framework::Vec3<float>)pos + Framework::Vec3<float>{0.5f, 0.5f, 0.5f});
 	setModelDaten(model);
 	setModelTextur(texture);
@@ -64,11 +64,6 @@ bool Block::isTransparent() const
 	return transparent;
 }
 
-void Block::setSideVisible(Direction dir, bool visible)
-{
-	sideVisible[getDirectionIndex(dir)] = visible;
-}
-
 void Block::setLightData(Direction dir, unsigned char* data)
 {
 	memcpy(lightData + getDirectionIndex(dir) * 6, data, 6);
@@ -92,6 +87,15 @@ void Block::setLightData(Direction dir, unsigned char* data)
 			*(int*)(lightBuffer + i * 4) = l;
 		}
 	}
+	if (data[0] | data[1] | data[2] | data[3] | data[4] | data[5])
+		sideVisible[getDirectionIndex(dir)] = 1;
+	else
+		sideVisible[getDirectionIndex(dir)] = 0;
+}
+
+bool Block::isVisible() const
+{
+	return sideVisible[0] || sideVisible[1] || sideVisible[2] || sideVisible[3] || sideVisible[4] || sideVisible[5];
 }
 
 Vec3<int> Block::getLocation() const

+ 1 - 1
FactoryCraft/Block.h

@@ -32,8 +32,8 @@ public:
 
 	void api(char* message);
 	bool isTransparent() const;
-	void setSideVisible(Direction dir, bool visible);
 	void setLightData(Direction dir, unsigned char* data);
+	bool isVisible() const;
 
 	Vec3<int> getLocation() const;
 	const BlockType* zBlockType() const;

+ 85 - 30
FactoryCraft/Chunk.cpp

@@ -62,7 +62,28 @@ void Chunk::api(char* message)
 					pos.y += this->location.y - CHUNK_SIZE / 2;
 					Block* zB = zBlockAt(pos);
 					if (zB)
+					{
+						bool visible = zB->isVisible();
 						zB->setLightData(getOppositeDirection(getDirectionFromIndex(i)), (unsigned char*)(message + 5));
+						if (zB->isVisible() != visible)
+						{
+							vcs.lock();
+							if (zB->isVisible())
+								visibleBlocks.add(zB);
+							else
+							{
+								for (Framework::Iterator<Block*> iterator = visibleBlocks.begin(); iterator; iterator++)
+								{
+									if (zB == (Block*)iterator)
+									{
+										iterator.remove();
+										break;
+									}
+								}
+							}
+							vcs.unlock();
+						}
+					}
 				}
 				else
 				{
@@ -70,7 +91,29 @@ void Chunk::api(char* message)
 					pos.y += this->location.y - CHUNK_SIZE / 2;
 					Block* zB = currentGame->zBlockAt(pos);
 					if (zB)
+					{
+						bool visible = zB->isVisible();
 						zB->setLightData(getOppositeDirection(getDirectionFromIndex(i)), (unsigned char*)(message + 5));
+						if (zB->isVisible() != visible)
+						{
+							Chunk* c = currentGame->zChunk(currentGame->getChunkCenter(pos.x, pos.y));
+							c->vcs.lock();
+							if (zB->isVisible())
+								c->visibleBlocks.add(zB);
+							else
+							{
+								for (Framework::Iterator<Block*> iterator = c->visibleBlocks.begin(); iterator; iterator++)
+								{
+									if (zB == (Block*)iterator)
+									{
+										iterator.remove();
+										break;
+									}
+								}
+							}
+							c->vcs.unlock();
+						}
+					}
 				}
 			}
 		}
@@ -101,33 +144,46 @@ void Chunk::setBlock(Block* block)
 	{
 		if (pos == iterator->getLocation())
 		{
+			vcs.lock();
+			for (Framework::Iterator<Block*> vi = visibleBlocks.begin(); vi; vi++)
+			{
+				if ((Block*)iterator == (Block*)vi)
+				{
+					iterator.remove();
+					break;
+				}
+			}
+			vcs.unlock();
 			iterator->release();
 			iterator.set(block);
-			cs.unlock();
-			return;
+			break;
 		}
 	}
 	blocks.add(block);
 	cs.unlock();
-	if (!isLoading)
-		updateVisibility();
 }
 
 void Chunk::removeBlock(Block* zBlock)
 {
 	cs.lock();
-	int index = 0;
-	for (Framework::Iterator<Block*> iterator = blocks.begin(); iterator; iterator++, index++)
+	for (Framework::Iterator<Block*> iterator = blocks.begin(); iterator; iterator++)
 	{
 		if (zBlock == (Block*)iterator)
 		{
-			blocks.remove(index);
-			cs.unlock();
-			if (!isLoading)
-				updateVisibility();
-			return;
+			iterator.remove();
+			break;
 		}
 	}
+	vcs.lock();
+	for (Framework::Iterator<Block*> iterator = visibleBlocks.begin(); iterator; iterator++)
+	{
+		if (zBlock == (Block*)iterator)
+		{
+			iterator.remove();
+			break;
+		}
+	}
+	vcs.unlock();
 	cs.unlock();
 }
 
@@ -165,7 +221,12 @@ void Chunk::load(Framework::StreamReader* zReader)
 					pos.y += this->location.y - CHUNK_SIZE / 2;
 					Block* zB = zBlockAt(pos);
 					if (zB)
+					{
+						bool visible = zB->isVisible();
 						zB->setLightData(getOppositeDirection(getDirectionFromIndex(i)), (unsigned char*)lightData);
+						if (zB->isVisible() && !visible)
+							visibleBlocks.add(zB);
+					}
 				}
 				else
 				{
@@ -173,14 +234,23 @@ void Chunk::load(Framework::StreamReader* zReader)
 					pos.y += this->location.y - CHUNK_SIZE / 2;
 					Block* zB = currentGame->zBlockAt(pos);
 					if (zB)
+					{
+						bool visible = zB->isVisible();
 						zB->setLightData(getOppositeDirection(getDirectionFromIndex(i)), (unsigned char*)lightData);
+						if (zB->isVisible() && !visible)
+						{
+							Chunk* c = currentGame->zChunk(currentGame->getChunkCenter(pos.x, pos.y));
+							c->vcs.lock();
+							c->visibleBlocks.add(zB);
+							c->vcs.unlock();
+						}
+					}
 				}
 			}
 		}
 		zReader->lese((char*)&index, 4);
 	}
 	isLoading = 0;
-	updateVisibility();
 }
 
 Framework::Punkt Chunk::getCenter() const
@@ -200,23 +270,8 @@ Framework::Vec3<int> Chunk::getMax() const
 
 void Chunk::forAll(std::function<void(Model3D*)> f)
 {
-	cs.lock();
-	for (Block* b : blocks)
+	vcs.lock();
+	for (Block* b : visibleBlocks)
 		f(b);
-	cs.unlock();
-}
-
-void Chunk::updateVisibility()
-{
-	cs.lock();
-	for (Block* b : blocks)
-	{
-		Framework::Vec3<int> pos = Framework::Vec3<int>((int)floor(b->getPos().x), (int)floor(b->getPos().y), (int)floor(b->getPos().z));
-		for (int i = 0; i < 6; i++)
-		{
-			Block* c = zBlockAt(pos + getDirection(getDirectionFromIndex(i)));
-			b->setSideVisible(getDirectionFromIndex(i), !c || c->isTransparent());
-		}
-	}
-	cs.unlock();
+	vcs.unlock();
 }

+ 2 - 1
FactoryCraft/Chunk.h

@@ -16,8 +16,10 @@ private:
 	Framework::Punkt location;
 	// TODO: use native array for bedder performance?
 	Framework::RCArray<Block> blocks;
+	Framework::Array<Block*> visibleBlocks;
 	bool isLoading;
 	Framework::Critical cs;
+	Framework::Critical vcs;
 
 public:
 	Chunk(Framework::Punkt location);
@@ -32,5 +34,4 @@ public:
 	Framework::Vec3<int> getMin() const;
 	Framework::Vec3<int> getMax() const;
 	void forAll(std::function<void(Model3D*)> f) override;
-	void updateVisibility();
 };

+ 6 - 1
FactoryCraft/World.cpp

@@ -320,5 +320,10 @@ Framework::Model3D* World::getCurrentTarget() const
 {
 	while (targetLock.isLocked())
 		Sleep(1);
-	return currentTarget ? dynamic_cast<Framework::Model3D * >(currentTarget->getThis()) : 0;
+	return currentTarget ? dynamic_cast<Framework::Model3D*>(currentTarget->getThis()) : 0;
+}
+
+Chunk* World::zChunk(Punkt center)
+{
+	return currentDimension->zChunk(center);
 }

+ 1 - 0
FactoryCraft/World.h

@@ -45,5 +45,6 @@ public:
 	void lockWorld();
 	void unlockWorld();
 	void onChunkAdded(Punkt pos);
+	Chunk* zChunk(Punkt center);
 	Framework::Model3D* getCurrentTarget() const;
 };