khanat-opennel-code/code/nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm_plane.cpp
2010-05-06 02:08:41 +02:00

706 lines
22 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Precompiled header
#include "stdafx.h"
#include "export_nel.h"
#include <vector>
using namespace std;
using namespace NLMISC;
using namespace NL3D;
#include "calc_lm_plane.h"
// -----------------------------------------------------------------------------------------------
SLMPlane::SLMPlane ()
{
nNbLayerUsed = 1;
x = y = 0; w = h = 1; msk.resize(1); msk[0] = 0;
col.resize(1);
col[0].R = col[0].G = col[0].B = col[0].A = 0.0f;
ray.resize(1);
ray[0] = 0;
}
// -----------------------------------------------------------------------------------------------
void SLMPlane::newLayer ()
{
col.resize( w*h*(nNbLayerUsed+1), CRGBAF(0.0f,0.0f,0.0f,0.0f) );
nNbLayerUsed += 1;
}
// -----------------------------------------------------------------------------------------------
bool SLMPlane::isAllBlack (uint8 nLayerNb)
{
for( uint32 i = 0; i < w*h; ++i )
if( (col[i+w*h*nLayerNb].R > 0.06f) || // around 15/255
(col[i+w*h*nLayerNb].G > 0.06f) ||
(col[i+w*h*nLayerNb].B > 0.06f) )
return false; // Not all is black
return true;
}
// -----------------------------------------------------------------------------------------------
void SLMPlane::copyColToBitmap8x2 (CBitmap* pImage, uint32 nLayerNb, CRGBAF lA, CRGBAF lD)
{
if( nLayerNb >= nNbLayerUsed )
return;
if( ( pImage->getWidth() != w ) ||
( pImage->getHeight() != h ) )
{
pImage->resize(w,h);
}
/*
We want to compress the RGBA lightmap L32 into a (lA,lD,L8) lightmap, where lA and lD are constants.
lA and lD are given, so we have to compute L8.
In the standard 32 bits Lightmap shader, for a single lightmap, the final formula is:
O= L32*F*T
where:
O: output
L32: the lightmap (actually in 16 bits RGB)
F: the lightmap factor (for light animation or activation)
T: the diffuse texture
In the "8bits *2" Lightmap shader, for a single lightmap, the final formula is:
O= (mA+L8*mD)*F*T*2
where:
L8: the 8 bits lightmap
mA: Material Lightmap Ambient term. equal to lA/2, for convenience, and avoid too much "ambient clamping"
mD: Material Lightmap Diffuse term. equal to lD.
*2: the pixel shader multiplyBy2, to allow some TextureDiffuse burn.
Hence, we have to solve the simple equation for L8:
(lA/2+L8*lD)*2 = L32
which result into:
L8= ((L32-lA) / lD) * 0.5
We define Vector0/Vector1 operation as the projection operation:
scalar= Vector0*Vector1 / sqrnorm(Vector1).
*/
// the dir vector lD
CVector vDir(lD.R, lD.G, lD.B);
float OOSqrNorm= 0;
if(!vDir.isNull())
OOSqrNorm= 1.0f / vDir.sqrnorm();
// for all pixel of the layer
CObjectVector<uint8> &vBitmap = pImage->getPixels();
for( uint32 i = 0; i < w*h; ++i )
{
const CRGBAF &srcCol= col[i+w*h*nLayerNb];
// find the factor f, such that f= (L32-lA)/lD
float f;
f= vDir * CVector(srcCol.R - lA.R, srcCol.G - lA.G, srcCol.B - lA.B);
f*= OOSqrNorm;
// we are in multiply x2 => compress to 8 bits from 0 to 127
const float fMult = 127.0f;
f*= fMult;
clamp(f, 0.f, 255.0f);
uint8 f8= (uint8)f;
vBitmap[4*i+0] = f8;
vBitmap[4*i+1] = f8;
vBitmap[4*i+2] = f8;
if (msk[i] != 0)
vBitmap[4*i+3] = 255;
else
vBitmap[4*i+3] = 0;
}
}
// -----------------------------------------------------------------------------------------------
void SLMPlane::copyColToBitmap32 (CBitmap* pImage, uint32 nLayerNb)
{
if( nLayerNb >= nNbLayerUsed )
return;
if( ( pImage->getWidth() != w ) ||
( pImage->getHeight() != h ) )
{
pImage->resize(w,h);
}
CObjectVector<uint8> &vBitmap = pImage->getPixels();
for( uint32 i = 0; i < w*h; ++i )
{
// if we are in multiply x2 we have to set the following value to 127.0 else set to 255.0
// By default we are in multiply x2 in Lightmap 8 bits mode but not in 32 bits mode
const float fMult = 255.0;
if( (fMult*col[i+w*h*nLayerNb].R) > 255.0 )
vBitmap[4*i+0] = 255;
else
vBitmap[4*i+0] = (uint8)(fMult*col[i+w*h*nLayerNb].R);
if( (fMult*col[i+w*h*nLayerNb].G) > 255.0 )
vBitmap[4*i+1] = 255;
else
vBitmap[4*i+1] = (uint8)(fMult*col[i+w*h*nLayerNb].G);
if( (fMult*col[i+w*h*nLayerNb].B) > 255.0 )
vBitmap[4*i+2] = 255;
else
vBitmap[4*i+2] = (uint8)(fMult*col[i+w*h*nLayerNb].B);
// Mask go into alpha channel
if (msk[i] != 0)
vBitmap[4*i+3] = 255;
else
vBitmap[4*i+3] = 0;
}
}
// -----------------------------------------------------------------------------------------------
// Put me in the plane Dst (copy the col and mask or mask only)
void SLMPlane::putIn (SLMPlane &Dst, bool bMaskOnly)
{
uint32 a, b, c;
while (this->nNbLayerUsed > Dst.nNbLayerUsed)
Dst.newLayer();
if( ( (this->w + this->x) > Dst.w ) || ( (this->h + this->y) > Dst.h ) )
{
a = 0; b = 0;
}
for( b = 0; b < this->h; ++b )
for( a = 0; a < this->w; ++a )
if( this->msk[a+b*this->w] != 0 )
{
Dst.msk[(this->x+a)+(this->y+b)*Dst.w] = this->msk[a+b*this->w];
if( bMaskOnly == false )
for( c = 0; c < this->nNbLayerUsed; ++c )
Dst.col[(this->x+a)+(this->y+b)*Dst.w+Dst.w*Dst.h*c] = this->col[a+b*this->w+w*h*c];
}
}
// -----------------------------------------------------------------------------------------------
// Test the mask between me and the plane dst (with my decalage)
bool SLMPlane::testIn (SLMPlane &Dst)
{
uint32 a, b;
for( b = 0; b < this->h; ++b )
for( a = 0; a < this->w; ++a )
if( this->msk[a+b*this->w] != 0 )
if( Dst.msk[(this->x+a)+(this->y+b)*Dst.w] != 0 )
return false;
return true;
}
// -----------------------------------------------------------------------------------------------
// Try all position to put me in the plane dst
bool SLMPlane::tryAllPosToPutIn (SLMPlane &Dst)
{
uint32 i, j;
if( this->w > Dst.w ) return false;
if( this->h > Dst.h ) return false;
// For all position test if the Src plane can be put in
for( j = 0; j < (Dst.h-this->h); ++j )
for( i = 0; i < (Dst.w-this->w); ++i )
{
this->x = i; this->y = j;
if( testIn( Dst ) )
return true;
}
return false;
}
// -----------------------------------------------------------------------------------------------
// Do not stretch the image inside the plane just enlarge and fill with black
void SLMPlane::resize (uint32 nNewSizeX, uint32 nNewSizeY)
{
vector<uint8> vImgTemp;
vector<CRGBAF> vImgTemp2;
uint32 i, j, k;
// Resize the mask
vImgTemp.resize(nNewSizeX*nNewSizeY);
for( i = 0; i < nNewSizeX*nNewSizeY; ++i )
vImgTemp[i] = 0;
for( j = 0; j < min(this->h,nNewSizeY); ++j )
for( i = 0; i < min(this->w,nNewSizeX); ++i )
vImgTemp[i+j*nNewSizeX] = this->msk[i+j*this->w];
this->msk.resize(nNewSizeX*nNewSizeY);
for( i = 0; i < nNewSizeX*nNewSizeY; ++i )
this->msk[i] = vImgTemp[i];
// Resize the raytrace information
for( i = 0; i < nNewSizeX*nNewSizeY; ++i )
vImgTemp[i] = 0;
for( j = 0; j < min(this->h,nNewSizeY); ++j )
for( i = 0; i < min(this->w,nNewSizeX); ++i )
vImgTemp[i+j*nNewSizeX] = this->ray[i+j*this->w];
this->ray.resize(nNewSizeX*nNewSizeY);
for( i = 0; i < nNewSizeX*nNewSizeY; ++i )
this->ray[i] = vImgTemp[i];
// The same as the mask but for the bitmap
vImgTemp2.resize(nNewSizeX*nNewSizeY*nNbLayerUsed);
for( i = 0; i < nNewSizeX*nNewSizeY*nNbLayerUsed; ++i )
{ vImgTemp2[i].R = vImgTemp2[i].G = vImgTemp2[i].B = vImgTemp2[i].A = 0.0f; }
for( k = 0; k < nNbLayerUsed; ++k )
for( j = 0; j < min(this->h,nNewSizeY); ++j )
for( i = 0; i < min(this->w,nNewSizeX); ++i )
vImgTemp2[i+j*nNewSizeX+nNewSizeX*nNewSizeY*k] = this->col[i+j*this->w+w*h*k];
this->col.resize(nNewSizeX*nNewSizeY*nNbLayerUsed);
for( i = 0; i < nNewSizeX*nNewSizeY*nNbLayerUsed; ++i )
this->col[i] = vImgTemp2[i];
this->w = nNewSizeX;
this->h = nNewSizeY;
}
// -----------------------------------------------------------------------------------------------
// Stretch a plane by a given factor 4.0 -> multiply its size by 4 and 0.5 -> halves its size
// Take care the decalage is affected by the scaling factor (like homothetie)
void SLMPlane::stretch (double osFactor)
{
if( osFactor < 0.0 )
osFactor = 0.0;
uint32 nNewSizeX = (uint32)(this->w * osFactor);
uint32 nNewSizeY = (uint32)(this->h * osFactor);
vector<uint8> vImgTemp;
vector<uint8> vImgTempRay;
vector<CRGBAF> vImgTemp2;
uint32 i, j, k;
// Reduce the color
vImgTempRay.resize(nNewSizeX * nNewSizeY);
for( i = 0; i < nNewSizeX*nNewSizeY; ++i )
vImgTempRay[i] = 0;
vImgTemp2.resize( nNewSizeX * nNewSizeY * nNbLayerUsed );
for( i = 0; i < nNewSizeX*nNewSizeY*nNbLayerUsed; ++i )
{ vImgTemp2[i].R = vImgTemp2[i].G = vImgTemp2[i].B = vImgTemp2[i].A = 0.0f; }
vImgTemp.resize( nNewSizeX * nNewSizeY );
for( i = 0; i < nNewSizeX*nNewSizeY; ++i )
vImgTemp[i] = 0;
double dx, dy, x, y;
if( osFactor > 1.0 ) // Enlarge the image
{
dx = 1.0/osFactor;
dy = 1.0/osFactor;
y = 0.0;
for( j = 0; j < nNewSizeY; ++j )
{
x = 0.0;
for( i = 0; i < nNewSizeX; ++i )
{
if( this->msk[((sint32)x)+((sint32)y)*this->w] != 0 )
{
vImgTemp[i+j*nNewSizeX] = 1;
}
for( k = 0; k < nNbLayerUsed; ++k )
{
vImgTemp2[i+j*nNewSizeX+nNewSizeX*nNewSizeY*k].R += col[((sint32)x)+((sint32)y)*w+w*h*k].R;
vImgTemp2[i+j*nNewSizeX+nNewSizeX*nNewSizeY*k].G += col[((sint32)x)+((sint32)y)*w+w*h*k].G;
vImgTemp2[i+j*nNewSizeX+nNewSizeX*nNewSizeY*k].B += col[((sint32)x)+((sint32)y)*w+w*h*k].B;
vImgTemp2[i+j*nNewSizeX+nNewSizeX*nNewSizeY*k].A += 1.0f;
}
vImgTempRay[i+j*nNewSizeX] = ray[((sint32)x)+((sint32)y)*w];
x += dx;
}
y += dy;
}
}
else // Reduce image
{
dx = osFactor;
dy = osFactor;
y = 0.0;
for( j = 0; j < this->h; ++j )
{
x = 0.0;
for( i = 0; i < this->w; ++i )
{
if( this->msk[i+j*this->w] != 0 )
{
vImgTemp[((sint32)x)+((sint32)y)*nNewSizeX] = 1;
}
for( k = 0; k < nNbLayerUsed; ++k )
{
vImgTemp2[((sint32)x)+((sint32)y)*nNewSizeX+nNewSizeX*nNewSizeY*k].R += col[i+j*w+w*h*k].R;
vImgTemp2[((sint32)x)+((sint32)y)*nNewSizeX+nNewSizeX*nNewSizeY*k].G += col[i+j*w+w*h*k].G;
vImgTemp2[((sint32)x)+((sint32)y)*nNewSizeX+nNewSizeX*nNewSizeY*k].B += col[i+j*w+w*h*k].B;
vImgTemp2[((sint32)x)+((sint32)y)*nNewSizeX+nNewSizeX*nNewSizeY*k].A += 1.0f;
}
vImgTempRay[((sint32)x)+((sint32)y)*nNewSizeX] = ray[i+j*w];
x += dx;
}
y += dy;
}
}
for( k = 0; k < nNbLayerUsed; ++k )
for( j = 0; j < nNewSizeY; ++j )
for( i = 0; i < nNewSizeX; ++i )
if( vImgTemp2[i+j*nNewSizeX+nNewSizeX*nNewSizeY*k].A > 1.0f )
{
vImgTemp2[i+j*nNewSizeX+nNewSizeX*nNewSizeY*k].R /= vImgTemp2[i+j*nNewSizeX+nNewSizeX*nNewSizeY*k].A;
vImgTemp2[i+j*nNewSizeX+nNewSizeX*nNewSizeY*k].G /= vImgTemp2[i+j*nNewSizeX+nNewSizeX*nNewSizeY*k].A;
vImgTemp2[i+j*nNewSizeX+nNewSizeX*nNewSizeY*k].B /= vImgTemp2[i+j*nNewSizeX+nNewSizeX*nNewSizeY*k].A;
vImgTemp2[i+j*nNewSizeX+nNewSizeX*nNewSizeY*k].A = 1.0f;
}
col.resize( nNewSizeX * nNewSizeY * nNbLayerUsed );
for( i = 0; i < nNewSizeX*nNewSizeY*nNbLayerUsed; ++i )
col[i] = vImgTemp2[i];
msk.resize( nNewSizeX * nNewSizeY );
for( i = 0; i < nNewSizeX*nNewSizeY; ++i )
msk[i] = vImgTemp[i];
ray.resize( nNewSizeX * nNewSizeY );
for( i = 0; i < nNewSizeX*nNewSizeY; ++i )
ray[i] = vImgTempRay[i];
this->w = nNewSizeX;
this->h = nNewSizeY;
this->x = (sint32)(this->x * osFactor);
this->y = (sint32)(this->y * osFactor);
}
// -----------------------------------------------------------------------------------------------
void SLMPlane::createFromPlane (SLMPlane &Src)
{
uint i;
// Resize to the same size
resize(Src.w,Src.h);
x = Src.x;
y = Src.y;
// Copy the mask
for( i = 0; i < Src.w*Src.h; ++i )
msk[i] = Src.msk[i];
// Copy the faces
faces.resize(Src.faces.size());
for( i = 0; i < Src.faces.size(); ++i )
faces[i] = Src.faces[i];
}
// -----------------------------------------------------------------------------------------------
void SLMPlane::copyFirstLayerTo (SLMPlane &Dst, uint8 nDstLayer)
{
uint i;
if( ( Dst.w != w ) || ( Dst.h != h ) )
Dst.resize( w, h );
while( nDstLayer >= Dst.nNbLayerUsed )
Dst.newLayer();
for( i = 0; i < w*h; ++i )
Dst.col[i+w*h*nDstLayer] = col[i];
}
// -----------------------------------------------------------------------------------------------
void SLMPlane::contourDetect ()
{
uint i, j;
vector<uint8> vImgTemp;
vImgTemp.resize(w*h);
for( i = 0; i < w*h; ++i )
vImgTemp[i] = 0;
for( j = 0; j < h; ++j )
for( i = 0; i < w; ++i )
{
if( i > 0 )
if( ray[i+j*w] != ray[i-1+j*w] )
vImgTemp[i+j*w] = 1;
if( i < (w-1) )
if( ray[i+j*w] != ray[i+1+j*w] )
vImgTemp[i+j*w] = 1;
if( j > 0 )
if( ray[i+j*w] != ray[i+(j-1)*w] )
vImgTemp[i+j*w] = 1;
if( j < (h-1) )
if( ray[i+j*w] != ray[i+(j+1)*w] )
vImgTemp[i+j*w] = 1;
if( ray[i+j*w] == 255 )
vImgTemp[i+j*w] = 1;
}
for( i = 0; i < w*h; ++i )
ray[i] = vImgTemp[i];
/*{
CBitmap b;
COFile f( "c:\\temp\\gloup.tga" );
b.resize(w,h);
CObjectVector<uint8>&bits = b.getPixels();
for( i = 0; i < w*h; ++i )
{
bits[i*4+0] = bits[i*4+1] = bits[i*4+2] = bits[i*4+3] = ray[i]*255;
}
b.writeTGA( f, 32 );
}*/
}
// -----------------------------------------------------------------------------------------------
void SLMPlane::andRayWidthMask ()
{
for( uint i = 0; i < w*h; ++i )
if( ray[i] == 0 )
msk[i] = 0;
}
// -----------------------------------------------------------------------------------------------
bool SLMPlane::isInTriangleOrEdge( double x, double y,
double xt1, double yt1,
double xt2, double yt2,
double xt3, double yt3)
{
// Test vector T1X and T1T2
double sign1 = ((xt2-xt1)*(y-yt1) - (yt2-yt1)*(x-xt1));
// Test vector T2X and T2T3
double sign2 = ((xt3-xt2)*(y-yt2) - (yt3-yt2)*(x-xt2));
// Test vector T3X and T3T1
double sign3 = ((xt1-xt3)*(y-yt3) - (yt1-yt3)*(x-xt3));
if( (sign1 <= 0.0)&&(sign2 <= 0.0)&&(sign3 <= 0.0) )
return true;
if( (sign1 >= 0.0)&&(sign2 >= 0.0)&&(sign3 >= 0.0) )
return true;
return false;
}
// -----------------------------------------------------------------------------------------------
bool SLMPlane::segmentIntersection( double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4)
{
double denominator = (y4-y3)*(x2-x1) - (x4-x3)*(y2-y1);
if( denominator == 0.0 )
return false; // The segment are colinear
double k = ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3) ) / denominator;
if( (k<=0.0) || (k>=1.0) ) return false;
k = ( (x2-x1)*(y1-y3) - (y2-y1)*(x1-x3) ) / denominator;
if( (k<=0.0) || (k>=1.0) ) return false;
return true;
}
// -----------------------------------------------------------------------------------------------
void SLMPlane::createFromFace (CMesh::CFace *pF)
{
double lumx1 = pF->Corner[0].Uvws[1].U, lumy1 = pF->Corner[0].Uvws[1].V,
lumx2 = pF->Corner[1].Uvws[1].U, lumy2 = pF->Corner[1].Uvws[1].V,
lumx3 = pF->Corner[2].Uvws[1].U, lumy3 = pF->Corner[2].Uvws[1].V;
double minx, miny;
double maxx, maxy;
sint32 j, k;
minx = lumx1;
if( minx > lumx2 ) minx = lumx2;
if( minx > lumx3 ) minx = lumx3;
maxx = lumx1;
if( maxx < lumx2 ) maxx = lumx2;
if( maxx < lumx3 ) maxx = lumx3;
miny = lumy1;
if( miny > lumy2 ) miny = lumy2;
if( miny > lumy3 ) miny = lumy3;
maxy = lumy1;
if( maxy < lumy2 ) maxy = lumy2;
if( maxy < lumy3 ) maxy = lumy3;
// Put the piece in the new basis (nPosX,nPosY)
sint32 decalX = ((sint32)floor(minx-0.5)) - x;
sint32 decalY = ((sint32)floor(miny-0.5)) - y;
sint32 sizeX = 1 + ((sint32)floor(maxx+0.5)) - ((sint32)floor(minx-0.5));
sint32 sizeY = 1 + ((sint32)floor(maxy+0.5)) - ((sint32)floor(miny-0.5));
lumx1 -= x; lumy1 -= y;
lumx2 -= x; lumy2 -= y;
lumx3 -= x; lumy3 -= y;
// The square interact with the triangle if an edge of the square is cut by an edge of the triangle
// Or the square is in the triangle
for (j = decalY; j < (decalY+sizeY-1); ++j)
for (k = decalX; k < (decalX+sizeX-1); ++k)
{
// Is the square (j,k) is interacting with the triangle
// This means : The square contains a point of the triangle (can be done for the 3 points)
// The triangle contains a point of the square
// If so then we have to turn on all the 4 pixels of the square
if( isInTriangleOrEdge(k+0.5,j+0.5,lumx1,lumy1,lumx2,lumy2,lumx3,lumy3) ||
isInTriangleOrEdge(k+1.5,j+0.5,lumx1,lumy1,lumx2,lumy2,lumx3,lumy3) ||
isInTriangleOrEdge(k+0.5,j+1.5,lumx1,lumy1,lumx2,lumy2,lumx3,lumy3) ||
isInTriangleOrEdge(k+1.5,j+1.5,lumx1,lumy1,lumx2,lumy2,lumx3,lumy3) )
{
msk[k + j *w] = 1;
msk[1+k + j *w] = 1;
msk[k + (1+j)*w] = 1;
msk[1+k + (1+j)*w] = 1;
}
else
if( segmentIntersection(k+0.5, j+0.5, k+1.5, j+0.5, lumx1, lumy1, lumx2, lumy2) ||
segmentIntersection(k+0.5, j+0.5, k+1.5, j+0.5, lumx2, lumy2, lumx3, lumy3) ||
segmentIntersection(k+0.5, j+0.5, k+1.5, j+0.5, lumx3, lumy3, lumx1, lumy1) ||
segmentIntersection(k+0.5, j+0.5, k+0.5, j+1.5, lumx1, lumy1, lumx2, lumy2) ||
segmentIntersection(k+0.5, j+0.5, k+0.5, j+1.5, lumx2, lumy2, lumx3, lumy3) ||
segmentIntersection(k+0.5, j+0.5, k+0.5, j+1.5, lumx3, lumy3, lumx1, lumy1) ||
segmentIntersection(k+1.5, j+1.5, k+1.5, j+0.5, lumx1, lumy1, lumx2, lumy2) ||
segmentIntersection(k+1.5, j+1.5, k+1.5, j+0.5, lumx2, lumy2, lumx3, lumy3) ||
segmentIntersection(k+1.5, j+1.5, k+1.5, j+0.5, lumx3, lumy3, lumx1, lumy1) ||
segmentIntersection(k+1.5, j+1.5, k+0.5, j+1.5, lumx1, lumy1, lumx2, lumy2) ||
segmentIntersection(k+1.5, j+1.5, k+0.5, j+1.5, lumx2, lumy2, lumx3, lumy3) ||
segmentIntersection(k+1.5, j+1.5, k+0.5, j+1.5, lumx3, lumy3, lumx1, lumy1) )
{
msk[k + j *w] = 1;
msk[1+k + j *w] = 1;
msk[k + (1+j)*w] = 1;
msk[1+k + (1+j)*w] = 1;
}
}
// For all the points of the triangle update the square
msk[((sint32)(lumx1-0.5)) + ((sint32)(lumy1-0.5)) *w] = 1;
msk[1+((sint32)(lumx1-0.5)) + ((sint32)(lumy1-0.5)) *w] = 1;
msk[((sint32)(lumx1-0.5)) + (1+((sint32)(lumy1-0.5)))*w] = 1;
msk[1+((sint32)(lumx1-0.5)) + (1+((sint32)(lumy1-0.5)))*w] = 1;
msk[((sint32)(lumx2-0.5)) + ((sint32)(lumy2-0.5)) *w] = 1;
msk[1+((sint32)(lumx2-0.5)) + ((sint32)(lumy2-0.5)) *w] = 1;
msk[((sint32)(lumx2-0.5)) + (1+((sint32)(lumy2-0.5)))*w] = 1;
msk[1+((sint32)(lumx2-0.5)) + (1+((sint32)(lumy2-0.5)))*w] = 1;
msk[((sint32)(lumx3-0.5)) + ((sint32)(lumy3-0.5)) *w] = 1;
msk[1+((sint32)(lumx3-0.5)) + ((sint32)(lumy3-0.5)) *w] = 1;
msk[((sint32)(lumx3-0.5)) + (1+((sint32)(lumy3-0.5)))*w] = 1;
msk[1+((sint32)(lumx3-0.5)) + (1+((sint32)(lumy3-0.5)))*w] = 1;
}
// -----------------------------------------------------------------------------------------------
void SLMPlane::createFromFaceGroup (vector<CMesh::CFace*>::iterator ItFace, uint32 nNbFace)
{
uint32 i, j;
double rMinU = 1000000.0, rMaxU = -1000000.0, rMinV = 1000000.0, rMaxV = -1000000.0;
vector<CMesh::CFace*>::iterator ItParseI = ItFace;
CMesh::CFace *pF;
faces.resize( nNbFace );
for( i = 0; i < nNbFace; ++i )
{
pF = *ItParseI;
for( j = 0; j < 3; ++j )
{
if( rMinU > pF->Corner[j].Uvws[1].U ) rMinU = pF->Corner[j].Uvws[1].U;
if( rMaxU < pF->Corner[j].Uvws[1].U ) rMaxU = pF->Corner[j].Uvws[1].U;
if( rMinV > pF->Corner[j].Uvws[1].V ) rMinV = pF->Corner[j].Uvws[1].V;
if( rMaxV < pF->Corner[j].Uvws[1].V ) rMaxV = pF->Corner[j].Uvws[1].V;
}
faces[i] = pF;
++ItParseI;
}
uint32 w = ( 1 + ((sint32)floor( rMaxU + 0.5 )) - ((sint32)floor( rMinU - 0.5 )) );
uint32 h = ( 1 + ((sint32)floor( rMaxV + 0.5 )) - ((sint32)floor( rMinV - 0.5 )) );
resize( w, h );
x = ( ((sint32)floor( rMinU - 0.5 )) );
y = ( ((sint32)floor( rMinV - 0.5 )) );
for( j = 0; j < w*h; ++j )
msk[j] = 0;
ItParseI = ItFace;
for( i = 0; i < nNbFace; ++i )
{
pF = *ItParseI;
// Create Mask
createFromFace (pF);
++ItParseI;
}
}
// -----------------------------------------------------------------------------------------------
CRGBAF SLMPlane::getAverageColor (uint8 nLayerNb)
{
uint32 a, b, c, nNbPixel = 0;
CRGBAF ret (0.0f, 0.0f, 0.0f, 0.0f);
if (nLayerNb > nNbLayerUsed)
return ret;
c = nLayerNb;
for( b = 0; b < this->h; ++b )
for( a = 0; a < this->w; ++a )
if( this->msk[a+b*this->w] != 0 )
{
ret += this->col[a+b*this->w+w*h*c];
++nNbPixel;
}
if (nNbPixel > 0)
{
ret.R = ret.R / (float)nNbPixel;
ret.G = ret.G / (float)nNbPixel;
ret.B = ret.B / (float)nNbPixel;
ret.A = ret.A / (float)nNbPixel;
}
return ret;
}
// -----------------------------------------------------------------------------------------------
bool SLMPlane::isSameColorAs (uint8 nLayerNb, CRGBAF color, float precision)
{
uint32 a, b, c;
if (nLayerNb > nNbLayerUsed)
return false;
c = nLayerNb;
for( b = 0; b < this->h; ++b )
for( a = 0; a < this->w; ++a )
if( this->msk[a+b*this->w] != 0 )
{
CRGBAF lc = this->col[a+b*this->w+w*h*c];
if ((fabsf(lc.R-color.R) > precision) ||
(fabsf(lc.G-color.G) > precision) ||
(fabsf(lc.B-color.B) > precision))
return false;
}
return true;
}