-
Сабж. Че то я никак не фтыкаю как по модельке построить SV.
-
Из DX8 SDK (геометрические расчёты везде одинаковы):
Each frame, the sihlouette of the plane is computed (using an edge detection algorithm, in which sihlouette edges are found because the normals of adjacent polygons will have opposing normals with respect to the light vector). The resulting edge list (the sihlouette) is pretuded into a 3D object away from the light source. This 3D object is known as the shadow volume, as everypoint inside the volume is inside a shadow.
//----------------------------------------------------------------------------- // Name: AddEdge() // Desc: Adds an edge to a list of silohuette edges of a shadow volume. //----------------------------------------------------------------------------- procedure AddEdge(var pEdges: array of Word; var dwNumEdges: DWord; v0, v1: Word); var i: Integer; begin // Remove interior edges (which appear in the list twice) for i:= 0 to (dwNumEdges - 1) do begin if ((pEdges[2*i+0] = v0) and (pEdges[2*i+1] = v1)) or ((pEdges[2*i+0] = v1) and (pEdges[2*i+1] = v0)) then begin if (dwNumEdges > 1) then begin pEdges[2*i+0] := pEdges[2*(dwNumEdges-1)+0]; pEdges[2*i+1] := pEdges[2*(dwNumEdges-1)+1]; end; Dec(dwNumEdges); Exit; end; end;
pEdges[2*dwNumEdges+0] := v0; pEdges[2*dwNumEdges+1] := v1; Inc(dwNumEdges); end;
//----------------------------------------------------------------------------- // Name: BuildFromMesh() // Desc: Takes a mesh as input, and uses it to build a shadowvolume. The // technique used considers each triangle of the mesh, and adds it's // edges to a temporary list. The edge list is maintained, such that // only silohuette edges are kept. Finally, the silohuette edges are // extruded to make the shadow volume vertex list. //----------------------------------------------------------------------------- function TShadowVolume.BuildFromMesh(pMesh: ID3DXMesh; vLight: TD3DXVector3): HResult; type PMeshVertex = ^TMeshVertex; TMeshVertex = packed record p, n: TD3DXVector3; tu, tv: Single; end;
PMeshVertexArray = ^TMeshVertexArray; TMeshVertexArray = array [0..0] of TMeshVertex;
var // dwFVF: DWORD; pVertices: PMeshVertexArray; pIndices: PWordArray;
// dwNumVertices: DWORD; dwNumFaces: DWORD;
pEdges: array of Word; dwNumEdges: DWord;
i: Integer;
wFace0, wFace1, wFace2: Word; v0, v1, v2, v3, v4: TD3DXVector3; v001, v002: TD3DXVector3;
vNormal: TD3DXVector3; begin // Note: the MESHVERTEX format depends on the FVF of the mesh // dwFVF := pMesh.GetFVF;
// Lock the geometry buffers pMesh.LockVertexBuffer(0, PByte(pVertices)); pMesh.LockIndexBuffer(0, PByte(pIndices)); // dwNumVertices := pMesh.GetNumVertices; dwNumFaces := pMesh.GetNumFaces;
// Allocate a temporary edge list SetLength(pEdges, dwNumFaces*6); dwNumEdges:= 0;
// For each face for i:= 0 to (dwNumFaces - 1) do begin wFace0 := pIndices[3*i+0]; wFace1 := pIndices[3*i+1]; wFace2 := pIndices[3*i+2];
v0 := pVertices[wFace0].p; v1 := pVertices[wFace1].p; v2 := pVertices[wFace2].p;
// Transform vertices or transform light? D3DXVec3Cross(vNormal, D3DXVec3Subtract(v001, v2, v1)^, D3DXVec3Subtract(v002, v1, v0)^);
if (D3DXVec3Dot(vNormal, vLight) >= 0.0) then begin AddEdge(pEdges, dwNumEdges, wFace0, wFace1); AddEdge(pEdges, dwNumEdges, wFace1, wFace2); AddEdge(pEdges, dwNumEdges, wFace2, wFace0); end; end;
for i:= 0 to (dwNumEdges - 1) do begin v1 := pVertices[pEdges[2*i+0]].p; v2 := pVertices[pEdges[2*i+1]].p; D3DXVec3Scale(v001, vLight, 10); // D3DXVECTOR3 v3 = v1 - vLight*10; D3DXVec3Subtract(v3, v1, v001); // D3DXVECTOR3 v4 = v2 - vLight*10; D3DXVec3Subtract(v4, v2, v001);
// Add a quad (two triangles) to the vertex list m_pVertices[m_dwNumVertices] := v1; Inc(m_dwNumVertices); m_pVertices[m_dwNumVertices] := v2; Inc(m_dwNumVertices); m_pVertices[m_dwNumVertices] := v3; Inc(m_dwNumVertices);
m_pVertices[m_dwNumVertices] := v2; Inc(m_dwNumVertices); m_pVertices[m_dwNumVertices] := v4; Inc(m_dwNumVertices); m_pVertices[m_dwNumVertices] := v3; Inc(m_dwNumVertices); end; // Delete the temporary edge list SetLength(pEdges, 0);
// Unlock the geometry buffers pMesh.UnlockVertexBuffer; pMesh.UnlockIndexBuffer;
Result := S_OK; end;
-
А с каких пор примеры из СДК на дельфе? :)) Спасибо!
-
> А с каких пор примеры из СДК на дельфе
С тех пор, как появился дельфи и clootie.ru;)
-
> С тех пор, как появился дельфи и clootie.ru;)
Так это не СДК. Вернее если и СДК, то не оффициальный.
Кстати, тут продолжение вопроса. У меня объект по сцене вращается и перемещается стандартными средствами Дельфи. Я правильно понимаю, нужно источник света умножить на матрицу обратную матрицы преобразования, чтобы получить правильный SV?
-
Похоже что да:
// Transform the light vector to be in object space D3DXMatrixInverse(m, nil, m_matObjectMatrix); vLight.x := Lx*m._11 + Ly*m._21 + Lz*m._31 + m._41; vLight.y := Lx*m._12 + Ly*m._22 + Lz*m._32 + m._42; vLight.z := Lx*m._13 + Ly*m._23 + Lz*m._33 + m._43;
// Build the shadow volume m_pShadowVolume.Reset; m_pShadowVolume.BuildFromMesh(m_pAirplane.GetSysMemMesh, vLight);
-
Отлично, сенька.
-
Мля. Две печатки заметил. Не средствами Дельфи, а средствами ОГЛ. И не источник умножать, а его позицию... :-[
-
Удалено модератором
-
Удалено модератором
|