display.h

来自「一个纹理地形渲染器」· C头文件 代码 · 共 1,043 行 · 第 1/2 页

H
1,043
字号
			return (int) _lights.size();
		}

		virtual int numberOfTextureStages() const
		{
            // note: we currently only support a single texture stage

			return 1;
		}

		virtual void world(const Matrix &matrix)
		{
            D3DXMATRIX d3d_matrix = ConvertMatrix(matrix);
			if (_device->SetTransform(D3DTS_WORLD, &d3d_matrix) != D3D_OK) throw Error("set world transform failed");
		}

		virtual void view(const Matrix &matrix)
		{
            D3DXMATRIX d3d_matrix = ConvertMatrix(matrix);
			if (_device->SetTransform(D3DTS_VIEW, &d3d_matrix) != D3D_OK) throw Error("set view transform failed");
		}

		virtual void projection(const Matrix &matrix)
		{
            D3DXMATRIX d3d_matrix = ConvertMatrix(matrix);
			if (_device->SetTransform(D3DTS_PROJECTION, &d3d_matrix) != D3D_OK) throw Error("set projection transform failed");
		}
		
		virtual Matrix world() const
		{
			D3DXMATRIX matrix;
			if (_device->GetTransform(D3DTS_WORLD, &matrix) != D3D_OK) throw Error("get world transform failed");
			return ConvertMatrix(matrix);
		}

		virtual Matrix view() const
		{
			D3DXMATRIX matrix;
			if (_device->GetTransform(D3DTS_VIEW, &matrix) != D3D_OK) throw Error("get view transform failed");
			return ConvertMatrix(matrix);
		}

		virtual Matrix projection() const
		{
			D3DXMATRIX matrix;
			if (_device->GetTransform(D3DTS_PROJECTION, &matrix) != D3D_OK) throw Error("get projection transform failed");
			return ConvertMatrix(matrix);
		}
        
		virtual System::Texture* createTexture(const char name[])
		{
			Texture *texture = new Texture(_device, name);
			addObject(texture);
			return texture;
		}

		virtual System::Mesh* createMesh(const std::vector<System::Vertex> &vertex, const std::vector<int> &index)
		{
			Mesh *mesh = new Mesh(_device, vertex, index);
			addObject(mesh);
			return mesh;
		}

		virtual System::Light* createLight()
		{
			Light *light = new Light();
			addObject(light);
			return light;
		}

		virtual System::Material* createMaterial()
		{
			Material *material = new Material();
			addObject(material);
			return material;
		}

		virtual System::Timer* createTimer()
		{
			Timer *timer = new Timer();
			addObject(timer);
			return timer;
		}

        virtual void selectTexture(System::Texture *texture, int stage)
		{
			if (texture)
			{
				// select texture

				assert(!_texture);

				_texture = (Texture*) texture;
				_texture->reference();
                				
				if (_device->SetTexture(stage, _texture->handle()) != D3D_OK) throw Error("set texture failed");
			}
			else
			{
				// unselect texture

				assert(_texture);

				if (_device->SetTexture(stage, 0) != D3D_OK) throw Error("disable texture failed");

				_texture->release();
				_texture = 0;
			}
		}

		virtual void selectLight(System::Light *light, int index)
		{
            if (_wireframe)
                return;

			assert(index>=0);
			assert(index<numberOfLights());

			if (light)
			{
				// setup light
				
				assert(!_lights[index]);

				_lights[index] = (Light*) light; 
				_lights[index]->reference();

                D3DLIGHT9 d3d_light = _lights[index]->light();

				if (_device->SetLight(index, &d3d_light) != D3D_OK) throw Error("set light failed");
				
				if (_device->LightEnable(index, TRUE) != D3D_OK) throw Error("enable light failed");
			}
			else
			{
				// disable light

				assert(_lights[index]);

				if (_device->LightEnable(index, FALSE) != D3D_OK) throw Error("disable light failed");

				_lights[index]->release();
				_lights[index] = 0;
			}
		}

		virtual void selectMaterial(System::Material *material)
		{
			if (material)
			{
				// setup material

				assert(!_material);

				_material = (Material*) material;
				_material->reference();

                D3DMATERIAL9 d3d_material = _material->material();

                if (_wireframe)
                {
                    d3d_material.Ambient.r = 0.7f;
                    d3d_material.Ambient.g = 0.7f;
                    d3d_material.Ambient.b = 0.7f;
                    d3d_material.Ambient.a = 1;
                }

				if (_device->SetMaterial(&d3d_material) != D3D_OK)
                    throw Error("set material failed");
			}
			else
			{
				// unselect material

				assert(_material);

				_material->release();
				_material = 0;
			}
		}

		virtual void selectMesh(System::Mesh *mesh)
		{
			if (mesh)
			{
				// select mesh

				assert(!_mesh);

				_mesh = (Mesh*) mesh; 
				_mesh->reference();

				if (_device->SetStreamSource(0, _mesh->vertex_buffer(), 0, sizeof(Vertex)) != D3D_OK) throw Error("set stream source failed");

				if (_device->SetIndices(_mesh->index_buffer()) != D3D_OK) throw Error("set indices failed");
			}
			else
			{
				// clear mesh

				assert(_mesh);

				if (_device->SetStreamSource(0, 0, 0, 0) != D3D_OK) throw Error("set stream source failed");

				if (_device->SetIndices(0) != D3D_OK) throw Error("set indices failed");

				_mesh->release();
				_mesh = 0;
			}
		}

		virtual void renderMesh()
		{
			assert(_mesh);

	        // draw indexed primitive

			Mesh *directx_mesh = (Mesh*) _mesh; 

			if (_device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, directx_mesh->vertex_count(), 0, directx_mesh->triangle_count()) != D3D_OK) throw Error("draw indexed primitive failed");
		}

        virtual void blendMode(Blend::Mode mode)
        {
            switch (mode)
            {
                case Blend::NONE:
	                _device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
                    break;

                case Blend::MULTIPLY:
	                _device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
	                _device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR);
                    _device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
                    break;

                case Blend::ADD:
	                _device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
	                _device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
                    _device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
                    break;

                case Blend::ALPHA:
	                _device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
	                _device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCCOLOR);
                    _device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
                    break;
            }
        }

        virtual void cullMode(Cull::Mode mode)
        {
            switch (mode)
            {
                case Cull::NONE:
                    _device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
                    break;

                case Cull::CLOCKWISE:
                    _device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
                    break;

                case Cull::COUNTERCLOCKWISE:
                    _device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
                    break;
            }
        }
        
        virtual void depthTest(bool enabled)
        {
            if (enabled)
            {
                _device->SetRenderState(D3DRS_ZENABLE, TRUE);
                _device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
            }
            else
            {
                _device->SetRenderState(D3DRS_ZENABLE, FALSE);
                _device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
            }
        }

        void beginQuadStream()
        {
            _quadEmitter.begin();
			
            _device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
        }

        void renderQuad(const Vector vertex[])
        {
            Vector *quad = _quadEmitter.quad();
            quad[0] = vertex[0];
            quad[1] = vertex[1];
            quad[2] = vertex[2];
            quad[3] = vertex[3];
        }

        void endQuadStream()
        {
            _quadEmitter.end();

            _device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
        }

        void beginLineStream()
        {
            _lineEmitter.begin();
			
            _device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
        }

        void renderLine(const Vector &a, const Vector &b)
        {
            Vector *line = _lineEmitter.line();
            line[0] = a;
            line[1] = b;
        }

        void endLineStream()
        {
            _lineEmitter.end();

            _device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
        }

        bool loadHeightfield(const char filename[], std::vector<float> &data, int &width, int &height)
        {
	        // get image info

	        D3DXIMAGE_INFO info;

	        if (FAILED(D3DXGetImageInfoFromFile(filename, &info)))
		        return false;
        	
	        width = info.Width;
	        height = info.Height;

	        // validate image format is acceptable

	        int bits = 0;

	        switch (info.Format)
	        {
		        case D3DFMT_A8R8G8B8:
			        System::log("ARBG8888");
			        bits = 32;
			        break;

		        case D3DFMT_X8R8G8B8:
			        System::log("XRGB8888");
			        bits = 32;
			        break;

		        case D3DFMT_R8G8B8:
			        System::log("RGB888");
			        bits = 24;
			        break;

		        case D3DFMT_R5G6B5:
			        System::log("RGB565");
			        bits = 16;
			        break;

		        case D3DFMT_X1R5G5B5:
			        System::log("RGB555");
			        bits = 16;
			        break;

		        case D3DFMT_A8:
			        System::log("A8");
			        bits = 8;
			        break;

		        case D3DFMT_P8:
			        System::log("P8");
			        bits = 8;
			        break;

		        case D3DFMT_L8:
			        System::log("L8");
			        bits = 8;
			        break;

		        // unsupported pixel format!

		        default:
                    System::log("unsupport format!");
			        return false;
	        }

	        // i *hate* manipulating 24bit image data...

	        if (bits==24)
		        info.Format = D3DFMT_A8R8G8B8;

	        // create surface

	        LPDIRECT3DSURFACE9 surface = 0;
            
	        if (FAILED(_device->CreateOffscreenPlainSurface(width, height, info.Format, D3DPOOL_SCRATCH, &surface, 0)))
		        return false;

	        // load heightfield image to surface

	        HRESULT result = D3DXLoadSurfaceFromFile(surface, 0, 0, filename, 0, D3DX_FILTER_NONE, 0, &info);

	        if (result==D3DERR_INVALIDCALL) printf("invalid call\n");
	        else if (result==D3DXERR_INVALIDDATA) printf("invalid data\n");

	        if (FAILED(result))
	        {
		        surface->Release();
		        return false;
	        }

	        // process surface into heightfield float samples

	        D3DLOCKED_RECT rect;
	        if (FAILED(surface->LockRect(&rect, 0, D3DLOCK_READONLY)))
	        {
		        surface->Release();
		        return false;
	        }

	        data.resize(width*height);

	        const void *image = rect.pBits;
	        unsigned int pitch = rect.Pitch;

	        if (bits==32)
	        {
                System::log("32 bpp");

		        for (int y=0; y<height; y++)
		        {
			        const unsigned int *src = (const unsigned int*) (((const unsigned char*)image) + y*pitch);
			        float *dst = &data[0] + width*y;

			        for (int x=0; x<width; x++)
			        {
				        dst[x] = ((float)(src[x]&0x00FFFFFF)) * (1.0f / 16777215);
				        assert(dst[x]>=0);
				        assert(dst[x]<=1);
			        }
		        }
	        }
	        else if (bits==24)
	        {
		        // we actually load it into 32 bit for ease of manipulation, but the actual data is still 24 bit

                System::log("24 bpp");

		        for (int y=0; y<height; y++)
		        {
			        const unsigned int *src = (const unsigned int*) (((const unsigned char*)image) + y*pitch);
			        float *dst = &data[0] + width*y;

			        for (int x=0; x<width; x++)
			        {
				        dst[x] = ((float)(src[x]&0x00FFFFFF)) * (1.0f / 16777215);
				        assert(dst[x]>=0);
				        assert(dst[x]<=1);
			        }
		        }
	        }
	        else if (bits==16)
	        {
                System::log("16 bpp");

		        for (int y=0; y<height; y++)
		        {
			        const unsigned short *src = (const unsigned short*) (((const unsigned char*)image) + y*pitch);
			        float *dst = &data[0] + width*y;

			        for (int x=0; x<width; x++)
			        {
				        dst[x] = ((float)src[x]) * (1.0f / 65535);
				        assert(dst[x]>=0);
				        assert(dst[x]<=1);
			        }
		        }
	        }
	        else if (bits==8)
	        {
                System::log("8 bpp");

		        for (int y=0; y<height; y++)
		        {
			        const unsigned char *src = ((const unsigned char*)image) + y*pitch;
			        float *dst = &data[0] + width*y;

			        for (int x=0; x<width; x++)
			        {
				        dst[x] = ((float)src[x]) * (1.0f / 255);
				        assert(dst[x]>=0);
				        assert(dst[x]<=1);
			        }
		        }
	        }
	        else
	        {
                System::log("unknown bpp");

		        for (unsigned int i=0; i<data.size(); i++)
			        data[i] = 0.5f;
	        }

	        surface->UnlockRect();

	        // release surface

	        surface->Release();

	        // success

            return true;
        }
    };
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?