OpenGL 纹理[转]

OpenGL 纹理[转]

目录

OpenGL 纹理[转]

uv坐标

状态机


uv坐标

  • 图片左下角(0,0),图片右上角(1,1)
  • 把图像缩放到一单位大小,需要乘以图片长宽然后找到真正对应的像素坐标位置
  • 图像除以自己的宽高,进行映射
  • 参考:https://blog.csdn.net/wang15061955806/article/details/51000450
  • 要使用纹理映射,我们必须做以下三件事情:在OpenGL中装入纹理,为顶点提供纹理坐标(为了把纹理映射到顶点),用纹理坐标在纹理上执行一个采样操作,得到一个像素颜色。
  • 点信息
struct  Vertex
{
    int2    p0;
    float2  uv0;
    Rgba    c0;

    int2    p1;
    float2  uv1;
    Rgba    c1;

    int2    p2;
    float2  uv2;
    Rgba    c2;
};
  • 边信息(由两个点决定)
class   Ege
{
public:
    int     _x1;
    int     _y1;
    float2  _uv1;   
    Rgba    _color1;

    int     _x2;
    int     _y2;
    float2  _uv2;  
    Rgba    _color2;

    Ege(int x1,int y1,Rgba color1,float2 uv1,int x2,int y2,Rgba color2,float2 uv2)
    {
        if (y1 < y2)
        {
            _x1     =   x1;
            _y1     =   y1;
            _uv1    =   uv1;
            _color1 =   color1;

            _x2     =   x2;
            _y2     =   y2;
            _uv2    =   uv2;
            _color2 =   color2;
        }
        else
        {
            _x1     =   x2;
            _y1     =   y2;
            _uv1    =   uv2;
            _color1 =   color2;

            _x2     =   x1;
            _y2     =   y1;
            _uv2    =   uv1;
            _color2 =   color1;
        }
    }
};
  • 水平边信息(由两条边上的两个点决定)
class   Span
{
public:
    int     _xStart;
    int     _xEnd;

    Rgba    _colorStart;
    Rgba    _colorEnd;

    float2  _uvStart;
    float2  _uvEnd;

    int     _y;

public:
    Span(int xStart,int xEnd,int y,Rgba colorStart,Rgba colorEnd,float2 uvStart,float2 uvEnd)
    {
        if (xStart < xEnd)
        {
            _xStart     =   xStart;
            _xEnd       =   xEnd;
            _colorStart =   colorStart;
            _colorEnd   =   colorEnd;

            _uvStart    =   uvStart;
            _uvEnd      =   uvEnd;

            _y          =   y;
        }
        else
        {
            _xStart     =   xEnd;
            _xEnd       =   xStart;

            _colorStart =   colorEnd;
            _colorEnd   =   colorStart;

            _uvStart    =   uvEnd;
            _uvEnd      =   uvStart;
            _y          =   y;
        }
    }
};
  • 颜色插值,UV插值
inline  Rgba4Byte   colorLerp(const Rgba4Byte& c1, const Rgba4Byte& c2, float s)
{
    Rgba4Byte   color;

    color._r = (unsigned char)(c1._r + s * (c2._r - c1._r));
    color._g = (unsigned char)(c1._g + s * (c2._g - c1._g));
    color._b = (unsigned char)(c1._b + s * (c2._b - c1._b));
    color._a = (unsigned char)(c1._a + s * (c2._a - c1._a));
    return color;
}

inline  tvec2<float>   uvLerp(const tvec2<float>& c1, const tvec2<float>& c2, float s)
{
    tvec2<float>   color;
    color.x =   (c1.x + s * (c2.x - c1.x));
    color.y =   (c1.y + s * (c2.y - c1.y));
    return  color;
}
  • 设置和获取某像素点颜色
inline  void    setPixelEx(unsigned x, unsigned y, Rgba color)
{
	_buffer[y * _width + x] = color._color;
}

inline  Rgba    getPixel(unsigned x, unsigned y)
{
	return  Rgba(_buffer[y * _width + x]);
}
inline  void    setPixel(unsigned x, unsigned y, Rgba color)
{
	if (x >= _width || y >= _height)
	{
		return;
	}
	_buffer[y * _width + x] = color._color;
}
  • 根据UV获取对应图像像素点的颜色信息
Rgba    pixelUV(float u, float v)
{
	float x = u * _width;
	float y = v * _height;

	return  pixelAt(x, y);
}
  • 绘制水平图像数据(获取UV,UV就代表着图像上某个像素点的颜色信息)
void    drawSpan(const Span& span, Image* image)
{
	float   length = span._xEnd - span._xStart;
	float   scale = 0;
	float   step = 1.0f / length;
	for (int x = span._xStart; x < span._xEnd; ++x)
	{
		//Rgba    color   =   colorLerp(span._colorStart,span._colorEnd,scale);
		float2  uv = uvLerp(span._uvStart, span._uvEnd, scale);
		Rgba    color = image->pixelUV(uv.x, uv.y);
		scale += step;
		setPixel(x, span._y, color);
	}
}
  • 通过两条边绘制平面图像
void    drawEge(const Ege& e1, const Ege& e2, Image* image)
{
	float   yOffset1 = e1._y2 - e1._y1;
	if (yOffset1 == 0)
	{
		return;
	}

	float   yOffset = e2._y2 - e2._y1;
	if (yOffset == 0)
	{
		return;
	}
	float   xOffset = e2._x2 - e2._x1;
	float   scale = 0;
	float   step = 1.0f / yOffset;


	float   xOffset1 = e1._x2 - e1._x1;
	float   scale1 = (float)(e2._y1 - e1._y1) / yOffset1;
	float   step1 = 1.0f / yOffset1;

	for (int y = e2._y1; y < e2._y2; ++y)
	{
		int     x1 = e1._x1 + (int)(scale1 * xOffset1);
		int     x2 = e2._x1 + (int)(scale * xOffset);
		Rgba    color2 = colorLerp(e2._color1, e2._color2, scale);
		Rgba    color1 = colorLerp(e1._color1, e1._color2, scale1);

		float2  uvStart = uvLerp(e1._uv1, e1._uv2, scale1);
		float2  uvEnd = uvLerp(e2._uv1, e2._uv2, scale);

		Span    span(x1, x2, y, color1, color2, uvStart, uvEnd);
		drawSpan(span, image);

		scale += step;
		scale1 += step1;

	}
}
  • 根据定点绘制三角形
void    drawTriangle(const Vertex& vertex, Image* image)
{
	Ege eges[3] =
	{
		Ege(vertex.p0.x,vertex.p0.y,vertex.c0,  vertex.uv0, vertex.p1.x,vertex.p1.y,vertex.c1,  vertex.uv1),
		Ege(vertex.p1.x,vertex.p1.y,vertex.c1,  vertex.uv1, vertex.p2.x,vertex.p2.y,vertex.c2,  vertex.uv2),
		Ege(vertex.p2.x,vertex.p2.y,vertex.c2,  vertex.uv2, vertex.p0.x,vertex.p0.y,vertex.c0,  vertex.uv0),
	};
	int iMax = 0;
	int length = eges[0]._y2 - eges[0]._y1;

	for (int i = 1; i < 3; ++i)
	{
		int len = eges[i]._y2 - eges[i]._y1;
		if (len > length)
		{
			length = len;
			iMax = i;
		}
	}
	int iShort1 = (iMax + 1) % 3;
	int iShort2 = (iMax + 2) % 3;

	drawEge(eges[iMax], eges[iShort1], image);
	drawEge(eges[iMax], eges[iShort2], image);
}
  • 调用:
CELL::Raster::Vertex    vertex  =   
{
    CELL::int2(10,10),      CELL::float2(0.0f,0.0f), CELL::Rgba(),
    CELL::int2(10,110),     CELL::float2(0.0f,1.0f), CELL::Rgba(),
    CELL::int2(110,110),    CELL::float2(1.0f,1.0f), CELL::Rgba(),
};

CELL::Raster::Vertex    vertex1  =   
{
    CELL::int2(10,10),      CELL::float2(0.0f,0.0f), CELL::Rgba(),
    CELL::int2(110,110),    CELL::float2(1.0f,1.0f), CELL::Rgba(),
    CELL::int2(110,10),     CELL::float2(1.0f,0.0f), CELL::Rgba(),
};


raster.drawTriangle(vertex,image1);
raster.drawTriangle(vertex1,image1);
friend  Rgba4Byte    operator + (const Rgba4Byte& left,const Rgba4Byte& right)
{
    return  Rgba4Byte(left._r * right._r
                    ,left._g * right._g
                    ,left._b * right._b
                    ,left._a * right._a);
}
  • uv与颜色混合
void    drawSpan(const Span& span,Image* image)
{
    float   length  =   span._xEnd - span._xStart;
    float   scale   =   0;
    float   step    =   1.0f/length;
    for (int x = span._xStart ; x < span._xEnd; ++ x)
    {
        Rgba    color   =   colorLerp(span._colorStart,span._colorEnd,scale);
        float2  uv      =   uvLerp(span._uvStart,span._uvEnd,scale);
        Rgba    pixel   =   image->pixelUV(uv.x,uv.y);
        Rgba    dst     =   color + pixel;
        scale   +=  step;
        setPixel(x,span._y,dst);
    }
}

状态机

  • 应用:
  • 顶点信息:
struct  Vertex
{
    float       x,y;
    float       u,v;
    CELL::Rgba  color;
};
Vertex  vertexs[]   =   
{
    {10,    10,     0.0f,   0.0f,   CELL::Rgba(255,255,255,255)},
    {210,   210,    1.0f,   1.0f,   CELL::Rgba(255,255,255,255)},
    {210,   10,     1.0f,   0.0f,   CELL::Rgba(255,255,255,255)},

    {10,    10,     0.0f,   0.0f,   CELL::Rgba(255,255,255,255)},
    {210,   210,    1.0f,   1.0f,   CELL::Rgba(255,255,255,255)},
    {10,    210,    0.0f,   1.0f,   CELL::Rgba(255,255,255,255)},
};

//注意:偏移量 比如取当前顶点坐标xy,然后取下一个顶点坐标xy需要跨越多长数据大小
raster.vertexPointer(2,CELL::DT_FLOAT,      sizeof(Vertex),&vertexs[0].x);
raster.textureCoordPointer(2,CELL::DT_FLOAT,sizeof(Vertex),&vertexs[0].u);
raster.colorPointer(4,CELL::DT_BYTE,        sizeof(Vertex),&vertexs[0].color);

raster.drawArrays(CELL::DM_TRIANGES,0,6);  //注意是6个点
  • 数据类型定义
enum    DRAWMODE
{
	DM_POINTS = 0,
	DM_LINES = 1,
	DM_LINE_LOOP = 2,
	DM_LINE_STRIP = 3,
	DM_TRIANGES = 4,
};

enum    DATETYPE
{
	DT_BYTE,
	DT_FLOAT,
	DT_DOUBLE,
};

struct  DateElementDes
{
	int         _size;
	DATETYPE    _type;
	int         _stride;
	const void* _data;
};

  • 变量声明:
class   Raster
{
public:
	uint*   _buffer;
	int     _width;
	int     _height;
	Rgba    _color;

	Image*  _texture;        //纹理

	DateElementDes      _poitionPointer;  //记录当前状态信息
	DateElementDes      _colorPointer;
	DateElementDes      _uvPointer;
  
	DateElementDes      _defaultColorPointer; //默认值,防止空指针解引用
	DateElementDes      _defaultUVPointer;
	Rgba                _defaultColorArray[3];  //示例画三角形,,给三个
	float2              _detaultUVArray[3];
   //....
}
  • 变量初始化:
Raster::Raster( int w,int h,void* buffer )
{
    _texture        =   0;
    _width          =   w;
    _height         =   h;
    _buffer         =   (uint*)buffer;
    memset(&_poitionPointer,0,  sizeof(_poitionPointer));
    memset(&_colorPointer,  0,  sizeof(_colorPointer));
    memset(&_uvPointer,     0,  sizeof(_uvPointer));

    _defaultColorPointer._size  =   4;
    _defaultColorPointer._type  =   DT_BYTE;
    _defaultColorPointer._stride=   sizeof(Rgba);
    _defaultColorPointer._data  =   _defaultColorArray;

    _defaultUVPointer._size     =   2;
    _defaultUVPointer._type     =   DT_FLOAT;
    _defaultUVPointer._stride   =   sizeof(float2);
    _defaultUVPointer._data     =   _detaultUVArray;
}
  • 初始化或者更改状态:
void    vertexPointer(int size, DATETYPE type, int stride, const void* data)
{
	_poitionPointer._size = size;
	_poitionPointer._type = type;
	_poitionPointer._stride = stride;
	_poitionPointer._data = data;
}

void    colorPointer(int size, DATETYPE type, int stride, const void* data)
{
	_colorPointer._size = size;
	_colorPointer._type = type;
	_colorPointer._stride = stride;
	_colorPointer._data = data;
}

void    textureCoordPointer(int size, DATETYPE type, int stride, const void* data)
{
	_uvPointer._size = size;
	_uvPointer._type = type;
	_uvPointer._stride = stride;
	_uvPointer._data = data;
}
  • 绑定纹理
void    bindTexture(Image* image)
{
	_texture = image;
}
  • 注意,使用模运算,可使纹理重复
Rgba    pixelUV(float u,float v)
{
    float x   =   u * _width;
    float y   =   v * _height;

    return  pixelAt((unsigned)(x)%_width,(unsigned)(y)%_height);
}
  • 绘制三角形:
void    drawTrianle(Ege eges[3])
{
	int iMax = 0;
	int length = eges[0]._y2 - eges[0]._y1;

	for (int i = 1; i < 3; ++i)
	{
		int len = eges[i]._y2 - eges[i]._y1;
		if (len > length)
		{
			length = len;
			iMax = i;
		}
	}
	int iShort1 = (iMax + 1) % 3;
	int iShort2 = (iMax + 2) % 3;

	drawEge(eges[iMax], eges[iShort1], _texture);
	drawEge(eges[iMax], eges[iShort2], _texture);
}
  • 绘制顶点图形:
void    drawArrays(DRAWMODE pri, int start, int count)
{
	if (_poitionPointer._data == 0)
	{
		return;
	}

   //用户没给值 _colorPointer 保持原状态,后面使用临时变量
	DateElementDes  colorPointerdesc = _colorPointer;  
	DateElementDes  uvPointerdesc = _uvPointer;
	if (colorPointerdesc._data == 0)  //如果没有传值,就给默认值
	{
		colorPointerdesc = _defaultColorPointer;
	}
	if (uvPointerdesc._data == 0)    //如果没有传值,就给默认值
	{
		uvPointerdesc = _defaultUVPointer;
	}

	char*   posData = (char*)_poitionPointer._data;
	char*   cData = (char*)colorPointerdesc._data;
	char*   uvData = (char*)uvPointerdesc._data;

	for (int i = start; i < start + count; i += 3)  //每次画三个点
	{
		float*  fData = (float*)posData;
		int2    p0(fData[0], fData[1]);

		posData += _poitionPointer._stride;
		fData = (float*)(posData);
		int2    p1(fData[0], fData[1]);

		posData += _poitionPointer._stride;
		fData = (float*)(posData);
		int2    p2(fData[0], fData[1]);
		posData += _poitionPointer._stride;


		Rgba*   pColor = (Rgba*)cData;
		Rgba    c0(*pColor);
		cData += _colorPointer._stride;
		Rgba    c1(*pColor);
		cData += _colorPointer._stride;
		Rgba    c2(*pColor);
		cData += _colorPointer._stride;

		float*  pUV = (float*)uvData;
		float2  uv0(pUV[0], pUV[1]);
		uvData += _uvPointer._stride;
		pUV = (float*)uvData;
		float2  uv1(pUV[0], pUV[1]);
		uvData += _uvPointer._stride;
		pUV = (float*)uvData;
		float2  uv2(pUV[0], pUV[1]);
		uvData += _uvPointer._stride;


		Ege eges[3] =
		{
			Ege(p0.x,p0.y,c0,  uv0, p1.x,p1.y,c1,  uv1),
			Ege(p1.x,p1.y,c1,  uv1, p2.x,p2.y,c2,  uv2),
			Ege(p2.x,p2.y,c2,  uv2, p0.x,p0.y,c0,  uv0),
		};
		drawTrianle(eges);

		if (_colorPointer._data == 0)  //恢复,防止绘制多个三角形越界
		{
			cData = (char*)colorPointerdesc._data;
		}
		if (_uvPointer._data == 0)
		{

			uvData = (char*)uvPointerdesc._data;
		}
	}

}
  • 纹理滚动显示
static  float   step = 0;

//  Vertex  vertexs[] ={.......}

for (int i = 0 ;i < 6 ; ++ i )
{
    vertexs[i].v    +=  step;
}
  • 设置纹理贴图UV值大于1,边重复
Rgba    pixelUV(float u,float v)
{
    float x   =   u * _width;
    float y   =   v * _height;
    if (_wrapType == 0)
    {
        return  pixelAt((unsigned)(x)%_width,(unsigned)(y)%_height);
    }
    else
    {
        if (x >= _width)
        {
            x   =   _width - 1;
        }
        if (y >= _height)
        {
            y   =   _height - 1;
        }
        return  pixelAt(x,y);
    }
}
  • 矩阵:
template <typename T>
struct tmat3x3
    {
        typedef T               value_type;
        typedef std::size_t     size_type;
        typedef tvec3<T>        col_type;
        typedef tvec3<T>        row_type;
        typedef tmat3x3<T>      type;
        typedef tmat3x3<T>      transpose_type;


    private:
        // Data
        col_type value[3];

    public:
        size_type length() const
        {
            return 3;
        }
        size_type col_size()
        {
            return 3;
        }

        size_type row_size()
        {
            return 3;
        }

        tmat3x3()
        {
            value_type const Zero(0);
            value_type const One(1);
            this->value[0] = col_type(One, Zero, Zero);
            this->value[1] = col_type(Zero, One, Zero);
            this->value[2] = col_type(Zero, Zero, One);
        }

        tmat3x3
            (
            tmat3x3<T> const & m
            )
        {
            this->value[0] = m.value[0];
            this->value[1] = m.value[1];
            this->value[2] = m.value[2];
        }


        tmat3x3(value_type const & s)
        {
            value_type const Zero(0);
            this->value[0] = col_type(s, Zero, Zero);
            this->value[1] = col_type(Zero, s, Zero);
            this->value[2] = col_type(Zero, Zero, s);
        }


        tmat3x3
            (
            value_type const & x0, value_type const & y0, value_type const & z0,
            value_type const & x1, value_type const & y1, value_type const & z1,
            value_type const & x2, value_type const & y2, value_type const & z2
            )
        {
            this->value[0] = col_type(x0, y0, z0);
            this->value[1] = col_type(x1, y1, z1);
            this->value[2] = col_type(x2, y2, z2);
        }

        tmat3x3
            (
            col_type const & v0,
            col_type const & v1,
            col_type const & v2
            )
        {
            this->value[0] = v0;
            this->value[1] = v1;
            this->value[2] = v2;
        }

        template <typename U>
        tmat3x3(U const & s)
        {
            value_type const Zero(0);
            this->value[0] = tvec3<T>(value_type(s), Zero, Zero);
            this->value[1] = tvec3<T>(Zero, value_type(s), Zero);
            this->value[2] = tvec3<T>(Zero, Zero, value_type(s));
        }

        template <
            typename X1, typename Y1, typename Z1,
            typename X2, typename Y2, typename Z2,
            typename X3, typename Y3, typename Z3>
            tmat3x3
            (
            X1 const & x1, Y1 const & y1, Z1 const & z1,
            X2 const & x2, Y2 const & y2, Z2 const & z2,
            X3 const & x3, Y3 const & y3, Z3 const & z3
            )
        {
            this->value[0] = col_type(value_type(x1), value_type(y1), value_type(z1));
            this->value[1] = col_type(value_type(x2), value_type(y2), value_type(z2));
            this->value[2] = col_type(value_type(x3), value_type(y3), value_type(z3));
        }

        template <typename V1, typename V2, typename V3>
        tmat3x3
            (
            tvec3<V1> const & v1,
            tvec3<V2> const & v2,
            tvec3<V3> const & v3
            )
        {
            this->value[0] = col_type(v1);
            this->value[1] = col_type(v2);
            this->value[2] = col_type(v3);
        }

        template <typename U>
        tmat3x3(tmat3x3<U> const & m)
        {
            this->value[0] = col_type(m[0]);
            this->value[1] = col_type(m[1]);
            this->value[2] = col_type(m[2]);
        }



        tmat3x3<T> _inverse() const
        {
            T S00 = value[0][0];
            T S01 = value[0][1];
            T S02 = value[0][2];

            T S10 = value[1][0];
            T S11 = value[1][1];
            T S12 = value[1][2];

            T S20 = value[2][0];
            T S21 = value[2][1];
            T S22 = value[2][2];

            tmat3x3<T> Inverse(
                S11 * S22 - S21 * S12,
                S12 * S20 - S22 * S10,
                S10 * S21 - S20 * S11,
                S02 * S21 - S01 * S22,
                S00 * S22 - S02 * S20,
                S01 * S20 - S00 * S21,
                S12 * S01 - S11 * S02,
                S10 * S02 - S12 * S00,
                S11 * S00 - S10 * S01);

            T Determinant = S00 * (S11 * S22 - S21 * S12)
                - S10 * (S01 * S22 - S21 * S02)
                + S20 * (S01 * S12 - S11 * S02);

            Inverse /= Determinant;
            return Inverse;
        }

        col_type &  operator[](size_type i)
        {
            assert(i < this->length());
            return this->value[i];
        }

        col_type const & operator[](size_type i) const
        {
            assert(i < this->length());
            return this->value[i];
        }

        tmat3x3<T> & operator=(tmat3x3<T> const & m)
        {
            this->value[0] = m[0];
            this->value[1] = m[1];
            this->value[2] = m[2];
            return *this;
        }
        template <typename U>
        tmat3x3<T> & operator=(tmat3x3<U> const & m)
        {
            this->value[0] = m[0];
            this->value[1] = m[1];
            this->value[2] = m[2];
            return *this;
        }

        template <typename U>
        tmat3x3<T> & operator+= (U const & s)
        {
            this->value[0] += s;
            this->value[1] += s;
            this->value[2] += s;
            return *this;
        }

        template <typename U>
        tmat3x3<T> & operator+=(tmat3x3<U> const & m)
        {
            this->value[0] += m[0];
            this->value[1] += m[1];
            this->value[2] += m[2];
            return *this;
        }

        template <typename U>
        tmat3x3<T> & operator-= (U const & s)
        {
            this->value[0] -= s;
            this->value[1] -= s;
            this->value[2] -= s;
            return *this;
        }

        template <typename U>
        tmat3x3<T> & operator-= (tmat3x3<U> const & m)
        {
            this->value[0] -= m[0];
            this->value[1] -= m[1];
            this->value[2] -= m[2];
            return *this;
        }

        template <typename U>
        tmat3x3<T> & operator*= (U const & s)
        {
            this->value[0] *= s;
            this->value[1] *= s;
            this->value[2] *= s;
            return *this;
        }
        template <typename U>
        tmat3x3<T> & operator*= (tmat3x3<U> const & m)
        {
            return (*this = *this * m);
        }

        template <typename U>
        tmat3x3<T> & operator/= (U const & s)
        {
            this->value[0] /= s;
            this->value[1] /= s;
            this->value[2] /= s;
            return *this;
        }

        template <typename U>
        tmat3x3<T> & operator/= (tmat3x3<U> const & m)
        {
            return (*this = *this / m);
        }

        tmat3x3<T> & operator++ ()
        {
            ++this->value[0];
            ++this->value[1];
            ++this->value[2];
            return *this;
        }
        tmat3x3<T> & operator-- ()
        {
            --this->value[0];
            --this->value[1];
            --this->value[2];
            return *this;
        }

        tvec3<T> operator*(const tvec3<T> &v) const 
        {

            return  tvec3<T>( 
             value[0][0] * v[0] + value[1][0] * v[1] + value[2][0] * v[2]
            ,value[0][1] * v[0] + value[1][1] * v[1] + value[2][1] * v[2]
            ,value[0][2] * v[0] + value[1][2] * v[1] + value[2][2] * v[2]
            );
        }

        tvec2<T> operator*(const tvec2<T> &v) const 
        {
            return  tvec2<T>( 
                value[0][0] * v[0] + value[1][0] * v[1] + value[2][0]
            ,value[0][1] * v[0] + value[1][1] * v[1] + value[2][1]
            );
        }

        void scale(T x,T y)
        {
            this->value[0] = col_type(value_type(x), value_type(0), value_type(0));
            this->value[1] = col_type(value_type(0), value_type(y), value_type(0));
            this->value[2] = col_type(value_type(0), value_type(0), value_type(1));
        }
        void rotate(T angle) 
        {
            T   rad   =   DEG2RAD(angle);
            T   c     =   cos(rad);
            T   s     =   sin(rad);
            this->value[0] = col_type(value_type(c), value_type(-s), value_type(0));
            this->value[1] = col_type(value_type(s), value_type(c), value_type(0));
            this->value[2] = col_type(value_type(0), value_type(0), value_type(1));
        }
        void    translate(T x,T y)
        {
            this->value[0] = col_type(value_type(1), value_type(0), value_type(0));
            this->value[1] = col_type(value_type(0), value_type(1), value_type(0));
            this->value[2] = col_type(value_type(x), value_type(y), value_type(1));
        }
    };

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值