bool RenderPrimitive(UInt16 address, PrimitiveInstruction opCode) { float shade = 0; // check if first vertex is a normal vector VertexInstruction vertex = Memory[address]; if (vertex.IsNormalVector) { // get the normal vector Vector3 normal = GetVertexFromTable(vertex); normal = Vector3.Transform(normal, Parent.WorldRotation); // get the first coordinate Vector3 pt = GetVertexFromTable(Memory[address + 1]); pt = Vector3.Transform(pt, Parent.D3DTS_WORLD); // check if surface is visible if (Vector3.Dot(normal, pt) <= 0) { return(false); // not visible } // if shading enabled if (opCode.IsShaded) { // both values are 14 bit fractional precision // so dot product must be dividied by 2^(14+14) to normalize from 0.0 - 1.0 // but then we multiply by 8 (2^3) to convert to a pallete index // so we divide by 2^(14+14-3) const float scale = 1.0f / (1 << 25); shade = Vector3.Dot(normal, Parent.Light) * scale; shade = Math.Min(7, Math.Max(0, shade)); } } // should we skip rendering? if (opCode.SkipRender) { return(true); // would have been visible } // prepare the vertex buffer BuildPrimitive(address, Parent.GetColor(opCode.ColorIndex, shade), opCode.RenderMode); return(true); }
void BuildPrimitive(UInt16 address, Color color, Mathbox.RenderMode renderMode) { // add points to buffer for (int numVertices = 0; ;) { VertexInstruction vertex = Memory[++address]; Vertices[numVertices++] = Vector3.Transform(GetVertexFromTable(vertex), Parent.D3DTS_WORLD); // is this the last point of the plygon? if (vertex.IsLastVertex) { #if DEBUG if (MaxVertices < numVertices) { MaxVertices = numVertices; Debug.WriteLine($"Max Vertices = {MaxVertices}"); } #endif DisplayListManager.AddPrimitive(renderMode, Vertices, numVertices, color); return; } } }
Vector3 GetVertexFromTable(VertexInstruction vertex) { return(Parent.GetVectorAt((UInt16)(VertexTableAddr + vertex.VertexOffset))); }