Jump to content

Runitai Linden

Lindens
  • Posts

    144
  • Joined

Everything posted by Runitai Linden

  1. Dain Shan wrote: So .. with all this bad and far too high numers we see 15000 / 2 cubes with 12 triangles each. That 7500 x 12 = 90000 Triangles .. not even half of the limit 200000 THIS is exactly the kind of feedback I'm looking for. Something isn't adding up here, so I took a look, and this is what I found out: Not all triangles are equal -- the streaming cost assumes an average of 10 bytes per triangle, but on low poly or faceted objects, many vertices are used in only one triangle, so the average triangle size (in bytes) for those objects is often much more than 10 bytes, not to mention the overhead of the mesh header and LLSD tags, which can outweigh the size of a tiny mesh. It's fair to charge more for these for a few reasons: 1. The extra data has to be streamed, creating overhead. 2. An extra HTTP request must be made for a tiny amount of data, creating overhead. 3. Actual render time performance of these objects is worse per triangle due to a high number of post TnL cache misses. #3 will vary from machine to machine, and will be much more noticeable on low end machines. As for 1 and 2, this could cut both ways -- using one small mesh multiple times will load better and require less bandwidth than baking multiple instances of that same mesh into one big mesh. The streaming cost already ignores the header when determining cost, and the overhead of the LLSD tags is constant, so a deduction could be made there. As for the extra HTTP request, that's a protocol issue builders have no control over, so it's really not fair to have that cost against you, and future protocol improvements could theoretically stream multiple meshes with one HTTP request. Thanks for the example! I'll need to see some large mesh builds to get a better idea of actual bandwidth usage and file sizes, but in the future we'll probably start talking about a visible mesh data size budget instead of a visible mesh triangle budget.
  2. Please resist the urge to compare meshes to prims in any form. I realize people will still use prims and sculpts to save on parcel limits, but that has no bearing on this discussion. Please limit the discussion to triangle budgets. In this case, would copying that mesh up to the prim limit of the region and distributing it evenly at ground level result in a greater than 300 thousand triangles being visible? If yes, then the streaming cost is doing its job and the mesh itself probably needs to reduce the number of triangles used in lower LoDs. Will the resulting triangle count be under 200 thousand? If yes, then that indicates a bug with the streaming cost that needs to be fixed. There are so many variables that go into that number it gets confusing, so just focus on the result -- a target triangle budget of 250 thousand triangles visible from the center of the region if the region was full to capacity with copies of that mesh distributed evenly at ground level. Here, "visible" means visible from the center, not all in frame from the center. Fill a sandbox up with your mesh and stand in the center, do a full rotation to get all the lods to resolve, and look at the scene stastics console (Develop->Consoles->Scene Statistics). I should also note that these numbers (200 thousand - 300 thousand triangles) are not final and should not be interpreted as a promise to tune the equations to that specific budget. It could go higher, it could go lower, but we need more data to tell what's appropriate.
  3. There's been a lot of discussion lately about prim equivalence, so I thought I'd post some of the principles that have been guiding the implementation of the streaming cost metric.  There's a lot of text here, but please read the whole thing before responding, as it starts off with some statements that seem bald face whacko without further explanation. First and foremost, the current implementation is far from final.  This is evidenced by the fact that the number in the upload floater, the number in the streaming cost debug display, and the number in the build floater all disagree with one another.  The last few months have been spent getting accounting code and asset formats into a place where we can fine tune the cost metrics.  We've only just begun fine tuning the cost equations.  To help, please build as much as you can.  I can't stress this enough.  The more content we have to examine and analyze, the better the final cost formula will serve us all. Second, meshes are not prims.  They LoD differently, transmit differently, tend to be different sizes, etc.  There is no analog between meshes and prims as far as triangle count or streaming cost.  They are completely different types of content.  The argument of "prim X has this many triangles so mesh Y should cost this many prims" has no merit.  Don't even get me started on sculpts.  The argument that some people will continue to use sculpts and prims instead of meshes specifically for an increase in triangle count at reduced prim cost, while completely true and valid, has no bearing on this discussion.  Please read on and I'll explain why. So what does "Prim Equivalence" mean?  Well, it means 1/15000th of a region's available resources.  Abandon the idea that "Prim Equivalence" means an "equivalent complexity compared to a prim."  It's an "equivalent parcel cost" compared to one prim.  So what is the "Prim Equivalence" trying to accomplish?  It's about budgeting.  The task now is to define a realistic resource budget for an entire region and adjust the physics, simulation, and mesh cost equations so that a cost of "15000" equals this budget.   Here, I'll talk about "streaming cost."  "Streaming cost" more or less translates directly into a "visible triangle cost," given that the number of triangles visible from any given point on a sim is directly proportional to the number of bytes that need to be transferred.  The goal of "streaming cost" is to limit the number of visible triangles to a realistic budget at default settings, and that budget is much smaller than you might think compared to overall scene budget.   Here are some examples: Abbott's Aerodome:  - 3.7 million triangles from prims - 500 thousand triangles visible from any given location Lusk: - 2.8 million triangles from prims - 218 thousand triangles visible from any given location Gibson: - 900 thousand triangles from prims - 150 thousand triangles visible from any given location Now, there are a lot of factors that play into performance other than triangle counts, but for the sake of simplicity, we're ignoring those for now.  If you explore built out regions in Second Life, you'll find similar numbers (use the "scene statistics" console to check for yourself).  The majority of built out regions seem to fall in the 200-400 thousand triangle range.  While it's true that prims are a completely different content type than meshes, this "visible triangles" number gives us a realistic target for predictable performance. Given that Second Life has bad framerates and prims aren't exactly stingy about wasting triangles, it's wise to bias meshes towards the low end of that spectrum, say at 250 thousand triangles give or take 50 thousand.  THAT is your visible triangle budget.  In order for Second Life to have a prayer of running well in a mesh build, the meshes MUST display no more than that number of triangles per frame.   So how does the streaming cost ensure that?  To be blunt, it doesn't.  No single metric can.  Object sizes, placements, and camera position all have a great effect on how many triangles you might see for any given frame.  The streaming cost merely provides an approximation for how much of this 15000 budget will be consumed by a single instance of the mesh in question.  Put another way, it tries to ensure that if a region were filled to capacity with instances of the mesh in question distributed evenly at ground level, the number of visible triangles per frame would closely match the specified triangle budget. What this means in practice is that triangles added to the high LoD are very cheap, while triangles added to the low LoD are very expensive (except for large meshes where the high lod is displayed over a large area).  This is because the low LoD tends to be displayed over a MUCH larger area than the high LoD, and thus this is the triangle count that will deduct from the 250 thousand triangle budget from most vantage points in the sim. So, be very aggressive about removing triangles from lower LoDs, build lots of stuff and focus discussion on concrete examples of mesh assets that are being penalized unfairly against the stated triangle budget, resist the temptation to compare meshes to sculpts and prims, and fret not that we're destroying mesh with high costs.  Do this, and two weeks from now we should be in a much better place with respect to prim equivalence.
  4. Please submit a jira with any sculpt IDs you feel are valid that are being detected as triangle bombs. Still looking for the sweet spot on that cutoff -- 32 square meters (at 1m scale) was much higher than any sculpts I came across while testing. The specific sculpt we're trying to protect against rings in at 500m, but that's worst case. We've got some wiggle room.
  5. Color not coming in would be a bug -- the color isn't stored in the mesh asset, but in the texture entries that are created at import. The new viewer uses a new import path to upload to the sim, so you're likely seeing a regression. It will be fixed.
  6.   The importer uses a map of joint names to internal names -- here's the map! mJointMap["mPelvis"] = "mPelvis"; mJointMap["mTorso"] = "mTorso"; mJointMap["mChest"] = "mChest"; mJointMap["mNeck"] = "mNeck"; mJointMap["mHead"] = "mHead"; mJointMap["mSkull"] = "mSkull"; mJointMap["mEyeRight"] = "mEyeRight"; mJointMap["mEyeLeft"] = "mEyeLeft"; mJointMap["mCollarLeft"] = "mCollarLeft"; mJointMap["mShoulderLeft"] = "mShoulderLeft"; mJointMap["mElbowLeft"] = "mElbowLeft"; mJointMap["mWristLeft"] = "mWristLeft"; mJointMap["mCollarRight"] = "mCollarRight"; mJointMap["mShoulderRight"] = "mShoulderRight"; mJointMap["mElbowRight"] = "mElbowRight"; mJointMap["mWristRight"] = "mWristRight"; mJointMap["mHipRight"] = "mHipRight"; mJointMap["mKneeRight"] = "mKneeRight"; mJointMap["mAnkleRight"] = "mAnkleRight"; mJointMap["mFootRight"] = "mFootRight"; mJointMap["mToeRight"] = "mToeRight"; mJointMap["mHipLeft"] = "mHipLeft"; mJointMap["mKneeLeft"] = "mKneeLeft"; mJointMap["mAnkleLeft"] = "mAnkleLeft"; mJointMap["mFootLeft"] = "mFootLeft"; mJointMap["mToeLeft"] = "mToeLeft"; mJointMap["avatar_mPelvis"] = "mPelvis"; mJointMap["avatar_mTorso"] = "mTorso"; mJointMap["avatar_mChest"] = "mChest"; mJointMap["avatar_mNeck"] = "mNeck"; mJointMap["avatar_mHead"] = "mHead"; mJointMap["avatar_mSkull"] = "mSkull"; mJointMap["avatar_mEyeRight"] = "mEyeRight"; mJointMap["avatar_mEyeLeft"] = "mEyeLeft"; mJointMap["avatar_mCollarLeft"] = "mCollarLeft"; mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft"; mJointMap["avatar_mElbowLeft"] = "mElbowLeft"; mJointMap["avatar_mWristLeft"] = "mWristLeft"; mJointMap["avatar_mCollarRight"] = "mCollarRight"; mJointMap["avatar_mShoulderRight"] = "mShoulderRight"; mJointMap["avatar_mElbowRight"] = "mElbowRight"; mJointMap["avatar_mWristRight"] = "mWristRight"; mJointMap["avatar_mHipRight"] = "mHipRight"; mJointMap["avatar_mKneeRight"] = "mKneeRight"; mJointMap["avatar_mAnkleRight"] = "mAnkleRight"; mJointMap["avatar_mFootRight"] = "mFootRight"; mJointMap["avatar_mToeRight"] = "mToeRight"; mJointMap["avatar_mHipLeft"] = "mHipLeft"; mJointMap["avatar_mKneeLeft"] = "mKneeLeft"; mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft"; mJointMap["avatar_mFootLeft"] = "mFootLeft"; mJointMap["avatar_mToeLeft"] = "mToeLeft"; mJointMap["hip"] = "mPelvis"; mJointMap["abdomen"] = "mTorso"; mJointMap["chest"] = "mChest"; mJointMap["neck"] = "mNeck"; mJointMap["head"] = "mHead"; mJointMap["figureHair"] = "mSkull"; mJointMap["lCollar"] = "mCollarLeft"; mJointMap["lShldr"] = "mShoulderLeft"; mJointMap["lForeArm"] = "mElbowLeft"; mJointMap["lHand"] = "mWristLeft"; mJointMap["rCollar"] = "mCollarRight"; mJointMap["rShldr"] = "mShoulderRight"; mJointMap["rForeArm"] = "mElbowRight"; mJointMap["rHand"] = "mWristRight"; mJointMap["rThigh"] = "mHipRight"; mJointMap["rShin"] = "mKneeRight"; mJointMap["rFoot"] = "mFootRight"; mJointMap["lThigh"] = "mHipLeft"; mJointMap["lShin"] = "mKneeLeft"; mJointMap["lFoot"] = "mFootLeft"; mJointMap["mPelvis"] = "mPelvis"; mJointMap["mTorso"] = "mTorso"; mJointMap["mChest"] = "mChest"; mJointMap["mNeck"] = "mNeck"; mJointMap["mHead"] = "mHead"; mJointMap["mSkull"] = "mSkull"; mJointMap["mEyeRight"] = "mEyeRight"; mJointMap["mEyeLeft"] = "mEyeLeft"; mJointMap["mCollarLeft"] = "mCollarLeft"; mJointMap["mShoulderLeft"] = "mShoulderLeft"; mJointMap["mElbowLeft"] = "mElbowLeft"; mJointMap["mWristLeft"] = "mWristLeft"; mJointMap["mCollarRight"] = "mCollarRight"; mJointMap["mShoulderRight"] = "mShoulderRight"; mJointMap["mElbowRight"] = "mElbowRight"; mJointMap["mWristRight"] = "mWristRight"; mJointMap["mHipRight"] = "mHipRight"; mJointMap["mKneeRight"] = "mKneeRight"; mJointMap["mAnkleRight"] = "mAnkleRight"; mJointMap["mFootRight"] = "mFootRight"; mJointMap["mToeRight"] = "mToeRight"; mJointMap["mHipLeft"] = "mHipLeft"; mJointMap["mKneeLeft"] = "mKneeLeft"; mJointMap["mAnkleLeft"] = "mAnkleLeft"; mJointMap["mFootLeft"] = "mFootLeft"; mJointMap["mToeLeft"] = "mToeLeft"; mJointMap["avatar_mPelvis"] = "mPelvis"; mJointMap["avatar_mTorso"] = "mTorso"; mJointMap["avatar_mChest"] = "mChest"; mJointMap["avatar_mNeck"] = "mNeck"; mJointMap["avatar_mHead"] = "mHead"; mJointMap["avatar_mSkull"] = "mSkull"; mJointMap["avatar_mEyeRight"] = "mEyeRight"; mJointMap["avatar_mEyeLeft"] = "mEyeLeft"; mJointMap["avatar_mCollarLeft"] = "mCollarLeft"; mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft"; mJointMap["avatar_mElbowLeft"] = "mElbowLeft"; mJointMap["avatar_mWristLeft"] = "mWristLeft"; mJointMap["avatar_mCollarRight"] = "mCollarRight"; mJointMap["avatar_mShoulderRight"] = "mShoulderRight"; mJointMap["avatar_mElbowRight"] = "mElbowRight"; mJointMap["avatar_mWristRight"] = "mWristRight"; mJointMap["avatar_mHipRight"] = "mHipRight"; mJointMap["avatar_mKneeRight"] = "mKneeRight"; mJointMap["avatar_mAnkleRight"] = "mAnkleRight"; mJointMap["avatar_mFootRight"] = "mFootRight"; mJointMap["avatar_mToeRight"] = "mToeRight"; mJointMap["avatar_mHipLeft"] = "mHipLeft"; mJointMap["avatar_mKneeLeft"] = "mKneeLeft"; mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft"; mJointMap["avatar_mFootLeft"] = "mFootLeft"; mJointMap["avatar_mToeLeft"] = "mToeLeft"; mJointMap["hip"] = "mPelvis"; mJointMap["abdomen"] = "mTorso"; mJointMap["chest"] = "mChest"; mJointMap["neck"] = "mNeck"; mJointMap["head"] = "mHead"; mJointMap["figureHair"] = "mSkull"; mJointMap["lCollar"] = "mCollarLeft"; mJointMap["lShldr"] = "mShoulderLeft"; mJointMap["lForeArm"] = "mElbowLeft"; mJointMap["lHand"] = "mWristLeft"; mJointMap["rCollar"] = "mCollarRight"; mJointMap["rShldr"] = "mShoulderRight"; mJointMap["rForeArm"] = "mElbowRight"; mJointMap["rHand"] = "mWristRight"; mJointMap["rThigh"] = "mHipRight"; mJointMap["rShin"] = "mKneeRight"; mJointMap["rFoot"] = "mFootRight"; mJointMap["lThigh"] = "mHipLeft"; mJointMap["lShin"] = "mKneeLeft"; mJointMap["lFoot"] = "mFootLeft";  
  7. The ToS dialog relies on a web page that probably isn't very reliable on the beta grid. If the ToS license text isn't appearing at all, it means this web page is failing to load. If this is the case, can you log into the main grid at all with any viewer (use ctrl-shift-g to bring up the grid selection checkbox from the login screen, agni is the production grid, aditi is the beta grid)? After accepting the ToS there, change your password (triggers a migration of inventory and account settings to beta grid as a side effect) and try to log into the beta grid again. If the text *is* appearing, you may need to scroll to the bottom of the text in order for the "agree" check box to be enabled.
  8. Er.. 65536 is the max vertex limit, but there is effectively no max triangle limit, so crashing on uploading the original model is a bug. That being said, even a 2,000 triangle comb is ludicrous by industry standards for a game engine. Try using an alpha texture for the teeth and use some of the recovered triangles to put the curve back in the handle.
×
×
  • Create New...