mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 00:26:39 +00:00 
			
		
		
		
	- very early version of the terrain engine, WORKING!
git-svn-id: https://openmw.svn.sourceforge.net/svnroot/openmw/trunk@125 ea6a568a-9f4f-0410-981a-c910a81bb256
This commit is contained in:
		
							parent
							
								
									367b9754b2
								
							
						
					
					
						commit
						393d284a8a
					
				
					 7 changed files with 297 additions and 139 deletions
				
			
		| 
						 | 
				
			
			@ -144,14 +144,6 @@ struct MeshInfo
 | 
			
		|||
    float *vbuf = vdest.ptr;
 | 
			
		||||
    assert(vdest.length == vertRows*vertCols*8);
 | 
			
		||||
 | 
			
		||||
    // Calculate the factor to multiply each height value with. The
 | 
			
		||||
    // heights are very limited in range as they are stored in a
 | 
			
		||||
    // single byte. Normal MW data uses a factor of 8, but we have to
 | 
			
		||||
    // double this for each successive level since we're splicing
 | 
			
		||||
    // several vertices together and need to allow larger differences
 | 
			
		||||
    // for each vertex. The formula is 8*2^(level-1).
 | 
			
		||||
    float scale = 4.0 * (1<<getLevel());
 | 
			
		||||
 | 
			
		||||
    // Merge the two data sets together into the output buffer.
 | 
			
		||||
    float offset = heightOffset;
 | 
			
		||||
    for(int y=0; y<vertRows; y++)
 | 
			
		||||
| 
						 | 
				
			
			@ -160,21 +152,21 @@ struct MeshInfo
 | 
			
		|||
        // height value. All the values in a row gives the height
 | 
			
		||||
        // relative to the previous value, and the first value in each
 | 
			
		||||
        // row is relative to the first value in the previous row.
 | 
			
		||||
        offset += *hmap;
 | 
			
		||||
        offset += *cast(short*)hmap;
 | 
			
		||||
 | 
			
		||||
        // This is the 'sliding offset' for this row. It's adjusted
 | 
			
		||||
        // for each vertex that's added, but only affects this row.
 | 
			
		||||
        float rowofs = offset;
 | 
			
		||||
        for(int x=0; x<vertCols; x++)
 | 
			
		||||
          {
 | 
			
		||||
            hmap++; // Skip the byte we just read
 | 
			
		||||
            hmap+=2; // Skip the height we just read
 | 
			
		||||
 | 
			
		||||
            // X and Y from the pregenerated buffer
 | 
			
		||||
            *vbuf++ = *gmap++;
 | 
			
		||||
            *vbuf++ = *gmap++;
 | 
			
		||||
 | 
			
		||||
            // The height is calculated from the current offset
 | 
			
		||||
            *vbuf++ = rowofs * scale;
 | 
			
		||||
            *vbuf++ = rowofs * 8;
 | 
			
		||||
 | 
			
		||||
            // Normal vector.
 | 
			
		||||
            *vbuf++ = *hmap++;
 | 
			
		||||
| 
						 | 
				
			
			@ -185,10 +177,9 @@ struct MeshInfo
 | 
			
		|||
            *vbuf++ = *gmap++;
 | 
			
		||||
            *vbuf++ = *gmap++;
 | 
			
		||||
 | 
			
		||||
            // Adjust the offset for the next vertex. On the last
 | 
			
		||||
            // iteration this will read past the current row, but
 | 
			
		||||
            // that's OK since rowofs is discarded afterwards.
 | 
			
		||||
            rowofs += *hmap;
 | 
			
		||||
            // Adjust the offset for the next vertex.
 | 
			
		||||
            if(x < vertCols-1)
 | 
			
		||||
              rowofs += *cast(short*)hmap;
 | 
			
		||||
          }
 | 
			
		||||
      }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -343,9 +334,20 @@ struct TerrainArchive
 | 
			
		|||
    ifile.readArray(indexBufData);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool hasQuad(int X, int Y, int level)
 | 
			
		||||
  {
 | 
			
		||||
    if((level in quadMap) is null ||
 | 
			
		||||
       (X in quadMap[level]) is null ||
 | 
			
		||||
       (Y in quadMap[level][X]) is null)
 | 
			
		||||
      return false;
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Get info about a given quad from the index.
 | 
			
		||||
  QuadInfo *getQuad(int X, int Y, int level)
 | 
			
		||||
  {
 | 
			
		||||
    assert(hasQuad(X,Y,level), format("Cannot find quad %s %s level %s",
 | 
			
		||||
                                      X, Y, level));
 | 
			
		||||
    int ind = quadMap[level][X][Y];
 | 
			
		||||
    QuadInfo *res = &quadList[ind];
 | 
			
		||||
    assert(res);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,7 +29,7 @@ public:
 | 
			
		|||
    float h = (p.y + 2048)*2.0/CELL_WIDTH;
 | 
			
		||||
    h *= h;
 | 
			
		||||
 | 
			
		||||
    mNode->setPosition(p.x, -p.z, -32 - h);
 | 
			
		||||
    mNode->setPosition(p.x, -p.z, -32 -h);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
| 
						 | 
				
			
			@ -55,16 +55,18 @@ private:
 | 
			
		|||
 | 
			
		||||
    vd = mMeshDistance;
 | 
			
		||||
 | 
			
		||||
    mObject->position(-vd,vd,-2048);
 | 
			
		||||
    const int HEIGHT = -2048 - 10;
 | 
			
		||||
 | 
			
		||||
    mObject->position(-vd,vd,HEIGHT);
 | 
			
		||||
    mObject->textureCoord(0, 1);
 | 
			
		||||
 | 
			
		||||
    mObject->position(-vd,-vd,-2048);
 | 
			
		||||
    mObject->position(-vd,-vd,HEIGHT);
 | 
			
		||||
    mObject->textureCoord(0, 0);
 | 
			
		||||
 | 
			
		||||
    mObject->position(vd,-vd,-2048);
 | 
			
		||||
    mObject->position(vd,-vd,HEIGHT);
 | 
			
		||||
    mObject->textureCoord(1, 0);
 | 
			
		||||
 | 
			
		||||
    mObject->position(vd,vd,-2048);
 | 
			
		||||
    mObject->position(vd,vd,HEIGHT);
 | 
			
		||||
    mObject->textureCoord(1, 1);
 | 
			
		||||
 | 
			
		||||
    mObject->quad(0,1,2,3);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -84,14 +84,26 @@ public:
 | 
			
		|||
    // Finally, create the material
 | 
			
		||||
    const std::string texName = info.getTexName();
 | 
			
		||||
 | 
			
		||||
    // Create or retrieve the material
 | 
			
		||||
    mMaterial = MaterialManager::getSingleton().createOrRetrieve
 | 
			
		||||
          (texName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME).first;
 | 
			
		||||
    // Set up the scene node.
 | 
			
		||||
    mNode = parent->createChildSceneNode();
 | 
			
		||||
    mNode->attachObject(this);
 | 
			
		||||
 | 
			
		||||
    // Finally, create or retrieve the material
 | 
			
		||||
    if(MaterialManager::getSingleton().resourceExists(texName))
 | 
			
		||||
      {
 | 
			
		||||
        mMaterial = MaterialManager::getSingleton().getByName
 | 
			
		||||
          (texName);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    // No existing material. Create a new one.
 | 
			
		||||
    mMaterial = MaterialManager::getSingleton().create
 | 
			
		||||
      (texName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
 | 
			
		||||
 | 
			
		||||
    Pass* pass = mMaterial->getTechnique(0)->getPass(0);
 | 
			
		||||
    pass->setLightingEnabled(false);
 | 
			
		||||
 | 
			
		||||
    if(level != 1)
 | 
			
		||||
    if(level > 1)
 | 
			
		||||
      {
 | 
			
		||||
        // This material just has a normal texture
 | 
			
		||||
        pass->createTextureUnitState(texName)
 | 
			
		||||
| 
						 | 
				
			
			@ -100,6 +112,8 @@ public:
 | 
			
		|||
      }
 | 
			
		||||
    else
 | 
			
		||||
      {
 | 
			
		||||
        assert(level == 1);
 | 
			
		||||
 | 
			
		||||
        // Get the background texture. TODO: We should get this from
 | 
			
		||||
        // somewhere, no file names should be hard coded. The texture
 | 
			
		||||
        // might exist as a .tga in earlier versions of the game, and
 | 
			
		||||
| 
						 | 
				
			
			@ -173,10 +187,6 @@ public:
 | 
			
		|||
            tus->setTextureScale(scale, scale);
 | 
			
		||||
          }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    // Finally, set up the scene node.
 | 
			
		||||
    mNode = parent->createChildSceneNode();
 | 
			
		||||
    mNode->attachObject(this);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ~TerrainMesh()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -275,7 +275,7 @@ extern "C"
 | 
			
		|||
      addResourceLocation("cache/terrain/", "FileSystem", "General");
 | 
			
		||||
 | 
			
		||||
    // Enter superman mode
 | 
			
		||||
    mCamera->setFarClipDistance(32*CELL_WIDTH);
 | 
			
		||||
    mCamera->setFarClipDistance(40*CELL_WIDTH);
 | 
			
		||||
    //ogre_setFog(0.7, 0.7, 0.7, 200, 32*CELL_WIDTH);
 | 
			
		||||
    d_terr_superman();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,7 @@ module terrain.generator;
 | 
			
		|||
 | 
			
		||||
import std.stdio;
 | 
			
		||||
import std.string;
 | 
			
		||||
 | 
			
		||||
import std.math2;
 | 
			
		||||
import std.c.string;
 | 
			
		||||
 | 
			
		||||
import terrain.cachewriter;
 | 
			
		||||
| 
						 | 
				
			
			@ -80,7 +80,7 @@ void generate(char[] filename)
 | 
			
		|||
  texSizes[5] = 512;
 | 
			
		||||
  texSizes[4] = 256;
 | 
			
		||||
  texSizes[3] = 256;
 | 
			
		||||
  texSizes[2] = 256;
 | 
			
		||||
  texSizes[2] = 512;
 | 
			
		||||
  texSizes[1] = 64;
 | 
			
		||||
 | 
			
		||||
  // Set some general parameters for the runtime
 | 
			
		||||
| 
						 | 
				
			
			@ -144,6 +144,20 @@ struct GenLevelResult
 | 
			
		|||
      quad.meshes[0].alphas[i].buffer = data[i*s..(i+1)*s];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Get the height offset
 | 
			
		||||
  float getHeight()
 | 
			
		||||
  {
 | 
			
		||||
    if(hasMesh)
 | 
			
		||||
      {
 | 
			
		||||
        assert(quad.meshes.length == 1);
 | 
			
		||||
        return quad.meshes[0].info.heightOffset;
 | 
			
		||||
      }
 | 
			
		||||
    else
 | 
			
		||||
      // The default mesh starts at 2048 = 256*8 units below water
 | 
			
		||||
      // level.
 | 
			
		||||
      return -256;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool isEmpty()
 | 
			
		||||
  {
 | 
			
		||||
    return (data.length == 0) && !hasMesh;
 | 
			
		||||
| 
						 | 
				
			
			@ -265,10 +279,8 @@ struct GenLevelResult
 | 
			
		|||
 | 
			
		||||
    mi.vertRows = size;
 | 
			
		||||
    mi.vertCols = size;
 | 
			
		||||
    // 1 height + 3 normal components = 4 bytes per vertex. The reader
 | 
			
		||||
    // algorithm (fillVertexBuffer) needs 1 extra byte so add that
 | 
			
		||||
    // too.
 | 
			
		||||
    mh.vertexBuffer = new byte[4*size*size+1];
 | 
			
		||||
    // 2 height bytes + 3 normal components = 5 bytes per vertex.
 | 
			
		||||
    mh.vertexBuffer = new byte[5*size*size];
 | 
			
		||||
 | 
			
		||||
    hasMesh = true;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -304,20 +316,7 @@ void genIndexData()
 | 
			
		|||
{
 | 
			
		||||
  scope auto _trc = new MTrace("genIndexData");
 | 
			
		||||
 | 
			
		||||
  // Generate mesh data for each level.
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
    TODO: The mesh data is very easy to generate, and we haven't
 | 
			
		||||
    really tested whether it's worth it to pregenerate it rather than
 | 
			
		||||
    to just calculate it at runtime. Unlike the index buffer below
 | 
			
		||||
    (which is just a memcpy at runtime, and definitely worth
 | 
			
		||||
    pregenerating), we have to loop through all the vertices at
 | 
			
		||||
    runtime anyway in order to splice this with the height data. It's
 | 
			
		||||
    possible that the additional memory use, pluss the slowdown
 | 
			
		||||
    (CPU-cache-wise) of reading from two buffers instead of one, makes
 | 
			
		||||
    it worthwhile to generate this data at runtime instead. However I
 | 
			
		||||
    guess the differences will be very small either way.
 | 
			
		||||
  */
 | 
			
		||||
  // FIXME: Do this at runtime.
 | 
			
		||||
  for(int lev=1; lev<=6; lev++)
 | 
			
		||||
    {
 | 
			
		||||
      // Make a new buffer to store the data
 | 
			
		||||
| 
						 | 
				
			
			@ -353,7 +352,7 @@ void genIndexData()
 | 
			
		|||
      cache.addVertexBuffer(lev,vertList);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  // Next up, triangle indices
 | 
			
		||||
  // Pregenerate triangle indices
 | 
			
		||||
  int size = 64*64*6;
 | 
			
		||||
  auto indList = new ushort[size];
 | 
			
		||||
  int index = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -531,8 +530,9 @@ void genLevel1Meshes(ref GenLevelResult res)
 | 
			
		|||
        // The vertex data from the ESM
 | 
			
		||||
        byte data = heightData[offs];
 | 
			
		||||
 | 
			
		||||
        // Write the height byte
 | 
			
		||||
        verts[index++] = data;
 | 
			
		||||
        // Write the height value as a short (2 bytes)
 | 
			
		||||
        *(cast(short*)&verts[index]) = data;
 | 
			
		||||
        index+=2;
 | 
			
		||||
 | 
			
		||||
        // Calculate the height here, even though we don't store
 | 
			
		||||
        // it. We use it to find the min and max values.
 | 
			
		||||
| 
						 | 
				
			
			@ -557,7 +557,7 @@ void genLevel1Meshes(ref GenLevelResult res)
 | 
			
		|||
      }
 | 
			
		||||
 | 
			
		||||
  // Make sure we wrote exactly the right amount of data
 | 
			
		||||
  assert(index == verts.length-1);
 | 
			
		||||
  assert(index == verts.length);
 | 
			
		||||
 | 
			
		||||
  // Store the min/max values
 | 
			
		||||
  mi.minHeight = min * 8;
 | 
			
		||||
| 
						 | 
				
			
			@ -864,111 +864,160 @@ void mergeMesh(GenLevelResult[] sub, ref GenLevelResult res)
 | 
			
		|||
  // level above the cell level.
 | 
			
		||||
  int shift = res.quad.info.level - 1;
 | 
			
		||||
  assert(shift >= 1);
 | 
			
		||||
 | 
			
		||||
  // Constants
 | 
			
		||||
  int intervals = 64;
 | 
			
		||||
  int vertNum = intervals+1;
 | 
			
		||||
  int vertSep = 128 << shift;
 | 
			
		||||
  assert(sub.length == 4);
 | 
			
		||||
 | 
			
		||||
  // Allocate the result buffer
 | 
			
		||||
  res.allocMesh(vertNum);
 | 
			
		||||
  res.allocMesh(65);
 | 
			
		||||
 | 
			
		||||
  MeshHolder *mh = &res.quad.meshes[0];
 | 
			
		||||
  MeshInfo *mi = &mh.info;
 | 
			
		||||
 | 
			
		||||
  // Basic info
 | 
			
		||||
  mi.worldWidth = vertSep*intervals;
 | 
			
		||||
  assert(mi.worldWidth == 8192<<shift);
 | 
			
		||||
  mi.worldWidth = 8192 << shift;
 | 
			
		||||
 | 
			
		||||
  // Get the height from the first cell
 | 
			
		||||
  float rowheight;
 | 
			
		||||
  if(sub[0].isEmpty())
 | 
			
		||||
    rowheight = 0.0;
 | 
			
		||||
  else
 | 
			
		||||
    rowheight = sub[0].quad.meshes[0].info.heightOffset;
 | 
			
		||||
  // Copy the mesh height from the top left mesh
 | 
			
		||||
  mi.heightOffset = sub[0].getHeight();
 | 
			
		||||
 | 
			
		||||
  // This is also the offset for the entire mesh
 | 
			
		||||
  mi.heightOffset = rowheight;
 | 
			
		||||
  // Output buffer
 | 
			
		||||
  byte verts[] = mh.vertexBuffer;
 | 
			
		||||
 | 
			
		||||
  // Just set bogus data for now
 | 
			
		||||
  int[] tmp = cast(int[])mh.vertexBuffer[0..$-1];
 | 
			
		||||
  tmp[] = 0x7f000000;
 | 
			
		||||
  float scale = 8.0 * (1<<shift);
 | 
			
		||||
  mi.minHeight = mi.maxHeight = mi.heightOffset * scale;
 | 
			
		||||
  return;
 | 
			
		||||
  // Bytes per vertex
 | 
			
		||||
  const int VSIZE = 5;
 | 
			
		||||
 | 
			
		||||
  byte *vertPtr = mh.vertexBuffer.ptr;
 | 
			
		||||
  // Used to calculate the max and min heights
 | 
			
		||||
  float minh = 300000.0;
 | 
			
		||||
  float maxh = -300000.0;
 | 
			
		||||
 | 
			
		||||
  // First off, rewrite this to use indices instead of pointers. It's
 | 
			
		||||
  // much safer and clearer.
 | 
			
		||||
 | 
			
		||||
  // Loop through each 'row' of submeshes
 | 
			
		||||
  for(int subY=0; subY<2; subY++)
 | 
			
		||||
  foreach(si, s; sub)
 | 
			
		||||
    {
 | 
			
		||||
      // Loop through each row of vertices
 | 
			
		||||
      for(int row=0; row<65; row++)
 | 
			
		||||
      int SX = si % 2;
 | 
			
		||||
      int SY = si / 2;
 | 
			
		||||
 | 
			
		||||
      // Find the offset in the destination buffer
 | 
			
		||||
      int dest = SX*32 + SY*65*32;
 | 
			
		||||
      dest *= VSIZE;
 | 
			
		||||
 | 
			
		||||
      void putValue(int val)
 | 
			
		||||
        {
 | 
			
		||||
          // FIXME: Ok, we have to skip each other row as well, of course.
 | 
			
		||||
          assert(val >= short.min && val <= short.max);
 | 
			
		||||
          *(cast(short*)&verts[dest]) = val;
 | 
			
		||||
          dest += 2;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
          // Loop through both sub meshes, left and right
 | 
			
		||||
          for(int subX=0; subX<2; subX++)
 | 
			
		||||
      if(s.hasMesh)
 | 
			
		||||
        {
 | 
			
		||||
          auto m = &s.quad.meshes[0];
 | 
			
		||||
          auto i = &m.info;
 | 
			
		||||
 | 
			
		||||
          minh = min(minh, i.minHeight);
 | 
			
		||||
          maxh = max(maxh, i.maxHeight);
 | 
			
		||||
 | 
			
		||||
          byte[] source = m.vertexBuffer;
 | 
			
		||||
          int src = 0;
 | 
			
		||||
 | 
			
		||||
          int getValue()
 | 
			
		||||
            {
 | 
			
		||||
              GenLevelResult *s = &sub[subX+2*subY];
 | 
			
		||||
              int s = *(cast(short*)&source[src]);
 | 
			
		||||
              src += 2;
 | 
			
		||||
              return s;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
              // Check if we have any data
 | 
			
		||||
              if(!s.isEmpty() && 0)
 | 
			
		||||
          // Loop through all the vertices in the mesh
 | 
			
		||||
          for(int y=0;y<33;y++)
 | 
			
		||||
            {
 | 
			
		||||
              // Skip the first row in the mesh if there was a mesh
 | 
			
		||||
              // above us. We assume that the previously written row
 | 
			
		||||
              // already has the correct information.
 | 
			
		||||
              if(y==0 && SY != 0)
 | 
			
		||||
                {
 | 
			
		||||
                  MeshHolder *smh = &s.quad.meshes[0];
 | 
			
		||||
                  byte* inPtr = smh.vertexBuffer.ptr;
 | 
			
		||||
 | 
			
		||||
                  // Loop through each vertex in this mesh. We skip two
 | 
			
		||||
                  // at a time.
 | 
			
		||||
                  for(int v=0; v<64; v+=2)
 | 
			
		||||
                    {
 | 
			
		||||
                      // Handle the v=0 case
 | 
			
		||||
 | 
			
		||||
                      // Count the height from the two next vertices
 | 
			
		||||
                      int data = *inPtr++;
 | 
			
		||||
                      inPtr++;inPtr++;inPtr++; // Skip the first normal
 | 
			
		||||
                      data += *inPtr++;
 | 
			
		||||
 | 
			
		||||
                      // Divide by two, since the result needs to fit in
 | 
			
		||||
                      // one byte. We compensate for this when we regen
 | 
			
		||||
                      // the mesh at runtime.
 | 
			
		||||
                      data >>= 1;
 | 
			
		||||
                      assert(data < 128 && data >= -128);
 | 
			
		||||
 | 
			
		||||
                      *vertPtr++ = data;
 | 
			
		||||
 | 
			
		||||
                      // Copy over the normal
 | 
			
		||||
                      *vertPtr++ = *inPtr++;
 | 
			
		||||
                      *vertPtr++ = *inPtr++;
 | 
			
		||||
                      *vertPtr++ = *inPtr++;
 | 
			
		||||
                    }
 | 
			
		||||
                  // Store the last one here. It _should_ be the
 | 
			
		||||
                  // same as the first in the next section, if
 | 
			
		||||
                  // present.
 | 
			
		||||
                  src += 65*VSIZE;
 | 
			
		||||
                  dest += 65*VSIZE;
 | 
			
		||||
                  continue;
 | 
			
		||||
                }
 | 
			
		||||
              else
 | 
			
		||||
 | 
			
		||||
              // Handle the first vertex of the row outside the
 | 
			
		||||
              // loop.
 | 
			
		||||
              int height = getValue();
 | 
			
		||||
 | 
			
		||||
              // If this isn't the very first row, sum up two row
 | 
			
		||||
              // heights and skip the first row.
 | 
			
		||||
              if(y!=0)
 | 
			
		||||
                {
 | 
			
		||||
                  // No data in this mesh. Just write zeros.
 | 
			
		||||
                  for(int v=0; v<32; v++)
 | 
			
		||||
                    {
 | 
			
		||||
                      // Height
 | 
			
		||||
                      *vertPtr++ = 0;
 | 
			
		||||
                  // Skip the rest of the row.
 | 
			
		||||
                  src += 64*VSIZE + 3;
 | 
			
		||||
 | 
			
		||||
                      // Normal, pointing straight upwards
 | 
			
		||||
                      *vertPtr++ = 0;
 | 
			
		||||
                      *vertPtr++ = 0;
 | 
			
		||||
                      *vertPtr++ = 0x7f;
 | 
			
		||||
                    }
 | 
			
		||||
                  // Add the second height
 | 
			
		||||
                  height += getValue();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              putValue(height);
 | 
			
		||||
 | 
			
		||||
              // Copy the normal
 | 
			
		||||
              verts[dest++] = source[src++];
 | 
			
		||||
              verts[dest++] = source[src++];
 | 
			
		||||
              verts[dest++] = source[src++];
 | 
			
		||||
 | 
			
		||||
              // Loop through the remaining 64 vertices in this row,
 | 
			
		||||
              // processing two at a time.
 | 
			
		||||
              for(int x=0;x<32;x++)
 | 
			
		||||
                {
 | 
			
		||||
                  height = getValue();
 | 
			
		||||
 | 
			
		||||
                  // Sum up the next two heights
 | 
			
		||||
                  src += 3; // Skip normal
 | 
			
		||||
                  height += getValue();
 | 
			
		||||
 | 
			
		||||
                  // Set the height
 | 
			
		||||
                  putValue(height);
 | 
			
		||||
 | 
			
		||||
                  // Copy the normal
 | 
			
		||||
                  verts[dest++] = source[src++];
 | 
			
		||||
                  verts[dest++] = source[src++];
 | 
			
		||||
                  verts[dest++] = source[src++];
 | 
			
		||||
                }
 | 
			
		||||
              // Skip to the next row
 | 
			
		||||
              dest += 32*VSIZE;
 | 
			
		||||
            }
 | 
			
		||||
          assert(src == source.length);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          minh = min(minh, -2048);
 | 
			
		||||
          maxh = max(maxh, -2048);
 | 
			
		||||
 | 
			
		||||
          // Set all the vertices to zero.
 | 
			
		||||
          for(int y=0;y<33;y++)
 | 
			
		||||
            {
 | 
			
		||||
              if(y==0 && SY != 0)
 | 
			
		||||
                {
 | 
			
		||||
                  dest += 65*VSIZE;
 | 
			
		||||
                  continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              for(int x=0;x<33;x++)
 | 
			
		||||
                {
 | 
			
		||||
                  if(x==0 && SX != 0)
 | 
			
		||||
                    {
 | 
			
		||||
                      dest += VSIZE;
 | 
			
		||||
                      continue;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                  // Zero height and vertical normal
 | 
			
		||||
                  verts[dest++] = 0;
 | 
			
		||||
                  verts[dest++] = 0;
 | 
			
		||||
                  verts[dest++] = 0;
 | 
			
		||||
                  verts[dest++] = 0;
 | 
			
		||||
                  verts[dest++] = 0x7f;
 | 
			
		||||
                }
 | 
			
		||||
              // Skip to the next row
 | 
			
		||||
              dest += 32*VSIZE;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  assert(vertPtr == mh.vertexBuffer.ptr + mh.vertexBuffer.length - 1);
 | 
			
		||||
 | 
			
		||||
  // Set max and min values here
 | 
			
		||||
  mi.minHeight = minh;
 | 
			
		||||
  mi.maxHeight = maxh;
 | 
			
		||||
  assert(minh <= maxh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------- OLD CODE - use these snippets later -------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										69
									
								
								terrain/myfile.d
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								terrain/myfile.d
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,69 @@
 | 
			
		|||
/*
 | 
			
		||||
  OpenMW - The completely unofficial reimplementation of Morrowind
 | 
			
		||||
  Copyright (C) 2009  Nicolay Korslund
 | 
			
		||||
  WWW: http://openmw.sourceforge.net/
 | 
			
		||||
 | 
			
		||||
  This file (archive.d) is part of the OpenMW package.
 | 
			
		||||
 | 
			
		||||
  OpenMW is distributed as free software: you can redistribute it
 | 
			
		||||
  and/or modify it under the terms of the GNU General Public License
 | 
			
		||||
  version 3, as published by the Free Software Foundation.
 | 
			
		||||
 | 
			
		||||
  This program is distributed in the hope that it will be useful, but
 | 
			
		||||
  WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
  General Public License for more details.
 | 
			
		||||
 | 
			
		||||
  You should have received a copy of the GNU General Public License
 | 
			
		||||
  version 3 along with this program. If not, see
 | 
			
		||||
  http://www.gnu.org/licenses/ .
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
import std.stream;
 | 
			
		||||
import std.stdio;
 | 
			
		||||
 | 
			
		||||
// Add a couple of helper functions to the file stream
 | 
			
		||||
class MyFile : File
 | 
			
		||||
{
 | 
			
		||||
  this(string filename, FileMode mode = FileMode.In)
 | 
			
		||||
    {
 | 
			
		||||
      super(filename, mode);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  void fill(T)(ref T t)
 | 
			
		||||
    {
 | 
			
		||||
      readExact(&t, T.sizeof);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  void dump(T)(ref T t)
 | 
			
		||||
    {
 | 
			
		||||
      writeExact(&t, T.sizeof);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  void fillArray(T)(T[] t)
 | 
			
		||||
    {
 | 
			
		||||
      readExact(t.ptr, t.length*T.sizeof);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  void dumpArray(T)(T[] t)
 | 
			
		||||
    {
 | 
			
		||||
      writeExact(t.ptr, t.length*T.sizeof);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  void readArray(T)(ref T[] arr)
 | 
			
		||||
    {
 | 
			
		||||
      int size;
 | 
			
		||||
      read(size);
 | 
			
		||||
      assert(size < 1024*1024 && size > 0);
 | 
			
		||||
      arr = new T[size];
 | 
			
		||||
      fillArray!(T)(arr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  void writeArray(T)(T[] t)
 | 
			
		||||
    {
 | 
			
		||||
      int size = t.length;
 | 
			
		||||
      write(size);
 | 
			
		||||
      dumpArray!(T)(t);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +31,8 @@ import std.file, std.stdio;
 | 
			
		|||
 | 
			
		||||
char[] cacheDir = "cache/terrain/";
 | 
			
		||||
 | 
			
		||||
// Enable this to render one single terrain mesh
 | 
			
		||||
// Enable this to render single terrain meshes instead of the entire
 | 
			
		||||
// data set
 | 
			
		||||
//debug=singleMesh;
 | 
			
		||||
 | 
			
		||||
void initTerrain(bool doGen)
 | 
			
		||||
| 
						 | 
				
			
			@ -55,12 +56,37 @@ void initTerrain(bool doGen)
 | 
			
		|||
 | 
			
		||||
  debug(singleMesh)
 | 
			
		||||
    {
 | 
			
		||||
      // Used for debugging single terrain meshes
 | 
			
		||||
      auto node = terr_createChildNode(20000,-60000,null);
 | 
			
		||||
      auto info = g_archive.getQuad(0,0,1);
 | 
			
		||||
      g_archive.mapQuad(info);
 | 
			
		||||
      auto mi = g_archive.getMeshInfo(0);
 | 
			
		||||
      auto m = terr_makeMesh(node, mi, info.level, TEX_SCALE);
 | 
			
		||||
      int X = 22;
 | 
			
		||||
      int Y = 0;
 | 
			
		||||
      bool next = false;
 | 
			
		||||
 | 
			
		||||
      void doQuad(int x, int y, int lev)
 | 
			
		||||
        {
 | 
			
		||||
          if(!g_archive.hasQuad(x,y,lev))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
          int diffx = x-X;
 | 
			
		||||
          int diffy = y-Y;
 | 
			
		||||
 | 
			
		||||
          diffx *= 8192;
 | 
			
		||||
          diffy *= 8192;
 | 
			
		||||
 | 
			
		||||
          if(diffx == 0 && lev == 2)
 | 
			
		||||
            diffx = 8192 * 2;
 | 
			
		||||
 | 
			
		||||
          auto node = terr_createChildNode(20000+diffx,-60000+diffy,null);
 | 
			
		||||
          auto info = g_archive.getQuad(x,y,lev);
 | 
			
		||||
          g_archive.mapQuad(info);
 | 
			
		||||
          auto mi = g_archive.getMeshInfo(0);
 | 
			
		||||
          terr_makeMesh(node, mi, info.level, TEX_SCALE);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      doQuad(X,Y,1);
 | 
			
		||||
      doQuad(X+1,Y,1);
 | 
			
		||||
      doQuad(X,Y+1,1);
 | 
			
		||||
      doQuad(X+1,Y+1,1);
 | 
			
		||||
 | 
			
		||||
      doQuad(X + (next?2:0),Y,2);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue