/** @brief This is rewrite code of SculptMesh.cs of OpenSim for JunkBox_Lib. @file SculptMesher.cpp @author Fumi.Iseki iseki@solar-system.tuis.ac.jp @version 1.1 @date 2015 5/27 @sa http://opensimulator.org/ @sa http://wiki.secondlife.com/wiki/Sculpted_Prims:_Technical_Explanation @sa OpenSim/Region/Physics/Meshing/SculptMesh.cs @sa Viewer_Source: indra\llmath\llvolume.cpp: sculptGenerateMapVertices() */ /* * see also http://opensimulator.org/ * see also http://wiki.secondlife.com/wiki/Sculpted_Prims:_Technical_Explanation * see also OpenSim/Region/Physics/Meshing/SculptMesh.cs * see also Viewer_Source: indra\llmath\llvolume.cpp: sculptGenerateMapVertices() * We got advice from Janus Dugong * * OpenSim CONTRIBUTORS.TXT is in OpenSim.License directory. */ /* * Copyright (c) Contributors * See CONTRIBUTORS.TXT for a full list of copyright holders. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the OpenSimulator Project nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "SculptMesher.h" using namespace jbxl; /////////////////////////////////////////////////////////////////////////////////////////////// // ScupltMesh Class // void SculptMesh::init(int typ) { clear(); xscale = 2; yscale = 2; flipUV = false; flipU = false; flipV = false; sizetype = SCULPT_SIZE_OTHER; // set_type(typ); } // void SculptMesh::clear(void) { clear_data(); clear_image(); } // void SculptMesh::clear_data(void) { coords.clear(); normals.clear(); uvs.clear(); sculptTriIndex.clear(); sculptTriArray.clear(); } // void SculptMesh::clear_image(void) { int rnum = (int)sculptImage.size(); for (int i=0; i SculptMesh::MakeSculptImage(MSGraph grd) { MSGraph sculpt; sculpt.state = SCULPT_IMAGE_ERROR; if (grd.isNull() || grd.zs<3) return sculpt; int psize = grd.xs*grd.ys; double pixScale = 1.0/256.0; int offsetA = 0; // アルファチャンネルが存在する場合のオフセット bool reverse = false; // true: BGR // if (grd.color==GRAPH_COLOR_RGB || grd.color==GRAPH_COLOR_RGBA) { // nop } else if (grd.color==GRAPH_COLOR_XRGB || grd.color==GRAPH_COLOR_ARGB) { if (grd.zs==4) offsetA = psize; } else if (grd.color==GRAPH_COLOR_BGR || grd.color==GRAPH_COLOR_BGRA) { reverse = true; } else if (grd.color==GRAPH_COLOR_XBGR || grd.color==GRAPH_COLOR_ABGR) { if (grd.zs==4) offsetA = psize; reverse = true; } else { return sculpt; // none supported color mode } sculpt.getm(grd.xs, grd.ys, 3); for (int j=0; j grd) { if (grd.isNull() || grd.zs<3) return false; sizetype = GetSculptScale(grd.xs, grd.ys, &xscale, &yscale); MSGraph sculpt = MakeSculptImage(grd); if (sculpt.isNull()) return false; int xsize = grd.xs/xscale; int ysize = grd.ys/yscale; int psize = sculpt.xs*sculpt.ys; // for (int j=0; j(-rval, gval, bval)); else row.push_back(Vector( rval, gval, bval)); } } if (row.size()>0) sculptImage.push_back(row); } } sculpt.free(); return true; } // void SculptMesh::GenerateMeshData(void) { clear_data(); if (sculptImage.size()==0) { PRINT_MESG("SculptMesh::GenerateMeshData(): WARNING: image data size is 0!\n"); return; } int xs = (int)sculptImage[0].size(); int ys = (int)sculptImage.size(); int ox = xs; int oy = ys; // X方向境界処理 if (type!=SCULPT_TYPE_PLANE) { if (ys%2==0) { for (int j=0; j topPole = sculptImage[0][xs/2]; Vector bottomPole = sculptImage[ys-1][xs/2]; xs = (int)sculptImage[0].size(); // Y方向境界処理 if (type==SCULPT_TYPE_SPHERE) { if (ys%2==0) { SCULPT_VECTOR_ARRAY bottomPoleRow; // for (int i=0; i=0; i--) { p4 = i + jj; p3 = p4 - 1; p2 = p4 - xs; p1 = p3 - xs; coords.push_back(sculptImage[j][i]); normals.push_back(Vector(0.0, 0.0, 0.0)); uvs.push_back(UVMap(du*i, 1.0-dv*j)); if (i>0 && j>0) { FacetTriIndex t1, t2; // if (invert) { t1.mlt_set(p1, p3, p4); t2.mlt_set(p1, p4, p2); } else { t1.mlt_set(p1, p4, p3); t2.mlt_set(p1, p2, p4); } // sculptTriIndex.push_back(t1); sculptTriIndex.push_back(t2); } } } if (flipUV) { execFlipUV(); } else { if (flipU) execFlipU(); if (flipV) execFlipV(); } ComputeTriNormals(xs, ys); SetupTriArray(); } // void SculptMesh::ComputeTriNormals(int xs, int ys) { int tnum = (int)sculptTriIndex.size(); for (int i=0; i normal = indx.SurfaceNormal(&coords); normals[indx.n1] = normals[indx.n1] + normal; normals[indx.n2] = normals[indx.n2] + normal; normals[indx.n3] = normals[indx.n3] + normal; } int nnum = (int)normals.size(); for (int i=0; i normal = (normals[jj] + normals[xs-1+jj]).normalize(); normals[jj] = normal; normals[xs-1+jj] = normal; } } return; } // void SculptMesh::SetupTriArray(void) { int tnum = (int)sculptTriIndex.size(); for (int i=0; i vert; int cnum = (int)coords.size(); for (int i=0; i q) { int cnum = (int)coords.size(); for (int i=0; i m(x, y, z); int cnum = (int)coords.size(); for (int i=0; i4096) { *xscale = width /64; *yscale = height/64; //*xscale = width /128 + 1; //*yscale = height/128 + 1; // if (*xscale==0) *xscale = 1; if (*yscale==0) *yscale = 1; } DEBUG_MODE PRINT_MESG("JBXL::GetSculptScale: type = %d, scale = (%d, %d)\n", type, *xscale, *yscale); return type; }