/** @brief OpenSimの Tree/Grassのサポート @file TreeTool.cpp @author Fumi.Iseki & D.Mizumaki @date 2015/06/14 */ #include "TreeTool.h" using namespace jbxl; // void TreeTool::init(void) { shape.PCode = PRIM_PCODE_TREE; shape.State = TREM_TREE_PINE1; addname = init_Buffer(); alphaTexture.init(); for (int i=0; i(3.2f, 0.0001f, 6.15f); // Pine 1 1024x1968 6.15 treeParam[ 1].size = Vector(1.0f, 0.0001f, 1.54f); // Oak 1024x1572 1.54 treeParam[ 2].size = Vector(0.6f, 0.0001f, 0.625f); // Tropical Bush 1 1024x1066 0.625 treeParam[ 3].size = Vector(1.2f, 0.0001f, 2.26f); // Palm 1 1024x1928 2.26 treeParam[ 4].size = Vector(0.8f, 0.0001f, 1.52f); // Dogwood 1024x1948 1.52 treeParam[ 5].size = Vector(0.5f, 0.0001f, 0.555f); // Tropical Bush 2 1024x1136 0.555 treeParam[ 6].size = Vector(1.2f, 0.0001f, 2.26f); // Palm 2 1024x1928 2.26 treeParam[ 7].size = Vector(2.0f, 0.0001f, 3.79f); // Cypress 1 1024x1940 3.79 treeParam[ 8].size = Vector(2.3f, 0.0001f, 4.40f); // Cypress 2 1024x1960 4.40 treeParam[ 9].size = Vector(2.7f, 0.0001f, 5.20f); // Pine 2 1024x1972 5.20 treeParam[10].size = Vector(1.3f, 0.0001f, 1.52f); // Plumeria 1024x1195 1.52 treeParam[11].size = Vector(1.0f, 0.0001f, 1.92f); // Winter Pine 1 1024x1968 1.92 treeParam[12].size = Vector(1.0f, 0.0001f, 1.89f); // Winter Aspen 1024x1932 1.89 treeParam[13].size = Vector(0.65f,0.0001f, 1.23f); // Winter Pine 2 1024x1936 1.23 treeParam[14].size = Vector(2.5f, 0.0001f, 3.79f); // Eucalyptus 1024x1552 3.79 treeParam[15].size = Vector(0.25f,0.0001f, 0.250f); // Fern 1024x1024 0.250 treeParam[16].size = Vector(0.25f,0.0001f, 0.469f); // Eelgrass 1024x1920 0.469 treeParam[17].size = Vector(0.15f,0.0001f, 0.168f); // Sea Sword 1024x1148 0.168 treeParam[18].size = Vector(0.42f,0.0001f, 0.758f); // Kelp 1 1024x1848 0.758 treeParam[19].size = Vector(0.3f, 0.0001f, 0.369f); // Beach Grass 1 1024x1260 0.369 treeParam[20].size = Vector(0.62f,0.0001f, 1.16f); // Kelp 2 1024x1920 1.16 treeParam[21].size = Vector(1.0f, 0.0001f, 1.0f); // for TEST Tree treeParam[ 7].num_panel = 3; // Cypress 1 treeParam[ 8].num_panel = 3; // Cypress 2 treeParam[12].num_panel = 6; // Winter Aspen treeParam[13].num_panel = 6; // Winter Pine 2 treeParam[15].num_panel = 6; // Fern treeParam[16].num_panel = 6; // Eelgrass treeParam[17].num_panel = 6; // Sea Sword treeParam[18].num_panel = 2; // Kelp 1 treeParam[20].num_panel = 2; // Kelp 2 // Grass grassParam[0].texture.setName("6c4727b8-ac79-ba44-3b81-f9aa887b47eb"); // Medium grassParam[1].texture.setName("79504bf5-c3ec-0763-6563-d843de66d0a1"); // Short 2 grassParam[2].texture.setName("6c4727b8-ac79-ba44-3b81-f9aa887b47eb"); // Tall Green grassParam[3].texture.setName("99bd60a2-3250-efc9-2e39-2fbcadefbecc"); // Short 1 grassParam[4].texture.setName("7a2b3a4a-53c2-53ac-5716-aac7d743c020"); // Tall Brown grassParam[5].texture.setName("8f458549-173b-23ff-d4ff-bfaa5ea2371b"); // Leafy Ground Cover grassParam[6].texture.init(); // for TEST Grass grassParam[0].size = Vector(0.7f, 0.0001f, 0.7f); // Medium grassParam[1].size = Vector(0.5f, 0.0001f, 0.5f); // Short 2 grassParam[2].size = Vector(1.0f, 0.0001f, 1.0f); // Tall Green grassParam[3].size = Vector(0.5f, 0.0001f, 0.5f); // Short 1 grassParam[4].size = Vector(1.0f, 0.0001f, 1.0f); // Tall Brown grassParam[5].size = Vector(1.0f, 0.0001f, 1.0f); // Leafy Ground Cover grassParam[6].size = Vector(1.0f, 0.0001f, 1.0f); // for TEST Grass return; } // void TreeTool::set_shape(PrimBaseShape pbs) { shape.free(); shape.dup(pbs); if (shape.PCode==PRIM_PCODE_NEWTREE || shape.PCode==PRIM_PCODE_TREE) { if (shape.State<0 || shape.State>=TREM_TREE_NUM) shape.State = 0; } else if (shape.PCode==PRIM_PCODE_GRASS) { if (shape.State<0 || shape.State>=TREM_GRASS_NUM) shape.State = 0; } } // void TreeTool::free(void) { free_Buffer(&addname); alphaTexture.free(); for (int i=0; i=0 && kind=0 && kind=TREM_TREE_NUM) pbs.State = 0; set_shape(pbs); if (ndiv<=0) ndiv = treeParam[pbs.State].num_panel; PrimBaseShape bases; PrimMeshParam param; bases.GenerateBaseParam(PRIM_TYPE_BOX); param.GetParamFromBaseShape(bases); PrimMesh primMesh = GeneratePrimMesh(param); bases.free(); param.free(); int trino; // 三角ポリゴンの数 int facetno; // 面の数 TriPolyData* tridata = TriPolyDataFromPrimMesh(primMesh, &facetno, &trino); primMesh.free(); for (int i=0; i(th*n, Vector(0.0, 0.0, 1.0))); } tridata = joinTriPolyData(tridata, trino*n, dupdata, trino); } freeTriPolyData(orgdata, trino); trino *= ndiv; facetno *= ndiv; // Material Paramter MaterialParam mparam[3]; mparam[0].setTextureName(alphaTexture.getName()); mparam[1].setTextureName(treeParam[shape.State].texture.getName()); mparam[2].setTextureName(treeParam[shape.State].texture.getName()); mparam[2].setFlipU(true); for (int i=0; i<3; i++) { mparam[i].setColor(1.0f, 1.0f, 1.0f, 1.0f); mparam[i].setTransparent(MTRL_DEFAULT_ALPHA); mparam[i].setAlphaMode(MATERIAL_ALPHA_MASKING); mparam[i].setAlphaCutoff(0.5); if (add_param) { char* paramsname = mparam[i].getBase64Params('T'); // T: Tree mparam[i].setAdditionalName(paramsname); if (paramsname!=NULL) ::free(paramsname); } } MeshObjectData* data = new MeshObjectData((char*)shape.ObjectName.buf); for (int i=0; iaddData(tridata, trino, i, NULL, false); } freeTriPolyData(tridata, trino); for (int i=0; isetMaterialParam(mparam[0]); data->setMaterialParam(mparam[1]); data->setMaterialParam(mparam[0]); data->setMaterialParam(mparam[2]); data->setMaterialParam(mparam[0]); data->setMaterialParam(mparam[0]); } for (int i=0; i<3; i++) mparam[i].free(); double scale = (shape.affineTrans.scale.x + shape.affineTrans.scale.y + shape.affineTrans.scale.z)/3.0; AffineTrans affine; affine.setScale(scale, scale, scale); affine.setShift(shape.affineTrans.shift.x, shape.affineTrans.shift.y, shape.affineTrans.shift.z); affine.rotate = shape.affineTrans.rotate; data->setAffineTrans(affine); affine.free(); return data; } /** 草データの生成. @param pbs 基本情報が格納された形状変数.木の種類は pbs.Stateに格納されている. @param terrain 地形情報ツールへのポインタ.草の Z座標を決めるために必要.NULLなら Z座標は 0.0 @param add_param マテリアルのテクスチャ名にパラメータ用文字列を付与するか?(Unity3D用) @return Meshデータ. */ MeshObjectData* TreeTool::GenerateGrass(PrimBaseShape pbs, TerrainTool* terrain, bool add_param) { if (pbs.State<0 || pbs.State>=TREM_GRASS_NUM) pbs.State = 0; set_shape(pbs); int num_grass = (int)(shape.affineTrans.scale.x*shape.affineTrans.scale.y*TREM_GRASS_NUM_RATE); DEBUG_MODE PRINT_MESG("TreeTool::GenerateGrass: number of grass unit is %d\n", num_grass); PrimBaseShape bases; PrimMeshParam param; bases.GenerateBaseParam(PRIM_TYPE_BOX); param.GetParamFromBaseShape(bases); PrimMesh primMesh = GeneratePrimMesh(param); bases.free(); param.free(); int trino; // 三角ポリゴンの数 int facetno; // 面の数 TriPolyData* orgdata = TriPolyDataFromPrimMesh(primMesh, &facetno, &trino); primMesh.free(); // for (int i=0; ixsize/2.0f; float bb = yy + terrain->ysize/2.0f; if (aa<0.0 || bb<0.0 || aa>(float)terrain->xsize-1.0f || bb>(float)terrain->ysize-1.0f) { // ex. 0.0 - 255.0 valid_pos = false; } else { int i0 = (int)aa; // ex. 0 - 255 int j0 = (int)bb; // ex. 0 - 255 int i1 = i0 + 1; int j1 = j0 + 1; if (i1>=terrain->xsize) i1 = terrain->xsize - 1; if (j1>=terrain->ysize) j1 = terrain->ysize - 1; float alph = aa - i0; float beta = bb - j0; float h0 = (float)terrain->height(i0, terrain->ysize-1-j0); float h1 = (float)terrain->height(i1, terrain->ysize-1-j0); float h2 = (float)terrain->height(i0, terrain->ysize-1-j1); float h3 = (float)terrain->height(i1, terrain->ysize-1-j1); height = h0*(1.0f-alph)*(1.0f-beta) + h1*alph*(1.0f-beta) + h2*(1.0f-alph)*beta + h3*alph*beta - terrain->waterHeight; } } // if (valid_pos) { TriPolyData* dupdata = dupTriPolyData(orgdata, trino); double th = (float)(Frand()*PI2); // for (int i=0; i(th*n, Vector(0.0, 0.0, 1.0))); dupdata[i].execShift(Vector(xx, yy, height+grassParam[shape.State].size.z/2.0)); } tridata = joinTriPolyData(tridata, trino*gnum, dupdata, trino); gnum++; } } // freeTriPolyData(orgdata, trino); trino *= gnum; facetno *= gnum; MaterialParam mparam[3]; mparam[0].setTextureName(alphaTexture.getName()); mparam[1].setTextureName(grassParam[shape.State].texture.getName()); mparam[2].setTextureName(grassParam[shape.State].texture.getName()); mparam[2].setFlipU(true); for (int i=0; i<3; i++) { mparam[i].setColor(1.0, 1.0, 1.0, 1.0); mparam[i].setTransparent(MTRL_DEFAULT_ALPHA); mparam[i].setAlphaMode(MATERIAL_ALPHA_MASKING); mparam[i].setAlphaCutoff(0.5); if (add_param) { char* paramsname = mparam[i].getBase64Params('G'); // G: Grass mparam[i].setAdditionalName(paramsname); if (paramsname!=NULL) ::free(paramsname); } } MeshObjectData* data = new MeshObjectData((char*)shape.ObjectName.buf); for (int i=0; iaddData(tridata, trino, i, NULL, false); } freeTriPolyData(tridata, trino); //for (int i=0; isetMaterialParam(mparam[0]); data->setMaterialParam(mparam[1]); data->setMaterialParam(mparam[0]); data->setMaterialParam(mparam[2]); data->setMaterialParam(mparam[0]); data->setMaterialParam(mparam[0]); } for (int i=0; i<3; i++) mparam[i].free(); return data; } ///////////////////////////////////////////////////////////////////////////////// void TreeParam::init(void) { texture.init(); size.set (1.0, 0.0001, 1.0); shift.set(0.0, 0.0); scale.set(1.0, 1.0); num_panel = 4; } // void GrassParam::init(void) { texture.init(); size.set(1.0, 0.0001, 1.0); }