00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "std3d.h"
00027
00028 #include "3d/patchuv_locator.h"
00029
00030 using namespace std;
00031 using namespace NLMISC;
00032
00033 namespace NL3D
00034 {
00035
00036
00037
00038 void CPatchUVLocator::build(const CPatch *patchCenter, sint edgeCenter, CPatch::CBindInfo &bindInfo)
00039 {
00040 nlassert(bindInfo.Zone);
00041
00042 _CenterPatch= const_cast<CPatch*>(patchCenter);
00043 _CenterPatchEdge= edgeCenter;
00044 _NPatchs= bindInfo.NPatchs;
00045
00046
00047
00048 _SameEdgeOrder= true;
00049
00050
00051
00052 for(sint i=0; i<_NPatchs; i++)
00053 {
00054
00055 sint edgeNeighbor= bindInfo.Edge[i];
00056 CPatch *paNeighbor= bindInfo.Next[i];
00057 _NeighborPatch[i]= paNeighbor;
00058
00059
00060
00061
00062 CVector2f &uvI= _NeighborBasis[i].UvI;
00063 CVector2f &uvJ= _NeighborBasis[i].UvJ;
00064 CVector2f &uvP= _NeighborBasis[i].UvP;
00065
00066
00067
00068
00069 sint rotation= (edgeCenter - edgeNeighbor + 4) & 3;
00070
00071 float scX, scY;
00072
00073 if( (edgeNeighbor&1)==0 )
00074 {
00075 scX= 1;
00076
00077
00078 scY= (float)paNeighbor->getOrderForEdge(edgeNeighbor) / (float)patchCenter->getOrderForEdge(edgeCenter);
00079
00080
00081 if(bindInfo.MultipleBindNum!=0)
00082 scY/= bindInfo.MultipleBindNum;
00083 if(_NPatchs>1)
00084 scY*= _NPatchs;
00085
00086 if(scY!=1)
00087 _SameEdgeOrder= false;
00088 }
00089 else
00090 {
00091 scY= 1;
00092
00093
00094 scX= (float)paNeighbor->getOrderForEdge(edgeNeighbor) / (float)patchCenter->getOrderForEdge(edgeCenter);
00095
00096
00097 if(bindInfo.MultipleBindNum!=0)
00098 scX/= bindInfo.MultipleBindNum;
00099 if(_NPatchs>1)
00100 scX*= _NPatchs;
00101
00102 if(scX!=1)
00103 _SameEdgeOrder= false;
00104 }
00105
00106 switch(rotation)
00107 {
00108 case 0: uvI.set(-scX, 0); uvJ.set(0, -scY); break;
00109 case 1: uvI.set(0, -scY); uvJ.set(scX, 0); break;
00110 case 2: uvI.set(scX, 0); uvJ.set(0, scY); break;
00111 case 3: uvI.set(0, scY); uvJ.set(-scX, 0); break;
00112 }
00113
00114
00115
00116
00117
00118 CVector2f uvCenter;
00119 CVector2f uvNeighbor;
00120 float decal;
00121
00122
00123 float ocS= patchCenter->getOrderS();
00124 float ocT= patchCenter->getOrderT();
00125
00126 if(_NPatchs>1)
00127 {
00128
00129 decal= (float)i / _NPatchs;
00130 }
00131 else
00132 decal= 0;
00133
00134 switch(edgeCenter)
00135 {
00136 case 0: uvCenter.set(0, decal*ocT); break;
00137 case 1: uvCenter.set(decal*ocS, ocT); break;
00138 case 2: uvCenter.set(ocS, (1-decal)*ocT); break;
00139 case 3: uvCenter.set((1-decal)*ocS, 0); break;
00140 };
00141
00142
00143 float onS= paNeighbor->getOrderS();
00144 float onT= paNeighbor->getOrderT();
00145
00146 if(bindInfo.MultipleBindNum!=0)
00147 {
00148
00149 sint id= (bindInfo.MultipleBindNum-1) - bindInfo.MultipleBindId;
00150
00151 decal= (float)id / bindInfo.MultipleBindNum;
00152 }
00153 else
00154 decal= 0;
00155
00156 switch(edgeNeighbor)
00157 {
00158 case 0: uvNeighbor.set(0, (1-decal)*onT); break;
00159 case 1: uvNeighbor.set((1-decal)*onS, onT); break;
00160 case 2: uvNeighbor.set(onS, decal*onT); break;
00161 case 3: uvNeighbor.set(decal*onS, 0); break;
00162 };
00163
00164
00165
00166
00167
00168 uvP= uvNeighbor - uvCenter.x * uvI - uvCenter.y * uvJ;
00169
00170 }
00171 }
00172
00173
00174
00175 uint CPatchUVLocator::selectPatch(const CVector2f &uvIn)
00176 {
00177 if(_NPatchs==1)
00178 return 0;
00179 else
00180 {
00181
00182 float selection=0.0;
00183 uint os= _CenterPatch->getOrderS();
00184 uint ot= _CenterPatch->getOrderT();
00185 switch(_CenterPatchEdge)
00186 {
00187 case 0: selection= uvIn.y / ot; break;
00188 case 1: selection= uvIn.x / os; break;
00189 case 2: selection= (ot-uvIn.y) / ot; break;
00190 case 3: selection= (os-uvIn.x) / os; break;
00191 }
00192
00193 sint sel= (sint)floor(selection*_NPatchs);
00194 clamp(sel, 0, _NPatchs-1);
00195
00196 return sel;
00197 }
00198 }
00199
00200
00201
00202 void CPatchUVLocator::locateUV(const CVector2f &uvIn, uint patch, CPatch *&patchOut, CVector2f &uvOut)
00203 {
00204 if(_NPatchs==1)
00205 {
00206
00207 _NeighborBasis[0].mulPoint(uvIn, uvOut);
00208 patchOut= _NeighborPatch[0];
00209 }
00210 else
00211 {
00212
00213 _NeighborBasis[patch].mulPoint(uvIn, uvOut);
00214 patchOut= _NeighborPatch[patch];
00215 }
00216 }
00217
00218
00219
00220 }