• 欢迎来到Minecraft插件百科!
  • 对百科编辑一脸懵逼?帮助:快速入门带您快速熟悉百科编辑!
  • 因近日遭受攻击,百科现已限制编辑,有意编辑请加入插件百科企鹅群:223812289

TerrainControl/高级部分

来自Minecraft插件百科
跳转到导航 跳转到搜索

高级部分

插件解析

页面信息

Mister_Tesseract 所做的插件解析,community(也可译为社区)所做的补充与纠错。

此页面已经从这里 复制到了Wiki。此文章的讨论请到这个论坛帖子.

目录

注:连接到英文原页面

介绍

回到顶部

Hello and thank you for your interest in this research about TerrainControl. I, Mister_Tesseract, call it a “research” and not a “tutorial” because it is more than a tutorial in that it tries to understand how the plugin works beyond what you really need to make it work in a general purpose. It is also less than a tutorial because it doesn’t provide many how-to’s (but perhaps I will do that a little more in the future). My ambition with this research is that after reading this once it is complete, you should be able to understand the deep mechanics that rule the TerrainControl generator enough to make virtually every possible biome in Minecraft.

Why not a simple step-by-step tutorial? I see two main reasons for this.

The first one is that TerrainControl is such a complex and vaste plugin that you cannot learn much from a step-by-step tutorial that would teach you how to make just one biome and then leave you on your own. There are so many parameters in TerrainControl that a tutorial would need to guide you through the creation of at least ten different biomes in order to have you get a glimpse of what it can do.

The second reason, a more personal one, is that it’s not my style to make that kind of tutorial. I have studied physics (and epistemology a little) and all that science gives you a methodology you cannot get out of your head just like that (and it’s so cool). So I set up an experimental protocol, I take measurements, I estimate margins of error, and I try to find applications for the newly acquired knowledge, which is pretty much what researchers do. This method cannot lead to a how-to tutorial without loss of information. But in the future I’m probably going to try and make a “generic” how-to which will explain in what order it is best to build a biome.

Obviously, I could look inside the source code and find the exact laws that rule the TerrainControl plugin and the Minecraft generator (or maybe I’ll find nothing at all) but believe me or not, I do this as if it was part of the game ; and I actually find it interesting and funny. In other words, I’m like a Minecraft crazy scientist trying to find the laws of the creation the universe.

Sometimes I might not be very clear in my explanations, and I apologize in advance for anything you couldn’t understand and that is due to my lack of clarity. Such clarity is one of my objectives but my priority was to finish a first version in order to release it as soon as possible. Hopefully that clarity will soon stop being a problem thanks to your feedback.

I try to use generated map images (with the command /tc map) as much as possible but sometimes I had to make more precise measurements, or it just didn’t help to have a map image (for instance when the image doesn’t show altitude). Here is the method I followed when a map image was not enough to fulfill the requirements in precision: 1.Create a world config with only one Biome in addition to Ocean and use it in a new world. 2.Delete the region folder if there is one. 3.Start the game in that world and make measurements about height, slope and shape of the terrain, and vegetation and ores. 4.Change a setting in the Biome config and save. 5.Quit the game. 6.Repeat from 2. until having enough measurements to have an accurate enough idea of the curve’s behaviour.

What I am looking for in this research is pertinence in terms of utility and not necessarily finding the exact inflection point of a function. For example, sometimes I will indicate what happens if you set a value inferior to -0.25 for MaxAverageHeight , but if you go at -0.20 it won't change very much so I could have put -0.20 to be more precise in my work. But the value -0.25 is safe and precise enough to be used as a zero and the lost information is a low cost compared to the time it would take to find the limit with better precision. This is what I mean by ‘utility’.

This partially explains the absence of regular intervals in the tables. You will also find odd values like 3.62 followed by 4.0 which seem close enough but I kept the measurement made at 3.62 because it gives a better idea of how strong you have to go down from 256.

There is also the default irregularity in terrain when all values are zero or close to their minimal effect. This doesn’t allow a perfect output in layer numbers because the terrain is not perfectly flat, even in the flattest areas (with most settings). I decided to choose the layer of floor that seemed to be the most represented in my environment after looking around a little, which was closest to the idea of an average/median value.

This study is evaluating every separate variable all other things being equal. If you have different results it is probably because you changed two variables at once. Some combinations of several variable changes will give expected results and some won’t. It is already a huge work to study each variable separately ; I probably won’t step into the details of studying every couple or triplet because it would take a very long time.

A very important point about all this research is that I write things here as I discover them. The facts (measurements) are obviously real and you will be able to reproduce them at will; but my interpretation is relative and it is always possible that a new fact comes burn my paradigm down to ashes. It happened to me when I came to Border and Isle biomes, as their size couldn’t match my interpretation. I then had to start from square one with world generation.

Conclusion: take every interpretation I make about this with a grain of salt. This is science, and as Karl Popper established it, if it’s science, then it can be tested. Even the most certain knowledge can be rammed down by the tiniest new fact. That is why I encourage you to comment and tell me when I’m wrong so the interpretation can be rebuilt and our knowledge in TerrainControl can see progress.

选择“default”作为数值的变量

回到顶部

The values and effects provided here were determined with using this WorldConfig.ini with a flat, resourceless PlainsBiomeConfig.ini biome. There are a few differences with default/vanilla settings:

  • WorldHeightBits = 8 (max land height = 28 = 256) so regular land will be at layer 128 (instead of 64 for vanilla Minecraft). The default value for this is usually 7, which prevents land from appearing above layer 128.
  • Almost every biome value is 0.0. The values that differ from zero are VolatilityWeight1 and VolatilityWeight2 because their default values are repectively 0.5 and 0.45. Sometimes BiomeVolatility is 0.1 instead of 0.0 because it looks like other variables are multiplied by BiomeVolatility and 0.0 would nullify them.
  • No resources at all, for faster generation: it’s a lot of work for the computer to generate a new map at every game, and finding ores is of course not the objective. This is true for doing research like mine, but it is also true when it comes to creating custom biomes. There will be a point where you’ll be reloading a new map every 60 seconds and change the value by 0.05 in order to get the fine tune. Then you want to go as fast as possible and resource generation takes a lot of processing time. That is why ore, trees and mob distribution is the thing you want to create in last position in your biome, especially with a slow computer. Of course, when it will come to researching about ore generation, it will be included as well.
生成过程

回到顶部

This part is about how I view how terrain generation works. I have acquired a good comprehension of it after reading this thread on the forums of dev.bukkit.org and I have developed my own way to formulating it but it’s basically the same explanation.

I wanted to explain separately WorldConfig.ini and xBiomeConfig.ini but it’s not possible to do without gaps or redundancy so I’m going to explain both of them as a whole. You will just have to figure out yourself where each variable stands.

One thing that I want to point at is that you can use any seed for TerrainControl. I noticed on the bukkit forums that some people kept using the seed “tim1998+steps1956” (which is not more special than any other seed). It is not mandatory at all. Every seed will work with TerrainControl, just like every seed works in the vanilla game.

The smallest unit of size that the generator can create is 1 chunk. By default, GenerationDepth has a value which is around 10. Every new increase of 1 for GenerationDepth is a double in size for the largest thing the generator will be able to generate. The biggest possible size for a generated surface will then be 2GenerationDepth.

Important note: the following description is not true for biomes set as Border or Isle, only for normal Biomes. Borders and Isles will be explained right after.

At first, the world is a full Ocean. Once GenerationDepth is determined, the generator will add land areas (not biomes yet, only landmass) on that Ocean. This depends on three parameters: LandSize , LandRarity and LandFuzzy .

LandRarity has “useful” values from 90 to 99 (100 if you want very little or no Ocean). It’s not a linear function, so below 94 it’s very difficult to find any land.

LandSize will determine size of landmasses, and then the generator will add ice areas with IceSize the same way.

LandFuzzy adds irregularities to the landmass borders (maybe biome borders ?). Its value has to be between 0 and GenerationDepth - LandSize because those irregularities use the accuracy of the generator. with value 0 there won’t be any fuzzy added to the land borders, and maximum LandFuzzy values will add lots of irregularities which size will vary from half of the landsize (LandSize - 1) to 1 chunk.

After that, the generator will fill in the biomes, from the largest (small BiomeSize value) to the tiniest (large BiomeSize value).

I’ve determined that the biggest sized item the generator can create will be roughly 2GenerationDepth times bigger than 1 chunk.

Demonstration: 1. Open a reset world. 2. Go to coordinates 0,0 and look towards east. 3. Go forward until you step on a new biome, then stop. 4. Note your coordinates which are at the limit between biomes (x or z should be 0). 5. Increase GenerationDepth by 1. Reset the world and open it again. 6. Repeat steps 2 to 5 as many times as desired.

These are the results I got :

GenerationDepth Distance
9 34
10 67
11 136
12 269

If you look well you may notice that the distance doubles when increasing GenerationDepth by 1. In every direction it’s the same pattern.

The following table is a direct consequence of that. With a biome taken from the first line, you can find biomes smaller than half a chunk because of other settings. I made it with a special biome with a very high BiomeHeight. It made it easier to spot while researching for GenerationDepth and other size variables.

Note that the same table can be used for BiomeSize and IceSize instead of LandSize .

Because the values in this table are theoretical, the size of biomes, land and iceland will differ from the values indicated here but a biome A with 1 more in BiomeSize than a biome B will always have approximately 4 times the surface of biome B. I have still to determine an acceptable margin of error for this ; until then it should be accepted as a good enough approximation that two biomes with the same size class have a surface ratio inferior to 4, and two biomes with 1 in size class difference should have a surface ratio between 2 and 8.


LandSize GD - LandSize Land size in chunks Land size in blocks
GD 0 1 16x16 = 256
GD-1 1 4 (not 2 because it’s a surface and 2*2=4) 32x32 = 1.024
GD-2 2 16 64x64 = 4.096
GD-3 3 64 128x128 = 16.384
GD-4 4 256 256x256 = 65.536
GD-5 5 1024 512x512 = 260.000
GD-6 6 4096 1024x1024 = 1.000.000
... ... ... ...
1 GD-1 4GD-1 2GD-1x2GD-1
0 GD 4GD 2GDx2GD

Recap :

  • GenerationDepth  : Largest possible size for an item.
  • GenerationDepth - Landsize : The bigger it is, the bigger the land size.
  • GenerationDepth - Icesize  : The bigger it is, the bigger the ice size.
  • GenerationDepth - BiomeSize  : The bigger it is, the bigger the biome size (not true for Isle Biomes).
  • A decrease of 1 in size class means a double size in blocks.

IceSize(冰面大小)以及Ice Biomes(冰雪生物群系)

回到顶部

IceSize is another type of landmass that will be filled only with the biomes listed in IceBiomes . It doesn’t force you to put snow biomes in there; nor will it make the biomes you put in the list snowy. It can be a handful workaround if you want two classes of biomes that don’t get mixed together. If I’m right, you could for instance have normal biomes and use IceBiomes to put a whole bunch of Nether-style biomes that will stick together in a large common area. This has to be investigated further, of course.

Border(边界生物群系)以及Isle Biomes(冰雪生物群系)

回到顶部

If you trust the previous chapter to add Border and Isle Biomes you will encounter several issues. On the bukkit dev forums, thedeadlytao had noticed there was a problem. This is an explanation for it.

A biome that is set as a border appears only in specific biomes, as indicated in the biome config file ( BiomeIsBorder ). When the generator reaches the size class of that border (reminder: the generator draws the biomes from the largest size class first, then goes more and more little until the smallest ones have been drawn), it proceeds to draw it within the boundaries of the biome of which it is the border, from the outside towards the center. The border size determines the distance from the edge to the center.

Please have a look here: http://i.imgur.com/inpf4.png. This picture summarizes pretty well how the border is painted in another biome. This also explains why the border size should not be too close to the inner biome size, else the inner biome will disappear completely. The Border BiomeSize should be between GenerationDepth and the inner biome’s BiomeSize value + 1. If you set the maximum possible value ( GenerationDepth ) the Border will be approximately one chunk width.

I tried several settings for BiomeRarity(生物群系稀有程度) on the border, but nothing happened. For now we’ll assume that BiomeRarity(生物群系稀有程度) has absolutely no effect on borders but I’ll explore this more in depth later if possible.

Something rather important to note is that the border makes the inner biome smaller, so you might want to make the biome bigger before putting a border in it.

Isle Biome: http://i.imgur.com/3DG10.png. Have first a look at the bottom of the picture (rarity 100). (please don’t pay attention to the blue biomes in this picture, they change because I was running several experiments at once but the relevant information here is given by the same colors as in the previous image, i.e. those colors:)

Isle Biomes work pretty much the same way as Border Biomes. The generator tries to find the outer limits of the isle biome by going from the edge of the outer biome towards its center. Then it paints the isle biome inside of the limit (instead of outside like it does for Border Biomes). There is an example showing it approximately with distance arrows at the bottom of the picture. All this leads to the fact that unlike other biomes, Isle Biome size increases with BiomeSize value.

If you set the maximum possible value ( GenerationDepth ) the remaining part of the outer biome will be a “border” of approximately one chunk width.

In fact, the boundary law for Borders and Isles is exactly the same. If you take a Biome A and put a Border B and an Isle C in it with BiomeSizeB = BiomeSizeC, Biome A will completely disappear under the two others.

BiomeRarity(生物群系稀有程度) has an influence on surface distribution here (see next chapter). Also, if there are several Isle Biomes in the same Biome, they will not compete in order to appear (contrary to normal biomes). My theory is that the generator will put the Isle Biome which ID is lowest first (Biome IDs are integers, indicated in WorldConfig.ini).

NotBorderNear is a list of biomes you don’t want the border biome to touch. It works only on border biomes, so there is no simple way to prevent two normal biomes to share a boundary.

BiomeRarity(生物群系稀有程度)

回到顶部 For normal Biomes: biomes of the same size class compete in order to appear on the map. Their BiomeRarity(生物群系稀有程度) value will be used to weigh their probability of appearance. The value for BiomeRarity(生物群系稀有程度) can go from 0 to BiomeRarity(生物群系稀有程度)Scale .

For Border Biomes: no effect. If several borders are set for the same biome, they will simply stack without overlapping. The first border drawn will be on the outside of the base biome, then the second one will be drawn on the outside of the remains of the base biome and so on. Their order is probably the same as their biomeID order.

For Isle Biomes: I generated several maps and used the ImageJ software with the 3D Color Inspector plugin in order to determine the surface distribution for each color. After eliminating the values for the other biomes represented in the map, these are my results (with the Border BiomeSize equal to GenerationDepth ):

Rarity Measured covered area Likely theoretical covered area
100 99% 100%
99 49% 50%
98 22.5% 25%
97 12% 12.5%

As you can see, every decrease of 1 point from 100 divides the surface distribution of the biome by 2. Unfortunately, BiomeRarity(生物群系稀有程度) must be an integer so it’s not possible to fine-tune it in order to have precise values such as 75% with just one biome.

There is a workaround for this, though. You can make a copy of the Isle biome file (with a different name, of course) with exactly the same settings except for BiomeRarity(生物群系稀有程度) . If for instance you want it to cover 75% of the area, give BiomeRarity(生物群系稀有程度) a value of 99 (50%) in the first Isle biome and 98 (25%) for the clone biome. Their total surface will be 50%+25% = 75%. (Not sure whether this works but it should).

Note: I am not sure yet whether LandRarity works the same way or not.

BiomeColor(生物群系颜色)

回到顶部 BiomeColor(生物群系颜色) is used when you make a map in FromImage mode. I’m not covering this part for now as mysource’s tutorials explain an acceptable part of it. Using FromImage is highly recommended when you create the settings for your biomes (as you won’t have to search for them). Nonetheless here is a link for hexadecimal colors in case you want to create a FromImage template: http://www.allprofitallfree.com/color-wheel2.html

RiverBiome(河流生物群系)

回到顶部 Pretty much straightforward. Specifies what biome is used as river in this biome. Leave blank to disable rivers in this biome.

BiomeTemperature(生物群系温度)以及BiomeWetness(生物群系湿润程度)

回到顶部 Those two variables alter the foliage and grass color through the biome diagram.

Low temperature values (like 0.15, I haven’t looked for the limit temperature as of yet) will make your biome a snow biome.

ReplaceToBiomeName(重命名生物群系)

回到顶部 This one is important. If you give your map to someone who doesn’t have TerrainControl, or if people on your server who don’t have TerrainControl, the biome will pretend to be one of the default biomes. The utility of this is mainly consistency with the colors of sky, water, foliage and grass.

BiomeHeight(生物群系高度)

回到顶部 Everything from BiomeVolatility to Volatility2 has value 0.0

VolatilityWeight1:0.5
VolatilityWeight2:0.45

BiomeHeight influences what will be the zero floor level for this biome. If the Biome is flat the main altitude will be determined by this variable.

Changes with BiomeHeight :


BiomeHeight Most represented block level
-4.0 <0
-3.62 3
-3.6 6
-3.5 10
-3.0 24
-2.001 60
-2.0 -∞ ?
-1.999 62
-1.99 62
-1.9 62
-1.8 66
-1.5 77
-1.0 94
0.0 128
1.0 161
2.0 193
3.0 227
3.5 240
3.62 247
4.0 255

This is only useful for relative altitude between biomes and according to the water level.

FractureHorizontal(横向裂面)以及 FractureVertical(纵向裂面)

回到顶部 Those two values appear in the WorldConfig.ini file. If you change them, they will have an effect on all the biomes.

BiomeVolatility(生物群系波动率)

回到顶部 Everything else from BiomeHeight to Volatility2 has value 0.0

VolatilityWeight1:0.5
VolatilityWeight2:0.45

Changes with BiomeVolatility :

BiomeVolatility Height amplitude
<-0.11 inverted world : air and land are swapped
-0.11 Ultra flat
-0.01 rather flat
0.0 almost flat
0.25 Hills reaching about +20
0.5 Hills reaching about +30
0.75 Hills reaching about +100
1.5 Extreme Hills
3.0 Ultra Hills
5.0 Liquid
10.0 Liquid

Note: BiomeVolatility seems to have no effect near the (0,0) coordinates for values near zero.

MaxAverageHeight(最大平均高度)以及MaxAverageDepth(最大平均深度)

回到顶部 MaxAverageHeight behaves like a multiplicator applied to the height levels only for the part of the map that is above BiomeHeight .

MaxAverageDepth is very similar to MaxAverageHeight except it works for slopes going down, i.e. the changes in altitude that go from BiomeHeight or any other lower value to any other lower value.

Example: with BiomeHeight:0.0 (block level about 128), MaxAverageDepth would concern slopes from 120 to 90, from 127 to 90, and from 87 to 20.

A slope that goes from 140 to 120 for instance is split into 2 slopes from 140 to 128 and 128 to 120. The first one will be concerned with MaxAverageHeight and the other with MaxAverageDepth .

In this graph, all slopes in green are considered going up and will be amplified or attenuated according to MaxAverageHeight . The blue ones are altered with MaxAverageDepth .

Important: MaxAverageHeight depends on BiomeVolatility . It works only when BiomeVolatility is not zero. Every other value from BiomeHeight to Volatility2 has value 0.0 except for BiomeVolatility:0.1 because 0.0 would cancel MaxAverageHeight ’s effect.

VolatilityWeight1:0.5
VolatilityWeight2:0.45

Changes with MaxAverageHeight :

MaxAverageHeight Block level reached by slopes
-50.0 42
-20.0 94
-10.0 108
-5.0 116
-1.0 128,calm
0.0 128
5.0 136
10.0 149
20.0 167
50.0 212

Also, it might be useful to note that MaxAverageHeight is a matter of height in a slope, not length. It means that if you take the same slope in a map generated with two different values of BiomeVolatility , the slope will grow in height, but not in length.

This means that the more you raise MaxAverageHeight , the more likely you will get cliffs in the terrain. In the same manner, raising MaxAverageDepth will eventually make pits in your terrain.

波动率1以及波动率2

回到顶部

Volatility1 and Volatility2 both depend on BiomeVolatility . They work only when BiomeVolatility is not zero (which probably means there’s a multiplicator somewhere, so a change in BiomeVolatility will probably create a big change in the effect of Volatility1/2 ). It’s difficult to describe in a few words so I’ll just let the tables explain for me.

Changes with Volatility1 :

Volatility1 Effect
<0 No effect
0.0 Normal
1.0 Terrain slopes are a little unpredictable, they can be gentle or rough and make cliffs. There can be hungover pieces of land.
10.0 Pieces of dirt in the air and rather flat ground areas. A very “liquid” look in some areas.
20.0 Some plains and then some holes and high mountains. Some of the mountains can go up to 200 blocks high. They are thick and rarely crossed by tunnels, but there can be bridges between them above 128 height.
100.0 Gives a system of very deep and high caves until height 128, from which you can find some plateaus. Where there are no plateaus, the floor can dive down to bedrock. Upwards there are extreme mountains pretty much looking like Skylands with shelves every 16 blocks down from top layer. But the most interesting is certainly the shards everywhere through the air. Give it a try, it’s worth looking.
500.0 Not so different from 100.0.

Changes with Volatility2 :

Volatility2 Effect
<0 No effect
0.0 Normal
1.0 Some hills
5.0 Some areas remain flat but some spots have become extreme. There are also rifts.
10.0 Still some flat areas. The extreme spots are even more extreme.
100.0 The terrain reaches layer 256 and can also go down to 0. The mountains are massive with a very liquid look and many galleries go through them but there still are some areas; it looks like Volatility2 doesn’t work everywhere. Unlike with Volatility1, there are no shards mid-air.
500.0 Not so different from 100.0.
CustomHeightControl(自定义高度控制)

回到顶部 CustomHeightControl is a tool for enabling/disabling some strata. On WorldHeightBits:8 , there are 33 strata which makes them roughly 7.7 blocks thick each (this raises a big question by the way: why not a whole number of blocks ?). The first number is for the lowest stratum and the last one is for the top one.

The comments in the file explain how it should be used pretty well so I’m just going to paraphrase them: positive values will increase the chance of block spawning and negative values will decrease it.

Like many other variables, this set of variables seems to act like a multiplicator. This one is very difficult to quantify and I have not thought of a method for this as of yet, so this is an example of one of my biomes called SkyDrops that uses CustomHeightControl : CustomHeightControl:

-100.0,-100.0,-200.0,-300.0,-400.0,-500.0,-500.0,-350.0,-200.0,-3000.0,-3000.0,-3000.0,-3000.0,-3000.0,-3000.0,-3000.0,-3000.0,-3000.0,-3000.0,-3000.0,-700.0,-600.0,-500.0,-400.0,-260.0,-210.0,-170.0,-120.0,-90.0,-60.0,-1500.0,-2000.0,-2000.0

There are many other settings that make SkyDrops a special biome but what CustomHeightControl does here is that it kills off every landmass in the strata that appear in red, while it gives shape to the strata in blue. Here is a scheme:

Keep in mind that the other values in my SkyDrops biome file are not default (it has a very high BiomeVolatility ). Of course, if I used negative values here but positive values would have added landmass instead of removing it.

I’m thinking that maybe a good way to comprehend CustomHeightControl is this: let’s say you have a column naturally formed in your terrain. Using positive CustomHeightControl values will make the column more fat, and negative values will make it thinner.

SurfaceBlock(表面方块)以及GroundBlock(基础方块)

回到顶部 Those values are meant to give the general appearance to your biome: use the block IDs for Surfaceblock and Groundblock . SurfaceBlock concerns the top layer of ground (generally grass) and 'GroundBlock gives value to the 3 (sometimes 4) block layers underneath it (generally dirt). Those variables cannot replace the stone underground; use ReplacedBlocks` instead.

UseWorldWaterLevel(使用水世界模式)

回到顶部 Determines whether this biome should be filled with water at WorldWaterLevel. If this is set to false, there will be water between WaterLevelMin and WaterLevelMax . In both cases, underground structures, caves and canyons will not be filled with water because they are dug into the terrain after terrain generation. Be careful: if two biomes that share a boundary that reaches below world water level and one of them has UseWorldWaterLevel set to true and the other biome has it set to false, you will have a wall of water at the boundary. This can be avoided by creating borders that will help for the transition.

ReplacedBlocks(替换方块)

回到顶部 ReplacedBlocks:(GRASS,DIRT,100,128),(GRAVEL,GLASS) means:

  • Between layers 100 and 127 included, replace all grass blocks to dirt blocks.
  • Replace all gravel blocks with glass blocks.

This is applied before resource generation, so if for instance you replace all stone with, say, dirt, you will have to change occurences of stone with dirt or the ores won’t be able to generate.

可见的生物群系设置

回到顶部 SkyColor , WaterColor , GrassColor and FoliageColor. These allow you to change the colors, like it says. Note that GrassColor and FoliageColor will override the grass and foliage colors that are normally determined by BiomeTemperature(生物群系温度)以及BiomeWetness(生物群系湿润程度). Here is a tool for converting colors into hexadecimal values: http://www.allprofitallfree.com/color-wheel2.html

赞助

回到顶部 mysource for the tutorials that helped me put the first toe in TerrainControl.