/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #ifndef CRYINCLUDE_EDITOR_LIGHTMAPCOMPILER_SIMPLETRIANGLERASTERIZER_H #define CRYINCLUDE_EDITOR_LIGHTMAPCOMPILER_SIMPLETRIANGLERASTERIZER_H #pragma once class CSimpleTriangleRasterizer { public: class IRasterizeSink { public: //! is called once per triangel for the first possible visible line //! /param iniStartY virtual void Triangle(const int iniStartY) { } //! callback function //! /param infXLeft included - not clipped against left and reight border //! /param infXRight excluded - not clipped against left and reight border //! /param iniXLeft included //! /param iniXRight excluded //! /param iniY virtual void Line(const float infXLeft, const float infXRight, const int iniXLeft, const int iniXRight, const int iniY) = 0; }; typedef unsigned long DWORD; // ----------------------------------------------------- //! implementation sink sample class CDWORDFlatFill : public IRasterizeSink { public: //! constructor CDWORDFlatFill(DWORD* inpBuffer, const DWORD indwPitchInPixels, DWORD indwValue) { m_dwValue = indwValue; m_pBuffer = inpBuffer; m_dwPitchInPixels = indwPitchInPixels; } virtual void Triangle(const int iniY) { m_pBufferLine = &m_pBuffer[iniY * m_dwPitchInPixels]; } virtual void Line(const float infXLeft, const float infXRight, const int iniLeft, const int iniRight, const int iniY) { DWORD* mem = &m_pBufferLine[iniLeft]; for (int x = iniLeft; x < iniRight; x++) { *mem++ = m_dwValue; } m_pBufferLine += m_dwPitchInPixels; } private: DWORD m_dwValue; //!< fill value DWORD* m_pBufferLine; //!< to get rid of the multiplication per line DWORD m_dwPitchInPixels; //!< in DWORDS, not in Bytes DWORD* m_pBuffer; //!< pointer to the buffer }; // ----------------------------------------------------- //! constructor //! /param iniWidth excluded //! /param iniHeight excluded CSimpleTriangleRasterizer(const int iniWidth, const int iniHeight) { m_iMinX = 0; m_iMinY = 0; m_iMaxX = iniWidth - 1; m_iMaxY = iniHeight - 1; } /* //! constructor //! /param iniMinX included //! /param iniMinY included //! /param iniMaxX included //! /param iniMaxY included CSimpleTriangleRasterizer( const int iniMinX, const int iniMinY, const int iniMaxX, const int iniMaxY ) { m_iMinX=iniMinX; m_iMinY=iniMinY; m_iMaxX=iniMaxX; m_iMaxY=iniMaxY; } */ //! simple triangle filler with clipping (optimizable), not subpixel correct //! /param pBuffer pointer o the color buffer //! /param indwWidth width of the color buffer //! /param indwHeight height of the color buffer //! /param x array of the x coordiantes of the three vertices //! /param y array of the x coordiantes of the three vertices //! /param indwValue value of the triangle void DWORDFlatFill(DWORD* inpBuffer, const DWORD indwPitchInPixels, float x[3], float y[3], DWORD indwValue, bool inbConservative) { CDWORDFlatFill pix(inpBuffer, indwPitchInPixels, indwValue); if (inbConservative) { CallbackFillConservative(x, y, &pix); } else { CallbackFillSubpixelCorrect(x, y, &pix); } } // Rectangle around triangle - more stable - use for debugging purpose void CallbackFillRectConservative(float x[3], float y[3], IRasterizeSink * inpSink); //! subpixel correct triangle filler (conservative or not conservative) //! \param pBuffer pointe to the DWORD //! \param indwWidth width of the buffer pBuffer pointes to //! \param indwHeight height of the buffer pBuffer pointes to //! \param x array of the x coordiantes of the three vertices //! \param y array of the x coordiantes of the three vertices //! \param inpSink pointer to the sink interface (is called per triangle and per triangle line) void CallbackFillConservative(float x[3], float y[3], IRasterizeSink * inpSink); //! subpixel correct triangle filler (conservative or not conservative) //! \param pBuffer pointe to the DWORD //! \param indwWidth width of the buffer pBuffer pointes to //! \param indwHeight height of the buffer pBuffer pointes to //! \param x array of the x coordiantes of the three vertices //! \param y array of the x coordiantes of the three vertices //! \param inpSink pointer to the sink interface (is called per triangle and per triangle line) void CallbackFillSubpixelCorrect(float x[3], float y[3], IRasterizeSink * inpSink); //! //! /param inoutfX //! /param inoutfY //! /param infAmount could be positive or negative static void ShrinkTriangle(float inoutfX[3], float inoutfY[3], float infAmount); private: // Clipping Rect; int m_iMinX; //!< minimum x value included int m_iMinY; //!< minimum y value included int m_iMaxX; //!< maximum x value included int m_iMaxY; //!< maximum x value included void lambertHorizlineConservative(float fx1, float fx2, int y, IRasterizeSink* inpSink); void lambertHorizlineSubpixelCorrect(float fx1, float fx2, int y, IRasterizeSink* inpSink); void CopyAndSortY(const float infX[3], const float infY[3], float outfX[3], float outfY[3]); }; // extension ideas: // * callback with coverage mask (possible non ordered sampling) // * z-buffer behaviour // * gouraud shading // * texture mapping with nearest/bicubic/bilinear filter // * further primitives: thick line, ellipse // * build a template version // * #endif // CRYINCLUDE_EDITOR_LIGHTMAPCOMPILER_SIMPLETRIANGLERASTERIZER_H