int HWDrawInfo::SetupLightsForOtherPlane(subsector_t * sub, FDynLightData &lightdata, const secplane_t *plane) { if (Level->HasDynamicLights && !isFullbrightScene()) { Plane p; FLightNode * node = sub->section->lighthead; lightdata.Clear(); while (node) { FDynamicLight * light = node->lightsource; if (!light->IsActive()) { node = node->nextLight; continue; } iter_dlightf++; p.Set(plane->Normal(), plane->fD()); draw_dlightf += lightdata.GetLight(sub->sector->PortalGroup, p, light, true); node = node->nextLight; } return screen->mLights->UploadLights(lightdata); } else return -1; }
void GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, int *dli) { Plane p; if (dli != NULL && *dli != -1) { gl_RenderState.ApplyLightIndex(GLRenderer->mLights->GetIndex(*dli)); (*dli)++; return; } lightdata.Clear(); FLightNode * node = sub->lighthead; while (node) { ADynamicLight * light = node->lightsource; if (light->flags2&MF2_DORMANT) { node=node->nextLight; continue; } iter_dlightf++; // we must do the side check here because gl_SetupLight needs the correct plane orientation // which we don't have for Legacy-style 3D-floors fixed_t planeh = plane.plane.ZatPoint(light->x, light->y); if (gl_lights_checkside && ((planeh<light->z && ceiling) || (planeh>light->z && !ceiling))) { node=node->nextLight; continue; } p.Set(plane.plane); gl_GetLight(p, light, false, false, lightdata); node = node->nextLight; } int d = GLRenderer->mLights->UploadLights(lightdata); if (pass == GLPASS_LIGHTSONLY) { GLRenderer->mLights->StoreIndex(d); } else { gl_RenderState.ApplyLightIndex(d); } }
// seppt3 //--------------------------------------------------------------------------- int SeparatePointSets3D ( // convex hull 0 int n0, const Point pts0[], int fCount0, const Triangle* face0, // convex hull 1 int n1, const Point pts1[], int fCount1, const Triangle* face1, // result plane, if result >0 Plane &plane) { int i, j0, j1, j2, side0, side1; //hg was double float ux, uy, uz, vx, vy, vz; float xNor,yNor,zNor,c; // test faces of hull 0 for possible separation of points for (i = 0; i < fCount0; i++) { // lookup face (assert: j0 != j1 && j0 != j2 && j1 != j2) j0 = face0[i][0]; j1 = face0[i][1]; j2 = face0[i][2]; // compute perpendicular to face (assert: (xNor,yNor,zNor) != (0,0,0)) ux = pts0[j1].x-pts0[j0].x; uy = pts0[j1].y-pts0[j0].y; uz = pts0[j1].z-pts0[j0].z; vx = pts0[j2].x-pts0[j0].x; vy = pts0[j2].y-pts0[j0].y; vz = pts0[j2].z-pts0[j0].z; xNor = uy*vz-uz*vy; yNor = uz*vx-ux*vz; zNor = ux*vy-uy*vx; if (xNor == 0 && yNor == 0 && zNor == 0) { TRACE("BAD NORMAL in hull !!!!!!\n"); continue; } // compute plane constant c = xNor*pts0[j0].x+yNor*pts0[j0].y+zNor*pts0[j0].z; // determine if hull 1 is on same side of plane side1 = OnSameSide(xNor,yNor,zNor,c,fCount1,face1,pts1); if ( side1 ) { // determine which side of plane hull 0 lies side0 = WhichSide(xNor,yNor,zNor,c,fCount0,face0,pts0); if ( side0*side1 <= 0 ) { // plane separates hulls plane.Set(xNor,yNor,zNor,c); return 1; } } } // test faces of hull 1 for possible separation of points for (i = 0; i < fCount1; i++) { // lookup edge (assert: j0 != j1 && j0 != j2 && j1 != j2) j0 = face1[i][0]; j1 = face1[i][1]; j2 = face1[i][2]; // compute perpendicular to face (assert: (xNor,yNor,zNor) != (0,0,0)) ux = pts1[j1].x-pts1[j0].x; uy = pts1[j1].y-pts1[j0].y; uz = pts1[j1].z-pts1[j0].z; vx = pts1[j2].x-pts1[j0].x; vy = pts1[j2].y-pts1[j0].y; vz = pts1[j2].z-pts1[j0].z; xNor = uy*vz-uz*vy; yNor = uz*vx-ux*vz; zNor = ux*vy-uy*vx; if (xNor == 0 && yNor == 0 && zNor == 0) { TRACE("BAD NORMAL in hull !!!!!!\n"); continue; } // compute plane constant c = xNor*pts1[j0].x+yNor*pts1[j0].y+zNor*pts1[j0].z; // determine if hull 0 is on same side of plane side0 = OnSameSide(xNor,yNor,zNor,c,fCount0,face0,pts0); if ( side0 ) { // determine which side of plane hull 1 lies side1 = WhichSide(xNor,yNor,zNor,c,fCount1,face1,pts1); if ( side0*side1 <= 0 ) { // plane separates hulls /* // normalize float l = sqrt(xNor*xNor + yNor*yNor + zNor*zNor); if (l != 0.0) { l= 1.0/l; xNor *= l; yNor *=l; zNor*=l; } c = xNor*pts1[j0].x+yNor*pts1[j0].y+zNor*pts1[j0].z; */ plane.Set(xNor,yNor,zNor,c); return 1; } } } #if 0 // what if two hulls are on same plane ? // don't do the full test return (0); #endif // build edge list for hull 0 EdgeNode* list0 = 0; for (i = 0; i < fCount0; i++) { // lookup face (assert: j0 != j1 && j0 != j2 && j1 != j2) j0 = face0[i][0]; j1 = face0[i][1]; j2 = face0[i][2]; AddEdge(list0,j0,j1); AddEdge(list0,j0,j2); AddEdge(list0,j1,j2); } // build edge list for hull 1 EdgeNode* list1 = 0; for (i = 0; i < fCount1; i++) { // lookup face (assert: j0 != j1 && j0 != j2 && j1 != j2) j0 = face1[i][0]; j1 = face1[i][1]; j2 = face1[i][2]; AddEdge(list1,j0,j1); AddEdge(list1,j0,j2); AddEdge(list1,j1,j2); } // Test planes whose normals are cross products of two edges, // one from each hull. for (EdgeNode* node0 = list0; node0; node0 = node0->next) { // get edge ux = pts0[node0->v1].x-pts0[node0->v0].x; uy = pts0[node0->v1].y-pts0[node0->v0].y; uz = pts0[node0->v1].z-pts0[node0->v0].z; for (EdgeNode* node1 = list1; node1; node1 = node1->next) { vx = pts1[node1->v1].x-pts1[node1->v0].x; vy = pts1[node1->v1].y-pts1[node1->v0].y; vz = pts1[node1->v1].z-pts1[node1->v0].z; // compute plane normal xNor = uy*vz-uz*vy; yNor = uz*vx-ux*vz; zNor = ux*vy-uy*vx; if (xNor == 0 && yNor == 0 && zNor == 0) { TRACE("BAD NORMAL in hull !!!!!!\n"); continue; } // compute plane constant c = xNor*pts0[node0->v0].x+yNor*pts0[node0->v0].y+zNor*pts0[node0->v0].z; // determine if hull 0 is on same side of plane side0 = OnSameSide(xNor,yNor,zNor,c,fCount0,face0,pts0); side1 = OnSameSide(xNor,yNor,zNor,c,fCount1,face1,pts1); if ( side0*side1 < 0 ) { // plane separates hulls DeleteList(list0); // hg DeleteList(list1); plane.Set(xNor,yNor,zNor,c); return 1; } } } DeleteList(list0); DeleteList(list1); return 0; }
void MeshEnt::UnSelectFaces( Area<S32> * rect) // = NULL { if (!selData) { return; } MeshRoot & root = RootPriv(); if (!rect) { selData->verts.DisposeAll(); selData->faces.DisposeAll(); } else { // get temp memory Vector * verts; U8 * hits; U32 heapSize = Vid::Heap::ReqVector( &verts, root.vertices.count, &hits, root.vertices.count); Utils::Memset( hits, 0, root.vertices.count); // set up transform matrices and transform verts to view space Matrix tranys[MAXMESHPERGROUP]; Bool doMultiWeight = (root.rootControlFlags & controlMULTIWEIGHT) && Vid::renderState.status.multiWeight ? TRUE : FALSE; root.SetVertsView( statesR, tranys, verts, root.vertices.count, doMultiWeight); // transform verts and clip in Z // U16 i, j; for (i = 0; i < root.faces.count; i++) { FaceObj &face = root.faces[i]; BucketLock &bucky = buckys[face.buckyIndex]; if (!(bucky.flags0 & RS_2SIDED)) { // backface cull // Plane plane; plane.Set( verts[face.verts[0]], verts[face.verts[2]], verts[face.verts[1]]); if (plane.Dot( verts[face.verts[0]]) <= 0.0f) { continue; } } for (j = 0; j < 3; j++) { Vector & vect = verts[face.verts[j]]; if (vect.z < Vid::Math::nearPlane || vect.z >= Vid::Math::farPlane) { // done or 3D clip continue; } // project // VertexTL v; Vid::ProjectFromCamera_I( v, vect); if (v.vv.x >= rect->p0.x && v.vv.x < rect->p1.x && v.vv.y >= rect->p0.y && v.vv.y < rect->p1.y) { // if a vert is inside the on screen box // UnSelectFace( i); break; } } } Vid::Heap::Restore( heapSize); } }
void COpenGLSkydomeRenderer::DoDrawReflectionSkydomeRenderBatch() { if( m_SkydomeStaticBuffer == NULL ) return; COpenGLShaderManager *pShaderManager = static_cast<COpenGLShaderManager*>(m_pRenderDevice->GetShaderManager()); Matrix4x4 SkydomeWorldMatrix; Plane ReflectionPlane; ReflectionPlane.Set( Vector3D(0, 1, 0), -m_pRenderDevice->GetWorldSystemManager()->getWater()->m_fWaterHeight ); SkydomeWorldMatrix.ReflectPlane( ReflectionPlane ); Vector4D newCamPos = m_pRenderDevice->getOpenGLCamera()->m_CameraPos * SkydomeWorldMatrix; SkydomeWorldMatrix = m_SkydomeWorldMatrix; SkydomeWorldMatrix.Translate( newCamPos.x, newCamPos.y, newCamPos.z ); Matrix4x4 MVP = SkydomeWorldMatrix * m_pRenderDevice->getOpenGLWaterRenderer()->m_MirrorViewMatrix * m_pRenderDevice->getOpenGLWaterRenderer()->m_ObliqueNearPlaneReflectionProjMatrix; Matrix4x4 MV = SkydomeWorldMatrix * m_pRenderDevice->getOpenGLWaterRenderer()->m_MirrorViewMatrix; ISGPMaterialSystem::MaterialList &Mat_List = m_pRenderDevice->GetMaterialSystem()->GetMaterialList(); const ISGPMaterialSystem::SGPMaterialInfo &SkydomeMaterial_info = Mat_List.getReference(ISGPMaterialSystem::eMaterial_skydome); m_pRenderDevice->getOpenGLMaterialRenderer()->PushMaterial( SkydomeMaterial_info.m_material, MM_Add ); m_pRenderDevice->getOpenGLMaterialRenderer()->ComputeMaterialPass(); m_pRenderDevice->getOpenGLMaterialRenderer()->OnePassPreRenderMaterial(0); pShaderManager->GetGLSLShaderProgram(m_SkydomeMaterialSkin.nShaderType)->useProgram(); pShaderManager->GetGLSLShaderProgram(m_SkydomeMaterialSkin.nShaderType)->setShaderUniform("modelViewProjMatrix", MVP); pShaderManager->GetGLSLShaderProgram(m_SkydomeMaterialSkin.nShaderType)->setShaderUniform("modelViewMatrix", MV); pShaderManager->GetGLSLShaderProgram(m_SkydomeMaterialSkin.nShaderType)->setShaderUniform("InvSunDir", m_SunDir); pShaderManager->GetGLSLShaderProgram(m_SkydomeMaterialSkin.nShaderType)->setShaderUniform("HGg", m_HGg); pShaderManager->GetGLSLShaderProgram(m_SkydomeMaterialSkin.nShaderType)->setShaderUniform("BetaRPlusBetaM", m_BetaRPlusBetaM); pShaderManager->GetGLSLShaderProgram(m_SkydomeMaterialSkin.nShaderType)->setShaderUniform("Multipliers", m_Multipliers); pShaderManager->GetGLSLShaderProgram(m_SkydomeMaterialSkin.nShaderType)->setShaderUniform("BetaDashR", m_BetaDashR); pShaderManager->GetGLSLShaderProgram(m_SkydomeMaterialSkin.nShaderType)->setShaderUniform("BetaDashM", m_BetaDashM); pShaderManager->GetGLSLShaderProgram(m_SkydomeMaterialSkin.nShaderType)->setShaderUniform("OneOverBetaRPlusBetaM", m_OneOverBetaRPlusBetaM); pShaderManager->GetGLSLShaderProgram(m_SkydomeMaterialSkin.nShaderType)->setShaderUniform("SunColorAndIntensity", m_SunColorAndIntensity); m_pRenderDevice->GetTextureManager()->getTextureByID(m_SkydomeMaterialSkin.nTextureID[0])->pSGPTexture->BindTexture2D(0); pShaderManager->GetGLSLShaderProgram(m_SkydomeMaterialSkin.nShaderType)->setShaderUniform("gSampler0", 0); if( m_SkydomeMaterialSkin.nTextureNum == 2 ) { m_pRenderDevice->GetTextureManager()->getTextureByID(m_SkydomeMaterialSkin.nTextureID[1])->pSGPTexture->BindTexture2D(1); pShaderManager->GetGLSLShaderProgram(m_SkydomeMaterialSkin.nShaderType)->setShaderUniform("gSampler1", 1); } pShaderManager->GetGLSLShaderProgram(m_SkydomeMaterialSkin.nShaderType)->setShaderUniform("cloudParam", m_SkydomeCloudParam); m_SkydomeStaticBuffer->pVBO->bindVAO(); glDrawElements( m_pRenderDevice->primitiveTypeToGL( m_SkydomeMaterialSkin.nPrimitiveType ), m_SkydomeStaticBuffer->nNumIndis, GL_UNSIGNED_SHORT, (void*)0 ); m_SkydomeStaticBuffer->pVBO->unBindVAO(); m_pRenderDevice->getOpenGLMaterialRenderer()->OnePassPostRenderMaterial(0); m_pRenderDevice->getOpenGLMaterialRenderer()->PopMaterial(); }
void GLWall::SetupLights() { if (RenderStyle == STYLE_Add && !glset.lightadditivesurfaces) return; // no lights on additively blended surfaces. // check for wall types which cannot have dynamic lights on them (portal types never get here so they don't need to be checked.) switch (type) { case RENDERWALL_FOGBOUNDARY: case RENDERWALL_MIRRORSURFACE: case RENDERWALL_COLOR: return; } float vtx[]={glseg.x1,zbottom[0],glseg.y1, glseg.x1,ztop[0],glseg.y1, glseg.x2,ztop[1],glseg.y2, glseg.x2,zbottom[1],glseg.y2}; Plane p; lightdata.Clear(); p.Set(&glseg); /* if (!p.ValidNormal()) { return; } */ FLightNode *node; if (seg->sidedef == NULL) { node = NULL; } else if (!(seg->sidedef->Flags & WALLF_POLYOBJ)) { node = seg->sidedef->lighthead; } else if (sub) { // Polobject segs cannot be checked per sidedef so use the subsector instead. node = sub->lighthead; } else node = NULL; // Iterate through all dynamic lights which touch this wall and render them while (node) { if (!(node->lightsource->flags2&MF2_DORMANT)) { iter_dlight++; DVector3 posrel = node->lightsource->PosRelative(seg->frontsector); float x = posrel.X; float y = posrel.Y; float z = posrel.Z; float dist = fabsf(p.DistToPoint(x, z, y)); float radius = node->lightsource->GetRadius(); float scale = 1.0f / ((2.f * radius) - dist); FVector3 fn, pos; if (radius > 0.f && dist < radius) { FVector3 nearPt, up, right; pos = { x, z, y }; fn = p.Normal(); fn.GetRightUp(right, up); FVector3 tmpVec = fn * dist; nearPt = pos + tmpVec; FVector3 t1; int outcnt[4]={0,0,0,0}; texcoord tcs[4]; // do a quick check whether the light touches this polygon for(int i=0;i<4;i++) { t1 = FVector3(&vtx[i*3]); FVector3 nearToVert = t1 - nearPt; tcs[i].u = ((nearToVert | right) * scale) + 0.5f; tcs[i].v = ((nearToVert | up) * scale) + 0.5f; if (tcs[i].u<0) outcnt[0]++; if (tcs[i].u>1) outcnt[1]++; if (tcs[i].v<0) outcnt[2]++; if (tcs[i].v>1) outcnt[3]++; } if (outcnt[0]!=4 && outcnt[1]!=4 && outcnt[2]!=4 && outcnt[3]!=4) { gl_GetLight(seg->frontsector->PortalGroup, p, node->lightsource, true, lightdata); } } } node = node->nextLight; } dynlightindex = GLRenderer->mLights->UploadLights(lightdata); }