//------------------------------------------------------------------------------------ Mesh* SceneManager::CreatePlaneMesh( float w, float h ) { float halfW = w / 2; float halfH = h / 2; SVertex vert[4] = { SVertex(VEC3(-w,0,+h), VEC2(0,0), VEC3::UNIT_Y), SVertex(VEC3(+w,0,+h), VEC2(1,0), VEC3::UNIT_Y), SVertex(VEC3(+w,0,-h), VEC2(1,1), VEC3::UNIT_Y), SVertex(VEC3(-w,0,-h), VEC2(0,1), VEC3::UNIT_Y), }; DWORD dwIndex[6] = {0,1,3,1,2,3}; Mesh* pMesh = new Mesh; SubMesh* pSubmesh = new SubMesh; pSubmesh->InitVertData(eVertexType_General, vert, 4, true); pSubmesh->InitIndexData(dwIndex, 6, true); pMesh->AddSubMesh(pSubmesh); return pMesh; }
// Does a few inits CMesh::CMesh() : m_minVert(numeric_limits<float>::max(), numeric_limits<float>::max(), numeric_limits<float>::max()) , m_maxVert(-numeric_limits<float>::max(), -numeric_limits<float>::max(), -numeric_limits<float>::max()) { // Pushing some dummy front values. // Note: this is uggly, find a better way. m_vertVector.push_back(SVertex(0, 0, 0)); m_texVector.push_back(SVertex(0, 0, 0)); m_normVector.push_back(SVertex(0, 0, 0)); }
// Empties the mesh. void CMesh::clear() { m_minVert.set(numeric_limits<float>::max(), numeric_limits<float>::max(), numeric_limits<float>::max()); m_maxVert.set(-numeric_limits<float>::max(), -numeric_limits<float>::max(), -numeric_limits<float>::max()); m_vertVector.clear(); m_texVector.clear(); m_normVector.clear(); m_faceVector.clear(); // Cf. ctor. m_vertVector.push_back(SVertex(0, 0, 0)); m_texVector.push_back(SVertex(0, 0, 0)); m_normVector.push_back(SVertex(0, 0, 0)); }
//---------------------------------------------------------------------------------------- D3D11RenderTarget::D3D11RenderTarget() :m_pRenderSystem(g_env.pRenderSystem) ,m_pRenderTexture(nullptr) ,m_clearColor(SColor::BLACK) ,m_bClearColor(true) ,m_bClearZBuffer(true) ,m_bHasDepthBuffer(false) ,m_bNoFrameBuffer(false) ,m_bUpdateRatioAspect(true) ,m_phaseFlag(eRenderPhase_Geometry) ,m_pDepthStencil(nullptr) ,m_sizeRatio(0, 0) { // Create screen quad static bool bCreate = false; if (!bCreate) { m_pQuadMesh = new Mesh; SubMesh* pSubMesh = new SubMesh; SVertex v[4] = { SVertex(VEC3(-1,1,0), VEC2(0,0)), SVertex(VEC3(1,1,0), VEC2(1,0)), SVertex(VEC3(-1,-1,0), VEC2(0,1)), SVertex(VEC3(1,-1,0), VEC2(1,1)) }; DWORD index[6] = { 0,1,2, 1,3,2 }; // Store index to frustum far corner v[0].normal.x = 0; v[1].normal.x = 1; v[2].normal.x = 2; v[3].normal.x = 3; pSubMesh->InitVertData(eVertexType_General, v, ARRAYSIZE(v), true); pSubMesh->InitIndexData(index, ARRAYSIZE(index), true); m_pQuadMesh->AddSubMesh(pSubMesh); m_pQuadEntity = new Entity(m_pQuadMesh); m_pQuadEntity->SetCastShadow(false); m_pQuadEntity->SetReceiveShadow(false); bCreate = true; } }
//------------------------------------------------------------------------------------ bool SceneManager::Init() { m_camera = new Camera; m_camera->SetAspectRatio(m_pRenderSystem->GetWndWidth() / (float)m_pRenderSystem->GetWndHeight()); m_sunLight.lightDir.Set(1, -1, 2); m_sunLight.lightDir.Normalize(); m_sunLight.lightColor.Set(0.8f, 0.8f, 0.8f); m_pSSAO = new SSAO; { m_pDebugRTMesh = new Mesh; SubMesh* pSubMesh = new SubMesh; SVertex v[4] = { SVertex(VEC3(0.5f,1.0f,0), VEC2(0,0)), SVertex(VEC3(1.0f,1.0f,0), VEC2(1,0)), SVertex(VEC3(0.5f,0.4f,0), VEC2(0,1)), SVertex(VEC3(1.0f,0.4f,0), VEC2(1,1)) }; DWORD index[6] = { 0,1,2, 1,3,2 }; pSubMesh->InitVertData(eVertexType_General, v, ARRAYSIZE(v), true); pSubMesh->InitIndexData(index, ARRAYSIZE(index), true); m_pDebugRTMesh->AddSubMesh(pSubMesh); m_pDebugRTMaterial = new Material; m_pDebugRTMaterial->InitShader(GetResPath("DebugRT.hlsl"), GetResPath("DebugRT.hlsl")); pSubMesh->SetMaterial(m_pDebugRTMaterial); } _InitAllScene(); return true; }
//------------------------------------------------------------------------------------ Decal::Decal(const VEC3& pos, float size, const QUATERNION& rot) : m_vPos(pos) , m_fSize(size) , m_pMaterial(nullptr) { if (!m_pUnitCube) { SVertex vert[8] = { SVertex(VEC3(-0.5f, -0.5f, +0.5f), VEC2(0, 0)), SVertex(VEC3(+0.5f, -0.5f, +0.5f), VEC2(0, 0)), SVertex(VEC3(+0.5f, -0.5f, -0.5f), VEC2(0, 0)), SVertex(VEC3(-0.5f, -0.5f, -0.5f), VEC2(0, 0)), SVertex(VEC3(-0.5f, +0.5f, +0.5f), VEC2(0, 0)), SVertex(VEC3(+0.5f, +0.5f, +0.5f), VEC2(0, 0)), SVertex(VEC3(+0.5f, +0.5f, -0.5f), VEC2(0, 0)), SVertex(VEC3(-0.5f, +0.5f, -0.5f), VEC2(0, 0)), }; DWORD dwIndex[36] = { 0,2,1,0,3,2, // bottom 4,5,7,5,6,7, // top 4,7,0,7,3,0, // left 6,5,2,5,1,2, // right 7,6,3,6,2,3, // behind 5,4,1,4,0,1, // front }; Mesh* pMesh = new Mesh; SubMesh* pSubmesh = new SubMesh; pSubmesh->InitVertData(eVertexType_General, vert, 8, true); pSubmesh->InitIndexData(dwIndex, 36, true); pMesh->AddSubMesh(pSubmesh); m_pUnitCube = new Entity(pMesh); m_pUnitCube->SetCastShadow(false); m_pCB_Decal = g_env.pRenderer->GetRenderSys()->CreateConstantBuffer(sizeof(cBufferDecal), 10); } m_cbDecal.matRotation = rot.ToRotationMatrix().Transpose(); m_cbDecal.fProjClip = 10000.f; }
void CTexturedLineRData::CreateLineCap(const SOverlayTexturedLine& line, const CVector3D& corner1, const CVector3D& corner2, const CVector3D& lineDirectionNormal, SOverlayTexturedLine::LineCapType endCapType, std::vector<SVertex>& verticesOut, std::vector<u16>& indicesOut) { if (endCapType == SOverlayTexturedLine::LINECAP_FLAT) return; // no action needed, this is the default // When not in closed mode, we've created artificial points for the start- and endpoints that extend the line in the // direction of the first and the last segment, respectively. Thus, we know both the start and endpoints have perpendicular // butt endings, i.e. the end corner vertices on either side of the line extend perpendicularly from the segment direction. // That is to say, when viewed from the top, we will have something like // . // this: and not like this: /| // ----+ / | // | / . // | / // ----+ / // int roundCapPoints = 8; // amount of points to sample along the semicircle for rounded caps (including corner points) float radius = line.m_Thickness; CVector3D centerPoint = (corner1 + corner2) * 0.5f; SVertex centerVertex(centerPoint, 0.5f, 0.5f); u16 indexOffset = verticesOut.size(); // index offset in verticesOut from where we start adding our vertices switch (endCapType) { case SOverlayTexturedLine::LINECAP_SHARP: { roundCapPoints = 3; // creates only one point directly ahead radius *= 1.5f; // make it a bit sharper (note that we don't use the radius for the butt-end corner points so it should be ok) centerVertex.m_UVs[0] = 0.480f; // slight visual correction to make the texture match up better at the corner points } // fall-through case SOverlayTexturedLine::LINECAP_ROUND: { // Draw a rounded line cap in the 3D plane of the line specified by the two corner points and the normal vector of the // line's direction. The terrain normal at the centroid between the two corner points is perpendicular to this plane. // The way this works is by taking a vector from the corner points' centroid to one of the corner points (which is then // of radius length), and rotate it around the terrain normal vector in that centroid. This will rotate the vector in // the line's plane, producing the desired rounded cap. // To please OpenGL's winding order, this angle needs to be negated depending on whether we start rotating from // the (center -> corner1) or (center -> corner2) vector. For the (center -> corner2) vector, we apparently need to use // the negated angle. float stepAngle = -(float)(M_PI/(roundCapPoints-1)); // Push the vertices in triangle fan order (easy to generate GL_TRIANGLES indices for afterwards) // Note that we're manually adding the corner vertices instead of having them be generated by the rotating vector. // This is because we want to support an overly large radius to make the sharp line ending look sharper. verticesOut.push_back(centerVertex); verticesOut.push_back(SVertex(corner2, 0.f, 0.f)); // Get the base vector that we will incrementally rotate in the cap plane to produce the radial sample points. // Normally corner2 - centerPoint would suffice for this since it is of radius length, but we want to support custom // radii to support tuning the 'sharpness' of sharp end caps (see above) CVector3D rotationBaseVector = (corner2 - centerPoint).Normalized() * radius; // Calculate the normal vector of the plane in which we're going to be drawing the line cap. This is the vector that // is perpendicular to both baseVector and the 'lineDirectionNormal' vector indicating the direction of the line. // Note that we shouldn't use terrain->CalcExactNormal() here because if the line is being rendered on top of water, // then CalcExactNormal will return the normal vector of the terrain that's underwater (which can be quite funky). CVector3D capPlaneNormal = lineDirectionNormal.Cross(rotationBaseVector).Normalized(); for (int i = 1; i < roundCapPoints - 1; ++i) { // Rotate the centerPoint -> corner vector by i*stepAngle radians around the cap plane normal at the center point. CQuaternion quatRotation; quatRotation.FromAxisAngle(capPlaneNormal, i * stepAngle); CVector3D worldPos3D = centerPoint + quatRotation.Rotate(rotationBaseVector); // Let v range from 0 to 1 as we move along the semi-circle, keep u fixed at 0 (i.e. curve the left vertical edge // of the texture around the edge of the semicircle) float u = 0.f; float v = clamp((i/(float)(roundCapPoints-1)), 0.f, 1.f); // pos, u, v verticesOut.push_back(SVertex(worldPos3D, u, v)); } // connect back to the other butt-end corner point to complete the semicircle verticesOut.push_back(SVertex(corner1, 0.f, 1.f)); // now push indices in GL_TRIANGLES order; vertices[indexOffset] is the center vertex, vertices[indexOffset + 1] is the // first corner point, then a bunch of radial samples, and then at the end we have the other corner point again. So: for (int i=1; i < roundCapPoints; ++i) { indicesOut.push_back(indexOffset); // center vertex indicesOut.push_back(indexOffset + i); indicesOut.push_back(indexOffset + i + 1); } } break; case SOverlayTexturedLine::LINECAP_SQUARE: { // Extend the (corner1 -> corner2) vector along the direction normal and draw a square line ending consisting of // three triangles (sort of like a triangle fan) // NOTE: The order in which the vertices are pushed out determines the visibility, as they // are rendered only one-sided; the wrong order of vertices will make the cap visible only from the bottom. verticesOut.push_back(centerVertex); verticesOut.push_back(SVertex(corner2, 0.f, 0.f)); verticesOut.push_back(SVertex(corner2 + (lineDirectionNormal * (line.m_Thickness)), 0.f, 0.33333f)); // extend butt corner point 2 along the normal vector verticesOut.push_back(SVertex(corner1 + (lineDirectionNormal * (line.m_Thickness)), 0.f, 0.66666f)); // extend butt corner point 1 along the normal vector verticesOut.push_back(SVertex(corner1, 0.f, 1.0f)); // push butt corner point 1 for (int i=1; i < 4; ++i) { indicesOut.push_back(indexOffset); // center point indicesOut.push_back(indexOffset + i); indicesOut.push_back(indexOffset + i + 1); } } break; default: break; } }