I'm Having a problem with my DirectX 9 Terrain Engine.. It's working fine, except for one thing, it doesn't load the heightmap in a proper way.
You can see a screenshot of the problem here: alt text http://img682.imageshack.us/img682/240/problemc.png
as you can see there is a diagonal crack through the entire map.. one side should be mirrored to render the map properly.
I'm almost sure the problem is not inside the file, as other programs don't seem to have a problem with it.
I'm loading my heightmap in this way (class header first):
class Terrain
{
public:
Terrain(const char* fileName);
~Terrain();
void Update(int x, int y);
void Render(LPDIRECT3DDEVICE9 Device);
private:
float* Data;
int Width;
int TileWidth;
bool isRendering;
bool isSwapping;
std::vector<Chunk*> RenderChunks;
};
and the constructor:
Terrain::Terrain(const char* fileName)
{
std::fstream File(fileName, std::ios::in | std::ios::binary);
File.seekg(0, std::ios::end);
int Length = File.tellg();
File.seekg(0, std::ios::beg);
int w = (int)sqrt((float)Length/4.0)-1;
Data = new float[Length / 4];
File.read((char*)Data, Length);
File.close();
Width = w;
int dataWidth = w+1;
TileWidth = w/16;
for (int y=0; y<TileWidth; y++)
{
for (int x=0; x<TileWidth; x++)
{
Chunk* c = new Chunk(x*16, y*16, 16, 512, Data);
RenderChunks.push_back(c);
}
}
}
Whenever I'm calling a height on the heightmap, i use it like this: Data[x + y*dataWidth] (just the usual way)
the Chunk class is a class that just renders a part of the heightmap, just so the detail decreases as the distance to the camera increaes.
So my question is: what could cause my problem?
EDIT: Rendering code:
void Terrain::Render(LPDIRECT3DDEVICE9 Device)
{
for (unsigned int i=0; i<RenderChunks.size(); ++i)
{
RenderChunks[i]->Render(Device);
}
}
Chunk::Chunk(int cX, int cY, int cW, int dW, float* Data):
Pos(cX, 0, cY)
{
Heights = new float[(cW + 1) * (cW + 1)];
ParentH = Data;
ParentOffset = cX + cY*dW;
ParentW = dW;
Width = cW + 1;
for (int y=0; y<Width; ++y)
{
memcpy(Heights + y*Width, Data + cX + (y+cY)*dW, sizeof(float)*Width);
}
Vertices = NULL;
Calculate(16, 16, 16, 16, 16);
}
void Chunk::Calculate(int L, int lod_L, int lod_R, int lod_U, int lod_D)
{
Detail = L;
if (Vertices) delete[] Vertices;
Vertices = new Vertex[(Width-1)*(Width-1)*6/(L*L)];
Count = (Width-1)*(Width-1)*2/(L*L);
float Height = 100.0f;
for (int y=0; y<Width-1; y += L)
{
for (int x=0; x<Width-1; x += L)
{
Vertex* thisQuad = Vertices + (y/L)*((Width-1)/L)*6 + (x/L)*6;
float heights[4] = {
Heights[(x ) + (y )*Width] * Height,
Heights[(x ) + (y + L)*Width] * Height,
Heights[(x + L) + (y )*Width] * Height,
Heights[(x + L) + (y + L)*Width] * Height};
float bonus[8] = {
heights[0],
heights[2],
heights[0],
heights[2],
heights[1],
heights[3],
heights[1],
heights[3]};
if (Pos.z + y > 0)
{
bonus[0] = ParentH[((int)Pos.x + x ) + ((int)Pos.z + y - L)*ParentW] * Height;
bonus[1] = ParentH[((int)Pos.x + x + L) + ((int)Pos.z + y - L)*ParentW] * Height;
}
if (Pos.x + x > 0)
{
bonus[2] = ParentH[((int)Pos.x + x - L) + ((int)Pos.z + y )*ParentW] * Height;
bonus[4] = ParentH[((int)Pos.x + x - L) + ((int)Pos.z + y + L)*ParentW] * Height;
}
if (Pos.x + x < ParentW-L-L)
{
bonus[3] = ParentH[((int)Pos.x + x+L+L) + ((int)Pos.z + y )*ParentW] * Height;
bonus[5] = ParentH[((int)Pos.x + x+L+L) + ((int)Pos.z + y + L)*ParentW] * Height;
}
if (Pos.z + y < ParentW-L-L)
{
bonus[6] = ParentH[((int)Pos.x + x ) + ((int)Pos.z + y+L+L)*ParentW] * Height;
bonus[7] = ParentH[((int)Pos.x + x + L) + ((int)Pos.z + y+L+L)*ParentW] * Height;
}
if (x == 0 && lod_L>L)
{
heights[0] = lerp(
Heights[(x ) + (((y )/lod_L)*lod_L )*Width],
Heights[(x ) + (((y )/lod_L)*lod_L + lod_L)*Width],
(float)((y ) % lod_L) / (float)lod_L) * Height;
heights[1] = lerp(
Heights[(x ) + (((y + L)/lod_L)*lod_L )*Width],
Heights[(x ) + (((y + L)/lod_L)*lod_L + lod_L)*Width],
(float)((y+L) % lod_L) / (float)lod_L) * Height;
}
if (x >= Width-2 && lod_R>L)
{
heights[2] = lerp(
Heights[(x + L) + (((y )/lod_R)*lod_R )*Width],
Heights[(x + L) + (((y )/lod_R)*lod_R + lod_R)*Width],
(float)((y ) % lod_R) / (float)lod_R) * Height;
heights[3] = lerp(
Heights[(x + L) + (((y + L)/lod_R)*lod_R )*Width],
Heights[(x + L) + (((y + L)/lod_R)*lod_R + lod_R)*Width],
(float)((y+L) % lod_R) / (float)lod_R) * Height;
}//*/
if (y == 0 && lod_U>L)
{
heights[0] = lerp(
Heights[(((x )/lod_U)*lod_U ) + (y )*Width],
Heights[(((x )/lod_U)*lod_U + lod_U) + (y )*Width],
(float)((x ) % lod_U) / (float)lod_U) * Height;
heights[2] = lerp(
Heights[(((x + L)/lod_U)*lod_U ) + (y )*Width],
Heights[(((x + L)/lod_U)*lod_U + lod_U) + (y )*Width],
(float)((x+L) % lod_U) / (float)lod_U) * Height;
}
if (y >= Width-2 && lod_D>L)
{
heights[1] = lerp(
Heights[(((x )/lod_D)*lod_D ) + (y + L)*Width],
Heights[(((x )/lod_D)*lod_D + lod_D) + (y + L)*Width],
(float)((x ) % lod_D) / (float)lod_D) * Height;
heights[3] = lerp(
Heights[(((x + L)/lod_D)*lod_D ) + (y + L)*Width],
Heights[(((x + L)/lod_D)*lod_D + lod_D) + (y + L)*Width],
(float)((x+L) % lod_D) / (float)lod_D) * Height;
}//*/
D3DXVECTOR3 fake(0,0,0);
Vertex p1(D3DXVECTOR3(x, heights[0], y ) + Pos, CalcNormal(bonus[2], heights[2], bonus[0], heights[1]));
Vertex p2(D3DXVECTOR3(x, heights[1], y + L) + Pos, CalcNormal(bonus[4], heights[3], heights[0], bonus[6]));
Vertex p3(D3DXVECTOR3(x + L, heights[2], y ) + Pos, CalcNormal(heights[0], bonus[3], bonus[1], heights[3]));
Vertex p4(D3DXVECTOR3(x + L, heights[3], y + L) + Pos, CalcNormal(heights[1], bonus[5], heights[2], bonus[7]));
thisQuad[0] = p1;
thisQuad[1] = p2;
thisQuad[2] = p3;
thisQuad[3] = p3;
thisQuad[4] = p2;
thisQuad[5] = p4;
}
}
}
void Chunk::Render(LPDIRECT3DDEVICE9 Device)
{
Device->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL);
Device->DrawPrimitiveUP(
D3DPT_TRIANGLELIST,
Count,
Vertices,
sizeof(Vertex));
}
I'm guessing your problem is that your chunk class takes a width (cW) and then you assign that value + 1 to the width. Im further assuming the cW is the number of texels in the heightmap(ie in a 1024x1024 heightmap cW is 1024). If thats right then by adding 1 each subseqent line will be offset to the left by 1. As you go on you make the problems worse so by 512 lines you'll be 512 to the left (or starting halfway across the texture). This would give you the diagonal shear you are seeing.
It seemed to be an "off by 1" error, but the post saying that seems to be deleted somehow..
it was the right solution anyway.
It looks a lot like the order in which you are building your triangle-strip(s) (or are you using another type of primitive?) has an issue. Can you post the relevant part of your rendering loop?
Edit: My intuition is that when you're mirroring your terrain data, you're creating criss-crossed geometry down the diagonal because the corners of your terrain quads (if you imagine them as such) are connecting to the corners diagonally across rather than directly across. I hope that some DirectX / rendering guru can give you a more precise answer based on the code you've posted.
Related
I have a requirement to implement the forward computing of deconv layer in the 3D filter manner.
Here, by '3D filter manner', I mean convolution like the Gaussian filter in CV. In the contrast, the caffe implements the deconv in the gemm + col2im manner.
I find a similar question here. The guy wrote the code according the introduction in tranposed conv.
Image
He/She does not open the source code. So I finished my own one:
template <typename DataType> int deconv_cpu(
DataType *src, DataType *dst, DataType *para, DataType *bias,
int in_width, int in_height, int in_channel,
int out_width, int out_height, int out_channel,
int ks, int padding = 0, int step = 1) { // step indicates the stride
int col, row, ch_o, ch_i, x, y;
int r = (ks - 1) / 2; //radius;
DataType result;
DataType *output;
DataType *filter;
DataType *input;
int sim_width, sim_height, sim_pad, width_border, height_border;
sim_width = in_width * step - step + 1;
sim_height = in_height * step - step + 1;
sim_pad = ks - padding - 1;
width_border = sim_pad == 0 ? r : 0;
height_border = sim_pad == 0 ? r : 0;
for (row = height_border; row < (sim_height - height_border); row++)
for (col = width_border; col < (sim_width - width_border); col++)
{
for (ch_o = 0; ch_o < out_channel; ch_o++)
{
output = dst + ch_o * out_width * out_height;
result = 0;
for (ch_i = 0; ch_i < in_channel; ch_i++)
{
filter = para + ks * ks * (in_channel * ch_o + ch_i);
//filter = para + ks*ks * (out_channel * ch_i + ch_o);
input = src + ch_i * in_width * in_height;
for (x = -r; x <= r; x++)
{
for (y = -r; y <= r; y++)
{
if ((row + x) >= 0 && (col + y) >= 0 && (row + x) < sim_height && (col + y) < sim_width)
{
if ( (row + x) % step != 0 || (col + y) % step != 0) continue;
result += input[(row + x) / step * in_width + (col + y) / step] * filter[(x + r) * ks + (y + r)];
}
}
}
}
if (bias != NULL) result = result + bias[ch_o];
output[(row - height_border) * out_width + (col - width_border)] = result;
}
}
return 0;
}
I compare the result with the caffe's one:
const caffe::vector<caffe::shared_ptr<caffe::Blob<float> > > blobs = layers[i]->blobs();
float *filter = blobs[0]->mutable_cpu_data();
float *bias = blobs[1]->mutable_cpu_data();
caffe::shared_ptr<caffe::Blob<float> > blob;
blob = caffe_net->blob_by_name(np.bottom(0));
deconv_cpu(blob->mutable_cpu_data(), dst, filter, bias, width1,
height1, c1, width2, height2, c2, ks, pad, stride);
blob = caffe_net->blob_by_name(np.top(0));
if(compare(dst, blob->mutable_cpu_data()) == 0) printf("match\n");
else printf("do not match\n");
However, the code does not give the same result with the caffe's implementation.
Do anyone know what is wrong? Or any advises or comment on the code?
This issue is finally fixed by change the filter index:
filter[(r-x) * ks + (r-y)]
I have this sample of code that I try to understand it:
__global__ void
d_boxfilter_rgba_x(unsigned int *od, int w, int h, int r)
{
float scale = 1.0f / (float)((r << 1) + 1);
unsigned int y = blockIdx.x*blockDim.x + threadIdx.x;
if (y < h)
{
float4 t = make_float4(0.0f);
for (int x = -r; x <= r; x++)
{
t += tex2D(rgbaTex, x, y);
}
od[y * w] = rgbaFloatToInt(t * scale);
for (int x = 1; x < w; x++)
{
t += tex2D(rgbaTex, x + r, y);
t -= tex2D(rgbaTex, x - r - 1, y);
od[y * w + x] = rgbaFloatToInt(t * scale);
}
}
}
__global__ void
d_boxfilter_rgba_y(unsigned int *id, unsigned int *od, int w, int h, int r)
{
unsigned int x = blockIdx.x*blockDim.x + threadIdx.x;
id = &id[x];
od = &od[x];
float scale = 1.0f / (float)((r << 1) + 1);
float4 t;
// partea din stanga
t = rgbaIntToFloat(id[0]) * r;
for (int y = 0; y < (r + 1); y++)
{
t += rgbaIntToFloat(id[y*w]);
}
od[0] = rgbaFloatToInt(t * scale);
for (int y = 1; y < (r + 1); y++)
{
t += rgbaIntToFloat(id[(y + r) * w]);
t -= rgbaIntToFloat(id[0]);
od[y * w] = rgbaFloatToInt(t * scale);
}
// main loop
for (int y = (r + 1); y < (h - r); y++)
{
t += rgbaIntToFloat(id[(y + r) * w]);
t -= rgbaIntToFloat(id[((y - r) * w) - w]);
od[y * w] = rgbaFloatToInt(t * scale);
}
// right side
for (int y = h - r; y < h; y++)
{
t += rgbaIntToFloat(id[(h - 1) * w]);
t -= rgbaIntToFloat(id[((y - r) * w) - w]);
od[y * w] = rgbaFloatToInt(t * scale);
}
}
This should be a box filter with CUDA.
From what I have read this should make an average with a given radius.
But in d_boxfilter_rgba_y make something like this:
od[0] = rgbaFloatToInt(t * scale);
I don't understand why is used this scale and why are made all that loops when there should be just one. To calculate the value from -r to +r and divide this by a number of pixels.
Can somebody help me?
To calculate the average of a box with radius 1 (3 values), you do:
(box[0] + box[1] + box[2]) / 3 // which is equal to
(box[0] + box[1] + box[2] * 1/3 // which is equal to your scale factor
The calculation of scale is:
1.0f / (float)((r << 1) + 1); // equal to
1 / ((r * 2) + 1) // equal to
1 / (2r + 1) // 2r because you go to the left and right and +1 for the middle
The two for loops are used, because the "sliding window" optimisation is used. First the first box is calculated:
for (int x = -r; x <= r; x++)
{
t += tex2D(rgbaTex, x, y);
}
And then for each step to the right, the value right of the box is added and the most left value of the box is removed. That way you can calculate the sum of the box with just 2 operations instead of 2*r + 1 operations.
for (int x = 1; x < w; x++)
{
t += tex2D(rgbaTex, x + r, y);
t -= tex2D(rgbaTex, x - r - 1, y);
od[y * w + x] = rgbaFloatToInt(t * scale);
}
}
I'm trying to update a 128x128 D3DLOCKED_RECT with sub images using the following code, but it seems to squish them down along the top, the X offset is ignored and the y offset is 60 percent off.
I've also tried to make the texture the correct size and copy it into a 128x128 texture at the correct location using RECT, however this is very slow and didn't seem to work correctly when I attempted it. There must be way to do it using the raw pixel data?
Any help would be much appreciated :)
EDIT: I got it semi working using the below code, the locations are now correct and the sizes. But it's only using the blue channel and everything is grey scale (blue scale?)
srcdata = (byte *) pixels;
dstdata = (unsigned int *)lockrect.pBits;
for (y = yoffset; y < (yoffset + height); y++)
{
for (x = xoffset; x < (xoffset + width); x++)
{
dstdata[ ( y * lockrect.Pitch / dstbytes + x ) + 0] = (unsigned int)srcdata[0];
dstdata[ ( y * lockrect.Pitch / dstbytes + x ) + 1] = (unsigned int)srcdata[1];
dstdata[ ( y * lockrect.Pitch / dstbytes + x ) + 2] = (unsigned int)srcdata[0];
dstdata[ ( y * lockrect.Pitch / dstbytes + x ) + 3] = (unsigned int)srcdata[3];
srcdata += srcbytes;
}
}'
END Edit
Test call after creating the 128x128 texture:
int x, y;
byte temp[132*132*4];
// Test texture (pink and black checker)
for( y = 0; y < 16; y++ )
{
for( x = 0; x < 16; x++ )
{
if(( y < 8 ) ^ ( x < 8 ))
((uint *)&temp)[y*16+x] = 0xFFFF00FF;
else ((uint *)&temp)[y*16+x] = 0xFF000000;
}
}
UpdateSubImage (0, 0, 16, 16, temp )
The update Fuction:
void UpdateSubImage (int xoffset, int yoffset, int width, int height, const
GLvoid *pixels)
{
int x, y;
int srcbytes = 4; //Hard coded for now, as all tests are RGBA
int dstbytes = 4; // ^
byte *srcdata;
byte *dstdata;
D3DLOCKED_RECT lockrect;
pTexture->LockRect( 0, &lockrect, NULL, 0);
srcdata = (byte *) pixels;
dstdata = (byte *) lockrect.pBits;
dstdata += (yoffset * width + xoffset) * dstbytes;
for (y = yoffset; y < (yoffset + height); y++)
{
for (x = xoffset; x < (xoffset + width); x++)
{
if (srcbytes == 1)
{
if (dstbytes == 1)
dstdata[0] = srcdata[0];
else if (dstbytes == 4)
{
dstdata[0] = srcdata[0];
dstdata[1] = srcdata[0];
dstdata[2] = srcdata[0];
dstdata[3] = srcdata[0];
}
}
else if (srcbytes == 3)
{
if (dstbytes == 1)
dstdata[0] = ((int) srcdata[0] + (int) srcdata[1] + (int) srcdata[2]) / 3;
else if (dstbytes == 4)
{
dstdata[0] = srcdata[2];
dstdata[1] = srcdata[1];
dstdata[2] = srcdata[0];
dstdata[3] = 255;
}
}
else if (srcbytes == 4)
{
if (dstbytes == 1)
dstdata[0] = ((int) srcdata[0] + (int) srcdata[1] + (int) srcdata[2]) / 3;
else if (dstbytes == 4)
{
dstdata[0] = srcdata[2];
dstdata[1] = srcdata[1];
dstdata[2] = srcdata[0];
dstdata[3] = srcdata[3];
}
}
// advance
srcdata += srcbytes;
dstdata += dstbytes;
}
}
pTexture->UnlockRect(0);
}
What the output looks like:
What the output should look like:
You're assuming that the data accessable through lockrect.pBits is linear in memory. This is in general not the case. Instead you have a constant offset between your rows which is defined by the lockrect.Pitch value.
To get the address of a pixel in the destination use:
byte * destAddr = (lockrect.pBits + y * lockrect.Pitch + 4 * x);
// for 32 bit images. For other formats adjust the hard-coded 4.
Thanks for the help :), in the end the following code worked:
Can it be made faster?
for (y = yoffset; y < (yoffset + height); y++)
{
for (x = xoffset; x < (xoffset + width); x++)
{
ARGB pixel;
pixel.r = srcdata[0];
pixel.g = srcdata[1];
pixel.b = srcdata[2];
pixel.a = srcdata[3];
memcpy( &dstdata[lockrect.Pitch * y + dstbytes * x], &pixel, dstbytes );
srcdata += srcbytes;
}
}
Currently, I'm trying to make a noise generated heightmap and display it with opengl. I'm following this tutorial, but my heightmap doesn't seem to work. It seems like it generates (or displays) only half of what it is supposed to.
This is the heightmap with normals for color:
As you can see, even though this is supposed to be a square, it appears rectangular with an unfinished edge.
This is my heightmap generation code:
public class HeightMap extends GameModel {
private static final float START_X = -0.5f;
private static final float START_Z = -0.5f;
public HeightMap(float minY, float maxY, float persistence, int width, int height) {
super(createMesh(minY, maxY, persistence, width, height));
}
protected static Mesh createMesh(final float minY, final float maxY, final float persistence, final int width,
final int height) {
SimplexNoise noise = new SimplexNoise(128, persistence, 2);// Utils.getRandom().nextInt());
float xStep = Math.abs(START_X * 2) / width;
float zStep = Math.abs(START_Z * 2) / height;
List<Float> positions = new ArrayList<>();
List<Integer> indices = new ArrayList<>();
for (int x = 0; x < width; x++) {
for (int z = 0; z < height; z++) {
// scale from [-0.5, 0.5] to [minY, maxY]
float heightY = (float) ((noise.getNoise(x, z) + 0.5f) * (maxY - minY) + minY);
positions.add(START_X + x * xStep);
positions.add(heightY);
positions.add(START_Z + z * zStep);
// Create indices
if (x < width - 1 && z < height - 1) {
int leftTop = z * width + x;
int leftBottom = (z + 1) * width + x;
int rightBottom = (z + 1) * width + x + 1;
int rightTop = z * width + x + 1;
indices.add(leftTop);
indices.add(leftBottom);
indices.add(rightTop);
indices.add(rightTop);
indices.add(leftBottom);
indices.add(rightBottom);
}
}
}
float[] verticesArr = Utils.listToArray(positions);
float[] colorArr = new float[positions.size()];
for (int i = 0; i < colorArr.length; i += 3) {
colorArr[i] = (float) i / colorArr.length;
colorArr[i + 1] = (float) .25f;
colorArr[i + 2] = (float) 0;
}
int[] indicesArr = indices.stream().mapToInt((i) -> i).toArray();
float[] normalArr = calcNormals(verticesArr, width, height);
return new Mesh(verticesArr, colorArr, normalArr, indicesArr);
}
private static float[] calcNormals(float[] posArr, int width, int height) {
Vector3f v0 = new Vector3f();
Vector3f v1 = new Vector3f();
Vector3f v2 = new Vector3f();
Vector3f v3 = new Vector3f();
Vector3f v4 = new Vector3f();
Vector3f v12 = new Vector3f();
Vector3f v23 = new Vector3f();
Vector3f v34 = new Vector3f();
Vector3f v41 = new Vector3f();
List<Float> normals = new ArrayList<>();
Vector3f normal = new Vector3f();
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
if (row > 0 && row < height - 1 && col > 0 && col < width - 1) {
int i0 = row * width * 3 + col * 3;
v0.x = posArr[i0];
v0.y = posArr[i0 + 1];
v0.z = posArr[i0 + 2];
int i1 = row * width * 3 + (col - 1) * 3;
v1.x = posArr[i1];
v1.y = posArr[i1 + 1];
v1.z = posArr[i1 + 2];
v1 = v1.sub(v0);
int i2 = (row + 1) * width * 3 + col * 3;
v2.x = posArr[i2];
v2.y = posArr[i2 + 1];
v2.z = posArr[i2 + 2];
v2 = v2.sub(v0);
int i3 = (row) * width * 3 + (col + 1) * 3;
v3.x = posArr[i3];
v3.y = posArr[i3 + 1];
v3.z = posArr[i3 + 2];
v3 = v3.sub(v0);
int i4 = (row - 1) * width * 3 + col * 3;
v4.x = posArr[i4];
v4.y = posArr[i4 + 1];
v4.z = posArr[i4 + 2];
v4 = v4.sub(v0);
v1.cross(v2, v12);
v12.normalize();
v2.cross(v3, v23);
v23.normalize();
v3.cross(v4, v34);
v34.normalize();
v4.cross(v1, v41);
v41.normalize();
normal = v12.add(v23).add(v34).add(v41);
normal.normalize();
} else {
normal.x = 0;
normal.y = 1;
normal.z = 0;
}
normal.normalize();
normals.add(normal.x);
normals.add(normal.y);
normals.add(normal.z);
}
}
return Utils.listToArray(normals);
}
}
Wild guess: You're using 16bit indices but specify the size of the index buffer as if it were 8bit indices (by setting the size of the buffer to number of elements in the buffer)?
Judging from the screenshot, it clearly looks like only the first half is drawn, so I would assume the problem lies in the creation of the index buffer or the draw call.
Maybe you used the wrong number of indices in the draw call? Like you used the number of triangles instead? Or assumes the number for a triangle fan instead of triangles?
You'll have to post the actual draw call and generation of the buffer objects to get more information.
Or at least tag your question according to the rendering library you are using, as it is not plain OpenGL.
I have some Irrlicht code that generates a rectangular mesh given a width and height. Here is the code that generates the vertices and indices:
int iNumVertices = (width + 1) * (height + 1);
S3DVertex * vertices = new S3DVertex[iNumVertices];
memset(vertices,0,sizeof(S3DVertex) * iNumVertices);
for(int i=0;i<=height;++i)
{
for(int j=0;j<=width;++j)
{
int iIndex = (i*(width + 1)) + j;
vertices[iIndex].Pos.X = i * 2.0f;
vertices[iIndex].Pos.Y = 0.0f;
vertices[iIndex].Pos.Z = j * 2.0f;
vertices[iIndex].Color.color = 0xFFFFFFFF;
vertices[iIndex].TCoords.X = i;
vertices[iIndex].TCoords.Y = j;
}
}
int iNumIndices = 6 * width * height;
u16 * indices = new u16[iNumIndices];
for(int i=0;i<height;++i)
{
for(int j=0;j<width;++j)
{
int iIndex = ((i*width) + j) * 6;
int tmp_offset = j + (i * (width + 1));
indices[iIndex + 0] = tmp_offset + 1;
indices[iIndex + 1] = tmp_offset + width + 1;
indices[iIndex + 2] = tmp_offset;
indices[iIndex + 3] = tmp_offset + 1;
indices[iIndex + 4] = tmp_offset + width + 2;
indices[iIndex + 5] = tmp_offset + width + 1;
}
}
Then the vertices and indices are added to the mesh and the bounding box is recalculated:
SMeshBuffer * buffer = new SMeshBuffer();
buffer->append(vertices,iNumVertices,indices,iNumIndices);
buffer->recalculateBoundingBox();
However, when rendered, the bounding box is nowhere close to the right size:
The end result of this is that the mesh doesn't get rendered when the small bounding box goes behind the camera.
Turns out that the problem was that I was calling recalculateBoundingBox() on the buffer instead of the mesh.