mirror of
https://github.com/bulletphysics/bullet3.git
synced 2026-09-09 11:58:53 +00:00
TinyRenderer: support plane shape (creating similar textured plane to OpenGL renderer)
TinyRenderer: perform clipping in double precision to improve accuracy
This commit is contained in:
@@ -66,6 +66,8 @@ struct TinyRendererVisualShapeConverterInternalData
|
||||
// Maps bodyUniqueId to a list of visual shapes belonging to the body.
|
||||
btHashMap<btHashInt, btAlignedObjectArray<b3VisualShapeData> > m_visualShapesMap;
|
||||
|
||||
btAlignedObjectArray<unsigned char> m_checkeredTexels;
|
||||
|
||||
int m_uidGenerator;
|
||||
int m_upAxis;
|
||||
int m_swWidth;
|
||||
@@ -560,10 +562,61 @@ static void convertURDFToVisualShape(const UrdfShape* visual, const char* urdfPa
|
||||
} // case mesh
|
||||
|
||||
case URDF_GEOM_PLANE:
|
||||
// TODO: plane in tiny renderer
|
||||
// TODO: export visualShapeOut for external render
|
||||
break;
|
||||
{
|
||||
glmesh = new GLInstanceGraphicsShape;
|
||||
// int index = 0;
|
||||
glmesh->m_indices = new b3AlignedObjectArray<int>();
|
||||
glmesh->m_vertices = new b3AlignedObjectArray<GLInstanceVertex>();
|
||||
glmesh->m_indices->push_back(0);
|
||||
glmesh->m_indices->push_back(1);
|
||||
glmesh->m_indices->push_back(2);
|
||||
glmesh->m_indices->push_back(0);
|
||||
glmesh->m_indices->push_back(2);
|
||||
glmesh->m_indices->push_back(3);
|
||||
glmesh->m_scaling[0] = 1;
|
||||
glmesh->m_scaling[1] = 1;
|
||||
glmesh->m_scaling[2] = 1;
|
||||
glmesh->m_scaling[3] = 1;
|
||||
|
||||
btScalar planeConst = 0;
|
||||
btVector3 planeNormal = visual->m_geometry.m_planeNormal;
|
||||
btVector3 planeOrigin = planeNormal * planeConst;
|
||||
btVector3 vec0, vec1;
|
||||
btPlaneSpace1(planeNormal, vec0, vec1);
|
||||
|
||||
btScalar vecLen = 128;
|
||||
btVector3 verts[4];
|
||||
|
||||
verts[0] = planeOrigin + vec0 * vecLen + vec1 * vecLen;
|
||||
verts[1] = planeOrigin - vec0 * vecLen + vec1 * vecLen;
|
||||
verts[2] = planeOrigin - vec0 * vecLen - vec1 * vecLen;
|
||||
verts[3] = planeOrigin + vec0 * vecLen - vec1 * vecLen;
|
||||
|
||||
GLInstanceVertex vtx;
|
||||
vtx.xyzw[0] = verts[0][0]; vtx.xyzw[1] = verts[0][1]; vtx.xyzw[2] = 0; vtx.xyzw[3] = 0;
|
||||
vtx.normal[0] = 0; vtx.normal[1] = 0; vtx.normal[2] = 1;
|
||||
vtx.uv[0] = vecLen; vtx.uv[1] = vecLen;
|
||||
glmesh->m_vertices->push_back(vtx);
|
||||
|
||||
vtx.xyzw[0] = verts[1][0]; vtx.xyzw[1] = verts[1][1]; vtx.xyzw[2] = 0; vtx.xyzw[3] = 0;
|
||||
vtx.normal[0] = 0; vtx.normal[1] = 0; vtx.normal[2] = 1;
|
||||
vtx.uv[0] = 0; vtx.uv[1] = vecLen;
|
||||
glmesh->m_vertices->push_back(vtx);
|
||||
|
||||
vtx.xyzw[0] = verts[2][0]; vtx.xyzw[1] = verts[2][1]; vtx.xyzw[2] = 0; vtx.xyzw[3] = 0;
|
||||
vtx.normal[0] = 0; vtx.normal[1] = 0; vtx.normal[2] = 1;
|
||||
vtx.uv[0] = 0; vtx.uv[1] = 0;
|
||||
glmesh->m_vertices->push_back(vtx);
|
||||
|
||||
vtx.xyzw[0] = verts[3][0]; vtx.xyzw[1] = verts[3][1]; vtx.xyzw[2] = 0; vtx.xyzw[3] = 0;
|
||||
vtx.normal[0] = 0; vtx.normal[1] = 0; vtx.normal[2] = 1;
|
||||
vtx.uv[0] = vecLen; vtx.uv[1] = 0;
|
||||
glmesh->m_vertices->push_back(vtx);
|
||||
|
||||
glmesh->m_numIndices = glmesh->m_indices->size();
|
||||
glmesh->m_numvertices = glmesh->m_vertices->size();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
b3Warning("TinyRenderer: unknown visual geometry type %i\n", visual->m_geometry.m_type);
|
||||
@@ -783,6 +836,45 @@ int TinyRendererVisualShapeConverter::convertVisualShapes(
|
||||
{
|
||||
B3_PROFILE("convertURDFToVisualShape");
|
||||
convertURDFToVisualShape(vis, pathPrefix, localInertiaFrame.inverse() * childTrans, vertices, indices, textures, visualShape, fileIO, m_data->m_flags);
|
||||
if ((vis->m_geometry.m_type == URDF_GEOM_PLANE) || (vis->m_geometry.m_type == URDF_GEOM_SPHERE))
|
||||
{
|
||||
int texWidth = 1024;
|
||||
int texHeight = 1024;
|
||||
if (m_data->m_checkeredTexels.size() == 0)
|
||||
{
|
||||
|
||||
int red = 173;
|
||||
int green = 199;
|
||||
int blue = 255;
|
||||
//create a textured surface
|
||||
|
||||
m_data->m_checkeredTexels.resize(texWidth * texHeight * 3);
|
||||
for (int i = 0; i < texWidth * texHeight * 3; i++)
|
||||
m_data->m_checkeredTexels[i] = 255;
|
||||
|
||||
for (int i = 0; i < texWidth; i++)
|
||||
{
|
||||
for (int j = 0; j < texHeight; j++)
|
||||
{
|
||||
int a = i < texWidth / 2 ? 1 : 0;
|
||||
int b = j < texWidth / 2 ? 1 : 0;
|
||||
|
||||
if (a == b)
|
||||
{
|
||||
m_data->m_checkeredTexels[(i + j * texWidth) * 3 + 0] = red;
|
||||
m_data->m_checkeredTexels[(i + j * texWidth) * 3 + 1] = green;
|
||||
m_data->m_checkeredTexels[(i + j * texWidth) * 3 + 2] = blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MyTexture2 texData;
|
||||
texData.m_width = texWidth;
|
||||
texData.m_height = texHeight;
|
||||
texData.textureData1 = &m_data->m_checkeredTexels[0];
|
||||
texData.m_isCached = true;
|
||||
textures.push_back(texData);
|
||||
}
|
||||
}
|
||||
|
||||
rgbaColor[0] = visualShape.m_rgbaColor[0];
|
||||
|
||||
@@ -167,11 +167,11 @@ struct Shader : public IShader
|
||||
Vec2f uv = varying_uv * bar;
|
||||
|
||||
Vec3f reflection_direction = (bn * (bn * m_light_dir_local * 2.f) - m_light_dir_local).normalize();
|
||||
float specular = std::pow(b3Max(reflection_direction.z, 0.f),
|
||||
m_model->specular(uv));
|
||||
float diffuse = b3Max(0.f, bn * m_light_dir_local);
|
||||
float specular = std::pow(b3Max(reflection_direction.z, 0.f),
|
||||
m_model->specular(uv));
|
||||
float diffuse = b3Max(0.f, bn * m_light_dir_local);
|
||||
|
||||
color = m_model->diffuse(uv);
|
||||
color = m_model->diffuse(uv);
|
||||
color[0] *= m_colorRGBA[0];
|
||||
color[1] *= m_colorRGBA[1];
|
||||
color[2] *= m_colorRGBA[2];
|
||||
|
||||
@@ -315,8 +315,10 @@ template <size_t DimRows,size_t DimCols,class T> std::ostream& operator<<(std::o
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef vec<2, float> Vec2f;
|
||||
typedef vec<2, double> Vec2d;
|
||||
typedef vec<2, int> Vec2i;
|
||||
typedef vec<3, float> Vec3f;
|
||||
typedef vec<3, double> Vec3d;
|
||||
typedef vec<3, int> Vec3i;
|
||||
typedef vec<4, float> Vec4f;
|
||||
typedef mat<4, 4, float> Matrix;
|
||||
|
||||
@@ -166,10 +166,10 @@ TGAColor Model::diffuse(Vec2f uvf)
|
||||
// bool repeat = true;
|
||||
// if (repeat)
|
||||
{
|
||||
uvf[0] = std::modf(uvf[0], &val);
|
||||
uvf[1] = std::modf(uvf[1], &val);
|
||||
}
|
||||
Vec2i uv(uvf[0] * diffusemap_.get_width(), uvf[1] * diffusemap_.get_height());
|
||||
uvf[0] = std::modf(uvf[0], &val);
|
||||
uvf[1] = std::modf(uvf[1], &val);
|
||||
}
|
||||
Vec2i uv(uvf[0] * diffusemap_.get_width(), uvf[1] * diffusemap_.get_height());
|
||||
return diffusemap_.get(uv[0], uv[1]);
|
||||
}
|
||||
return TGAColor(255, 255, 255, 255);
|
||||
|
||||
@@ -61,19 +61,25 @@ Matrix lookat(Vec3f eye, Vec3f center, Vec3f up)
|
||||
return ModelView;
|
||||
}
|
||||
|
||||
Vec3f barycentric(Vec2f A, Vec2f B, Vec2f C, Vec2f P)
|
||||
Vec3d barycentric(Vec2f A1, Vec2f B1, Vec2f C1, Vec2f P1)
|
||||
{
|
||||
Vec3f s[2];
|
||||
|
||||
Vec2d A(A1.x, A1.y);
|
||||
Vec2d B(B1.x, B1.y);
|
||||
Vec2d C(C1.x, C1.y);
|
||||
Vec2d P(P1.x, P1.y);;
|
||||
|
||||
Vec3d s[2];
|
||||
for (int i = 2; i--;)
|
||||
{
|
||||
s[i][0] = C[i] - A[i];
|
||||
s[i][1] = B[i] - A[i];
|
||||
s[i][2] = A[i] - P[i];
|
||||
}
|
||||
Vec3f u = cross(s[0], s[1]);
|
||||
Vec3d u = cross(s[0], s[1]);
|
||||
if (std::abs(u[2]) > 1e-2) // dont forget that u[2] is integer. If it is zero then triangle ABC is degenerate
|
||||
return Vec3f(1.f - (u.x + u.y) / u.z, u.y / u.z, u.x / u.z);
|
||||
return Vec3f(-1, 1, 1); // in this case generate negative coordinates, it will be thrown away by the rasterizator
|
||||
return Vec3d(1. - (u.x + u.y) / u.z, u.y / u.z, u.x / u.z);
|
||||
return Vec3d(-1., 1., 1.); // in this case generate negative coordinates, it will be thrown away by the rasterizator
|
||||
}
|
||||
|
||||
void triangleClipped(mat<4, 3, float> &clipc, mat<4, 3, float> &orgClipc, IShader &shader, TGAImage &image, float *zbuffer, const Matrix &viewPortMatrix)
|
||||
@@ -119,25 +125,28 @@ void triangleClipped(mat<4, 3, float> &clipc, mat<4, 3, float> &orgClipc, IShade
|
||||
{
|
||||
for (P.y = bboxmin.y; P.y <= bboxmax.y; P.y++)
|
||||
{
|
||||
float frag_depth = 0;
|
||||
double frag_depth = 0;
|
||||
{
|
||||
Vec3f bc_screen = barycentric(pts2[0], pts2[1], pts2[2], P);
|
||||
Vec3f bc_clip = Vec3f(bc_screen.x / screenSpacePts[0][3], bc_screen.y / screenSpacePts[1][3], bc_screen.z / screenSpacePts[2][3]);
|
||||
Vec3d bc_screen = barycentric(pts2[0], pts2[1], pts2[2], P);
|
||||
Vec3d bc_clip = Vec3d(bc_screen.x / screenSpacePts[0][3], bc_screen.y / screenSpacePts[1][3], bc_screen.z / screenSpacePts[2][3]);
|
||||
bc_clip = bc_clip / (bc_clip.x + bc_clip.y + bc_clip.z);
|
||||
frag_depth = -1 * (clipc[2] * bc_clip);
|
||||
Vec3d clipd(clipc[2].x, clipc[2].y, clipc[2].z);
|
||||
frag_depth = -1. * (clipd * bc_clip);
|
||||
|
||||
if (bc_screen.x < 0 || bc_screen.y < 0 || bc_screen.z < 0 ||
|
||||
zbuffer[P.x + P.y * image.get_width()] > frag_depth)
|
||||
continue;
|
||||
}
|
||||
|
||||
Vec3f bc_screen2 = barycentric(orgPts2[0], orgPts2[1], orgPts2[2], P);
|
||||
Vec3f bc_clip2 = Vec3f(bc_screen2.x / orgScreenSpacePts[0][3], bc_screen2.y / orgScreenSpacePts[1][3], bc_screen2.z / orgScreenSpacePts[2][3]);
|
||||
Vec3d bc_screen2 = barycentric(orgPts2[0], orgPts2[1], orgPts2[2], P);
|
||||
Vec3d bc_clip2 = Vec3d(bc_screen2.x / orgScreenSpacePts[0][3], bc_screen2.y / orgScreenSpacePts[1][3], bc_screen2.z / orgScreenSpacePts[2][3]);
|
||||
bc_clip2 = bc_clip2 / (bc_clip2.x + bc_clip2.y + bc_clip2.z);
|
||||
float frag_depth2 = -1 * (orgClipc[2] * bc_clip2);
|
||||
|
||||
bool discard = shader.fragment(bc_clip2, color);
|
||||
Vec3d orgClipd(orgClipc[2].x, orgClipc[2].y, orgClipc[2].z);
|
||||
double frag_depth2 = -1. * (orgClipd * bc_clip2);
|
||||
|
||||
Vec3f bc_clip2f(bc_clip2.x, bc_clip2.y, bc_clip2.z);
|
||||
bool discard = shader.fragment(bc_clip2f, color);
|
||||
|
||||
if (!discard)
|
||||
{
|
||||
zbuffer[P.x + P.y * image.get_width()] = frag_depth;
|
||||
@@ -182,14 +191,16 @@ void triangle(mat<4, 3, float> &clipc, IShader &shader, TGAImage &image, float *
|
||||
{
|
||||
for (P.y = bboxmin.y; P.y <= bboxmax.y; P.y++)
|
||||
{
|
||||
Vec3f bc_screen = barycentric(pts2[0], pts2[1], pts2[2], P);
|
||||
Vec3f bc_clip = Vec3f(bc_screen.x / pts[0][3], bc_screen.y / pts[1][3], bc_screen.z / pts[2][3]);
|
||||
Vec3d bc_screen = barycentric(pts2[0], pts2[1], pts2[2], P);
|
||||
Vec3d bc_clip = Vec3d(bc_screen.x / pts[0][3], bc_screen.y / pts[1][3], bc_screen.z / pts[2][3]);
|
||||
bc_clip = bc_clip / (bc_clip.x + bc_clip.y + bc_clip.z);
|
||||
float frag_depth = -1 * (clipc[2] * bc_clip);
|
||||
Vec3d clipd(clipc[2].x, clipc[2].y, clipc[2].z);
|
||||
double frag_depth = -1. * (clipd * bc_clip);
|
||||
if (bc_screen.x < 0 || bc_screen.y < 0 || bc_screen.z < 0 ||
|
||||
zbuffer[P.x + P.y * image.get_width()] > frag_depth)
|
||||
continue;
|
||||
bool discard = shader.fragment(bc_clip, color);
|
||||
Vec3f bc_clipf(bc_clip.x, bc_clip.y, bc_clip.z);
|
||||
bool discard = shader.fragment(bc_clipf, color);
|
||||
if (frag_depth < -shader.m_farPlane)
|
||||
discard = true;
|
||||
if (frag_depth > shader.m_nearPlane)
|
||||
|
||||
@@ -296,6 +296,23 @@ bool TGAImage::unload_rle_data(std::ofstream &out) const
|
||||
|
||||
TGAColor TGAImage::get(int x, int y) const
|
||||
{
|
||||
if (x < 0)
|
||||
{
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
y = 0;
|
||||
}
|
||||
if (x >= width)
|
||||
{
|
||||
x = width - 1;
|
||||
}
|
||||
if (y >= height)
|
||||
{
|
||||
y = height - 1;
|
||||
}
|
||||
|
||||
if (!data || x < 0 || y < 0 || x >= width || y >= height)
|
||||
{
|
||||
return TGAColor(128.f, 128.f, 128.f, 255.f);
|
||||
|
||||
Reference in New Issue
Block a user