c++ read flash AIR NativeAplication arguments - c++
Hy I have made an AIR application that uses the flash.desktop.NativeProcess to start an c++ a* pathsolver. The reason being - Flash needs too much time to solve 250 * 250 open grid.
The AIR app is fine. It can start the c++ exe file
The exe fine works on its own
The problem is. They don't work in pair :(
When flash sends the arguments the c++ part just dies silently
char buf[ 256 ]; std::cin.getline( buf, 256 );
I just havent mannaged to find wat is going on. If i use arguments insted of standard imput i get some strange characters. Any idea ?
Well then. You will find the working (furthermore, working fast) wave pathfinding demo below. There are two test cases:
32x32 predesigned dungeon, loops 256 times, runs 0.12s - 0.13s
320x320 big, empty, entrance and exit are at opposite corners, runs 0.03s - 0.04s
So, the problem with the tutorials and algorithms that they are ideal for clean small tutorial cases. When there are a lot of data, well, not so much. If you'd followed that tutorial, it leaves you with that Node class of getters and setters. Each time you refer a getter or setter, you invoke a function call, which is a relatively heavy operation. One time, ten times, hundred times - no problem, but there you have 64K of those nodes, that builds the performance momentum. Even if you didn't go for getter/setter picture, there are still a lot of node instances, you pull their properties... you get the picture, right?
When I first did that wave pathfinding in 2009, I too did blunder into the mess of node instances and their properties. Then 2-dimensional array of ints, no good. Then I thought of BitmapData class which could quite literally represent the map and hold 32 bits of data per cell/pixel. Every one idea turned out to still be too slow.
I might've possibly thought of 1-dimensional representation faster, but the thing is, I worked with hexagonal map so each cell had 6 ways out, not just 4, a bit confusing.
Yet, in the end, I came up with the whole idea of mapping the area into 1-dimensional array and navigating it with +1, -1, +width and -width shifts (well, 2 more for hexagonal topography). I had no need of complicated things back then (and I don't think you need them either) like path weights, just to find the shortest path in an UX-acceptable time frame.
If you look at the algorithms pathfinding part, it's so simple. No x and y coordinates. No border checks. No node objects, no properties, no additional function calls. Just the simplest math and a few operations per each cell - as few as it possible. That's why it is so fast and efficient.
The mentioned Log class, you can grab it at my repo.
package
{
import flash.utils.getTimer;
import flash.display.Sprite;
import ru.delimiter.utils.Log;
/**
* ...
* #author Dmitry Yamaykin
*/
public class PathFinding extends Sprite
{
public function PathFinding()
{
super();
// Log is a debug output panel which allows you
// to see things if traces are unavailable
// or/and suppressed by the release build.
Log.create(this, true);
Log.log("[PathFinding] starts!");
testBig();
testSmall();
}
// The main data array that keeps obstacles,
// empty cells and those already passed by the wave.
private var map:Vector.<int> = new Vector.<int>;
// The front of the wave and the next front.
private var wave:Vector.<int> = new Vector.<int>;
private var froth:Vector.<int> = new Vector.<int>;
// Mapping the map back to the original data. Just for
// this demo, you probably won't need it with the real thing.
private var route:Vector.<int> = new Vector.<int>;
// Be extra careful with the 'w' argument, if you fumble with
// the width of the row, the whole thing will totally go astray.
private function findPath(source:Array, w:int, h:int):Array
{
var length:int = source.length;
var begin:int;
var end:int;
var i:int;
var steps:int;
var windex:int;
var findex:int;
var mindex:int;
map.fixed = false;
wave.fixed = false;
froth.fixed = false;
route.fixed = false;
// The brilliance of it: working with just a few instances
// that are set up in the very beginning and fixed to a
// certain amount of memory. No memory management while
// finding paths, no creating and disposing of instances,
// no Garbage Collector to kick in and do its thing.
map.length = length;
wave.length = w + h;
froth.length = w + h;
route.length = length;
map.fixed = true;
wave.fixed = true;
froth.fixed = true;
route.fixed = true;
// The main idea behind fast wave is mapping the source
// 2-dimensional data into 1-dimensional array of int
// values. Your position is indicated by a single
// index, +1 is 'go right', -1 is 'go left',
// +width and -width are 'go down' and 'go up' respectively.
// Just don't forget to add a solid impassable top and bottom
// lines (to avoid 'out of range' array errors) and a solid
// wall at the right (at least) so you don't flip over the
// data while going right from the rightmost position
// and left from the leftmost. It's far more efficient this
// way than additional code checks for borders.
for (i = 0; i < length; i++)
{
switch (source[i])
{
case '.':
map[mindex] = 0;
route[mindex] = i;
mindex++;
break;
case '#':
map[mindex] = -1;
route[mindex] = i;
mindex++;
break;
case 'X':
map[mindex] = -1;
route[mindex] = i;
end = mindex;
mindex++;
break;
case 'Y':
// We need it to be passable
// for wave to wash in there.
map[mindex] = 0;
route[mindex] = i;
begin = mindex;
mindex++;
break;
}
}
// Be careful with logging. It duplicates the output to the
// standard trace, which includes writing to a file
// (Flash thing, not my fault) which is really,
// like REALLY slow operation to do.
// Log.log(begin, '>', end);
// With just fixed [1, -1, w, -w] it will work a bit faster,
// bit the algorithm will prefer going in the straight lines,
// rather than wandering in diagonals and cutting the corners.
var AWX:int = 0;
var AWAY:Array;
var WAYS:Array =
[
[1, -1, w, -w],
[w, -w, 1, -1],
[-1, w, 1, -w],
[-w, 1, w, -1],
[1, -1, -w, w],
[w, -w, -1, 1],
[-1, 1, -w, w],
[w, -w, -1, 1],
[1, w, -1, -w],
[w, -1, -w, 1],
[-1, 1, w, -w],
[-w, w, 1, -1],
[1, -w, -1, w],
[w, 1, -w, -1],
[-1, -w, 1, w],
[w, -1, -w, 1],
];
// Lets the party begin.
wave[0] = end;
windex = 1;
// Repeat while wave front is not empty.
while (windex)
{
// Pick the next pattern of motion preferences.
if (--AWX < 0) AWX = WAYS.length - 1;
AWAY = WAYS[AWX];
// Go through all the points on the current wave front.
while (windex--)
{
var anindex:int = wave[windex];
// Try to move into the all
// possible directions from it.
for each (var ashift:int in AWAY)
{
// This value will be used a few times
// so it's better to calculate it once and store.
var awindex:int = anindex + ashift;
// Either -1 (impassable) or 1+
// (wave's been here already) means
// this spot is of no interest to us.
if (map[awindex]) continue;
// The 'path is found' routine.
if (awindex == begin)
{
// Log.log("THE WAY");
// The following code is just a dummy demo.
var result:Array = source.slice();
while (anindex != end)
{
result[route[anindex]] = '*';
anindex = map[anindex];
}
return result;
/**
* The main idea behind the result code
* is to unwind the calculated path,
* which is pretty easy because each
* affected map cell contains
* the index of the previous
* cell all the way back
* to the center of
* the wave.
*
result = [begin];
while (anindex != end)
{
result.push(anindex);
anindex = map[anindex];
}
result.push(end);
*
**/
}
// Add the empty cell to the
// next front line of the wave.
map[awindex] = anindex;
froth[findex++] = awindex;
}
}
// The next front line is formed,
// time to move on to the next iteration.
var xchange:Vector.<int> = froth;
var xindex:int = findex;
froth = wave;
findex = 0;
wave = xchange;
windex = xindex;
//Log.log(windex, wave);
}
// If we're here, that means the wave started
// at the 'end' point never hit the 'begin'.
trace("NO WAY");
return null;
}
// Tests pathfinding in a smaller dungeon: a multiple times.
private function testSmall():void
{
var X:XML = <root><![CDATA[
##################################
#.............#................#Y#
#.....#.......#.......#........#.#
#.....#.......#.......#........#.#
#.....#.......#.......#........#.#
#.....#.......#.......#........#.#
#.....#.......#.......#........#.#
#.....#.......#.......#........#.#
#.....#.......#.......#........#.#
#.....#.......#.......#........#.#
#.....#...............#..........#
#.....############################
#................................#
#................................#
#................................#
#................................#
#######..........................#
#................................#
#...####.........................#
#................................#
#................................#
#................................#
#................................#
#................................#
#................................#
#................................#
##################...............#
#................#...............#
#................#...............#
#...######.......#...............#
#........#.......#...............#
#........#.......#...............#
#........#.......#...............#
#X.......#.......................#
##################################
]]></root>;
var D:String = X.children()[0].toString().split("\r").join("");
var A:Array = D.split("");
var aTime:int = getTimer();
var R:Array;
for (var i:int = 255; i >= 0; i--)
{
R = findPath(A, 34, 34);
}
Log.log("");
Log.log("32 x 32, pre-designed, not empty, 256 times.");
Log.log("Elapsed", getTimer() - aTime, "ms.");
if (R) Log.log(R.join(""));
}
// Tests pathfinding in a big empty dungeon.
private function testBig():void
{
var D:String = "";
// Lets form a biiig empty field with
// entrance and exit at the opposite corners.
var TB:String = G("#", 322);
var TX:String = "#" + G(".", 319) + "X#";
var TY:String = "#Y" + G(".", 319) + "#";
var TE:String = "#" + G(".", 320) + "#";
D += TB;
D += TX;
for (var i:int = 0; i < 318; i++)
{
D += TE;
}
D += TY;
D += TB;
var A:Array = D.split("");
var aTime:int = getTimer();
var R:Array = findPath(A, 320, 320);
Log.log("");
Log.log("320 x 320, empty.");
Log.log("Elapsed", getTimer() - aTime, "ms.");
}
private function G(char:String, repeat:int):String
{
var result:String = char;
while (result.length < repeat)
{
result += result;
}
result = result.substr(0, repeat);
return result;
}
}
}
Ugly hack, but does the job :D
var f = File.documentsDirectory.resolvePath("command.txt");
var stream = new FileStream();
stream.open(f, FileMode.WRITE);
stream.writeUTFBytes(nextQuery.command + "/" + nextQuery.data);
stream.close();
You can guess the c++ side
std::stringstream strmap;
strmap << my_documents << "/command.txt" ;
std::ifstream myfile (strmap.str().c_str());
I call it the
black market algorytm
Related
ds_list Not working as inteded in game maker studio
The problem with my code occurs when i try to use a ds list for all my targets. It seems like it wont register a thing, i don't know what i am doing wrong, i have tried everything i know. When i display the values for the ds list its always 0, even tho the collision id i put in to the list has a value. also the collision id default at -4 when It's not colliding with anything for some reason. here is the code that assign the value to the ds list. //get all enemys in area current_coli = collision_circle(x, y, tower_range, obj_enemys, 0, 1); if (current_coli != noone){ ds_list_add(collision_list, current_coli); } Here is the code I'm trying to use the ds list in witch dose nothing. var i for (i = 0; i < ds_list_size(collision_list) + 1; i++){ target_test = ds_list_find_value(collision_list, i); if (instance_exists(target_test) and (rectangle_in_circle(target_test.x - 7, target_test.y - 7, target_test.x + 7, target_test.y + 7, x, y, tower_range) > 0)) { target = ds_list_find_value(collision_list, i); target.show_hp_bar = true; target.path_speed = target.path_speed * ((100 - slow)/100) show_debug_message(other.target); }else{ target.path_speed = target.start_speed; ds_list_delete(collision_list, i); } } I can't execute that code because of the ds list containing nothing. As i said before, the "current_coli" gives the id of the object, but it dose not store it to the ds list for some reason, "target_test" is always unidentified and the ds list "collision_list" is always 0. the code is inside a object step event that have a stationary place on the map and apply the effect to a enemy object that is inside its collision radius.
This is wrong: //get all enemys in area current_coli = collision_circle(x, y, tower_range, obj_enemys, 0, 1); if (current_coli != noone){ ds_list_add(collision_list, current_coli); } collision_circle returns only one (least) ID, not all IDs. You can to do something like this: with obj_enemys { if point_distance(x, y, other.x, other.y) < other.tower_range { ds_list_add(other.collision_list, id); } } And var i for (i = 0; i < ds_list_size(collision_list) + 1; i++) also wrong. Right: for (var i=0; i<ds_list_size(collision_list); i++) You can write var inside for. You don't need +1. One more thing. When you do ds_list_delete(collision_list, i); It changes data and breaks your for loop. For example, you can decrease i after deleting. ds_list_delete(collision_list, i); i--; or same in one line ds_list_delete(collision_list, i--);
grass fire algorithm taking way too long, how to optimize?
So I am working with openCV and trying to write a bunch of algorithms "from scratch" so to speak so that I can really understand what the library is doing. I wrote a modified grass fire algorithm to segment BLOBs from an image that I have already digitized. However, the algorithm takes over 2 minutes to run on my very capable laptop (16 gigs ram, quad core i7, etc...). What am I doing here that is making it so complex? Alternately, is there a better algorithm for extracting BLOBs from a digitized image? THANKS! Here is the algorithm std::vector<boundingBox> grassFire(cv::Mat digitalImage){ std::vector<boundingBox> blobList; int minY, minX, maxY, maxX, area, yRadius, xRadius, xCenter, yCenter; for(int curRow = 0; curRow<digitalImage.rows; curRow++){ for(int curCol = 0; curCol<digitalImage.cols; curCol++){ //if there is something at that spot in the image if((int)digitalImage.at<unsigned char>(curRow, curCol)){ minY = curRow; maxY = curRow; minX = curCol; maxX = curCol; area = 0; yRadius = 0; xRadius = 0; for(int fireRow=curRow; fireRow<digitalImage.rows; fireRow++){ //is in keeps track of the row and started keeps track of the col //is in will break if no pixel in the row is part of the blob //started will break the inner loop if a nonpixel is reached AFTER a pixel is reached bool isIn = false; bool started = false; for(int fireCol = curCol; fireCol<digitalImage.cols; fireCol++){ //make sure that the pixel is still in if((int)digitalImage.at<unsigned char>(fireRow, fireCol)){ //signal that an in pixel has been found started = true; //signal that the row is still in isIn = true; //add to the area area++; //reset the extrema variables if(fireCol > maxX){maxX = fireCol;} if(fireCol < minX){minX = fireCol;} if(fireRow > maxY){maxY = fireRow;} //no need to check min y since it is set already by the loop trigger //set the checked pixel values to 0 to avoid double counting digitalImage.at<unsigned char>(fireRow, fireCol) = 0; } //break if the next pixel is not in and youve already seen an in pixel //do nothing otherwise else{if(started){break;}} //if the entire blob has been detected if(!isIn){break;} } } }else{}//just continue the loop if the current pixel is not in //calculate all blob specific values for the blob at hand xRadius =(int)((double)(maxX - minX)/2.); yRadius =(int)((double)(maxY - minY)/2.); xCenter = maxX - xRadius; yCenter = maxY - yRadius; //add the blob to the vector in the appropriate position (largest area first) int pos = 0; for(auto elem : blobList){ if(elem.getArea() > area){ pos++; } else{break;} } blobList.insert(blobList.begin() + pos, boundingBox(area, xRadius, yRadius, xCenter, yCenter)); } } return blobList; }
You say `just continue the loop if the current pixel is not in but you don't continue the loop there, and fall thru to the code that adds another element to blobList (which code will access past the end of the lit of no element satisfies the condition in that for loop). And using this for(const auto &elem : blobList) would avoid making copies of all those boundingBoxes.
passing values to a boolean array
I'm working on a simple 2d game engine, and am trying to set up a system where the player model can move behind certain objects. Every time an non-player object is blitted to the screen, its X and Y are recorded in an array so they can be used later. As such, I have set up a system where if the player X and player Y are relative to an environmental object's X and Y in a certain way, the environmental object is not immediately blitted (Normally, it would be immediately blitted before the player character so that the player character is above the object). Instead of being blitted, I have a true value be handed to a boolean array. I have an int variable that gets 1 larger every time an object is blitted so that the different X, Y and boolean values are associated with a certain position in the array. Essentially, the system looks like this: HDcounter += 1; forbiddenX[HDcounter] = modelX[modelNumber] + modelXChange; forbiddenY[HDcounter] = modelY[modelNumber] + modelYChange; forbiddenSpriteWidth[HDcounter] = 100; forbiddenSpriteHeight[HDcounter] = 200; forbiddenSpriteDepth[HDcounter] = 25; if((forbiddenX[HDcounter] <= playerXE + forbiddenSpriteWidth[HDcounter]) && (forbiddenX[HDcounter] + forbiddenSpriteWidth[HDcounter] >= playerXE) && (forbiddenY[HDcounter] <= playerYE + forbiddenSpriteWidth[HDcounter]) && (forbiddenY[HDcounter] + forbiddenSpriteHeight[HDcounter] >= playerYE + 77)) { pineTreeBlitAP = true; blitModelAP[HDcounter] = true; } else { modelIMAGE = IBFobjectENVIRO.loadIMG("pineTree.png"); IBFobjectENVIRO.blitIMG(modelX[modelNumber] + modelXChange, modelY[modelNumber] + modelYChange, windowMODELS, modelIMAGE, 0, 0, 200, 200); } The problem is that when I try to use the boolean array to blit the model after the player, it does not seem to work. I can get something to happen when the player X and Y hits the threshold, but I cannot seem to get the true value recorded inside the boolean array and then used by my function. This is the function where it is used: void enviroment::blitEnviroModelsAP(SDL_Surface* BAPwindow, int modelAmount) { SDL_Surface* modelAPimage; for(int model = 0; model < modelAmount; model++) { if((pineTreeBlitAP == true) && (blitModelAP[model] == true)) { modelAPimage = IBFobjectENVIRO.loadIMG("pineTree.png"); IBFobjectENVIRO.blitIMG(forbiddenX[model], forbiddenY[model], BAPwindow, modelAPimage, 0, 0, 200, 200); } } } I get that this is probably a totally noob question, I just want some kind of help with this as I have been stuck for nearly a week. Edit: Here are how my arrays are declared. int forbiddenX[2000] = {0}; int forbiddenY[2000] = {0}; int forbiddenSpriteHeight[2000] = {0}; int forbiddenSpriteWidth[2000] = {0}; int forbiddenSpriteDepth[2000] = {0}; int blitModelAP[2000] = {false};
Photoshop CS4 Script or Action to: Write 0 to 100 on separate text layers
My goal is to create 101 separate text layers containing 0-100 (i.e. 1, 2, 3...100) I know I can mass change the attributes but cant write or alter the containing text.
What you want can easily be done with a script (easier than renaming 100 layers in all the right order and record an action for it) This script will create 100 layers of text, each layer will be named 1,2,3..etc and the text will be the same. I think that's waht you are after, your description was rather short. // call the source document var srcDoc = app.activeDocument; var numOfLayers = 100; //var numOfLayers = srcDoc.layers.length; var numPadding = "0"; var layerNum = 1; // change this to 0 to start layers at 0 var w = Math.floor(srcDoc.width.value/2); var h = Math.floor(srcDoc.height.value/2); // main loop starts here for (var i = numOfLayers -1; i >= 0 ; i--) { if (layerNum < 10) numPadding = "0"; else numPadding =""; createText("Arial-BoldMT", 20.0, 0,0,0, layerNum, w, h); var currentLayer = srcDoc.activeLayer; currentLayer.name = numPadding + layerNum; layerNum +=1; } // function CREATE TEXT(typeface, size, R, G, B, content, Xpos, Ypos) // -------------------------------------------------------- function createText(fface, size, colR, colG, colB, content, tX, tY) { var artLayerRef = srcDoc.artLayers.add() artLayerRef.kind = LayerKind.TEXT textColor = new SolidColor(); textColor.rgb.red = colR; textColor.rgb.green = colG; textColor.rgb.blue = colB; textItemRef = artLayerRef.textItem textItemRef.font = fface; textItemRef.contents = content; textItemRef.color = textColor; textItemRef.size = size textItemRef.position = new Array(tX, tY) //pixels from the left, pixels from the top activeDocument.activeLayer.textItem.justification.CENTER } Save this out as numberLayers1-100.jsx and then reun it from Photoshop via the Files -> Scripts menu.
C++ vector element is different when accessed at different times
I'm developing a 3D game using SDL and OpenGL on Ubuntu 9.04 using Eclipse CDT. I've got a class to hold the mesh data in vectors for each type. Such as Vertex, Normal, UVcoord (texture coordinates), as well as a vector of faces. Each face has 3 int vectors which hold indexes to the other data. So far my game has been working quite well at rendering at nice rates. But then again I only had less then one hundred vertexes among two objects for testing purposes. The loop accessing this data looks like this: void RenderFace(oFace face) { /* * More Stuff */ oVertice gvert; oUVcoord tvert; oNormal nvert; for (unsigned int fvIndex = 0; fvIndex < face.GeoVerts.size(); fvIndex++) { gvert = obj.TheMesh.GetVertice(face.GeoVerts[fvIndex] - 1); tvert = obj.TheMesh.GetUVcoord(face.UV_Verts[fvIndex] - 1); nvert = obj.TheMesh.GetNormal(face.NrmVerts[fvIndex] - 1); glNormal3f(nvert.X, nvert.Y, nvert.Z); glTexCoord2f(tvert.U, tvert.V); glVertex3f(scale * gvert.X, scale * gvert.Y, scale * gvert.Z); } /* * More Stuff */ } There is a loop that calls the renderFace() function which includes the above for loop. The minus one is because Wavefront .obj files are 1 indexed (instead of c++ 0 index). Anyway, I discovered that once you have about 30 thousand or so faces, all those calls to glVertex3f() and the like slow the game down to about 10 FPS. That I can't allow. So I learned about vertex arrays, which require pointers to arrays. Following the example of a NeHe tutorial I continued to use my oVertice class and the others. Which just have floats x, y, z, or u, v. So I added the same function above to my OnLoad() function to build the arrays which are just "oVertice*" and similar. Here is the code: bool oEntity::OnLoad(std::string FileName) { if (!obj.OnLoad(FileName)) { return false; } unsigned int flsize = obj.TheMesh.GetFaceListSize(); obj.TheMesh.VertListPointer = new oVertice[flsize]; obj.TheMesh.UVlistPointer = new oUVcoord[flsize]; obj.TheMesh.NormListPointer = new oNormal[flsize]; oFace face = obj.TheMesh.GetFace(0); oVertice gvert; oUVcoord tvert; oNormal nvert; unsigned int counter = 0; unsigned int temp = 0; for (unsigned int flIndex = 0; flIndex < obj.TheMesh.GetFaceListSize(); flIndex++) { face = obj.TheMesh.GetFace(flIndex); for (unsigned int fvIndex = 0; fvIndex < face.GeoVerts.size(); fvIndex++) { temp = face.GeoVerts[fvIndex]; gvert = obj.TheMesh.GetVertice(face.GeoVerts[fvIndex] - 1); temp = face.UV_Verts[fvIndex]; tvert = obj.TheMesh.GetUVcoord(face.UV_Verts[fvIndex] - 1); temp = face.NrmVerts[fvIndex]; nvert = obj.TheMesh.GetNormal(face.NrmVerts[fvIndex] - 1); obj.TheMesh.VertListPointer[counter].X = gvert.X; obj.TheMesh.VertListPointer[counter].Y = gvert.Y; obj.TheMesh.VertListPointer[counter].Z = gvert.Z; obj.TheMesh.UVlistPointer[counter].U = tvert.U; obj.TheMesh.UVlistPointer[counter].V = tvert.V; obj.TheMesh.NormListPointer[counter].X = nvert.X; obj.TheMesh.NormListPointer[counter].Y = nvert.Y; obj.TheMesh.NormListPointer[counter].Z = nvert.Z; counter++; } } return true; } The unsigned int temp variable is for debugging purposes. Apparently I don't have a default constructor for oFace that doesn't have something to initialize with. Anyway, as you can see it's pretty much that same exact routine. Only instead of calling a gl function I add the data to three arrays. Here's the kicker: I'm loading a typical cube made of triangles. When I access element 16 (0 indexed) of the UV_Verts vector from the RenderFace() function I get 12. But when I access element 16 (0 indexed) of the same UV_Verts vector from the OnLoad() function I get something like 3045472189 I am so confused. Does anyone know what's causing this? And if so how to resolve it?
One possible reason could be that you're creating arrays with size flsize: obj.TheMesh.VertListPointer = new oVertice[flsize]; obj.TheMesh.UVlistPointer = new oUVcoord[flsize]; obj.TheMesh.NormListPointer = new oNormal[flsize]; but use the arrays with indices up to flsize * face.GeoVerts.size for (...; flIndex < obj.TheMesh.GetFaceListSize(); ...) { // flsize = GetFaceListSize for (...; fvIndex < face.GeoVerts.size(); ...) { ... obj.TheMesh.UVlistPointer[counter].U = ...; ... counter++; } } so your array creation code should actually be more like obj.TheMesh.VertListPointer = new oVertice[flsize * face.GeoVerts.size()]; obj.TheMesh.UVlistPointer = new oUVcoord[flsize * face.GeoVerts.size()]; obj.TheMesh.NormListPointer = new oNormal[flsize * face.GeoVerts.size()];