Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
0
Question by b1gry4n · Oct 01, 2016 at 06:14 PM · mathstuckformulaequationstupid

Issues wrapping my brain around this math

This is a problem for you math wizards that I have been stumped on for a while even though I feel like I should be able to solve it.

What I am doing : I am taking an image, or rather, float[,] values from an image and putting them into an array. From that array I am "upressing" the values so that the range of values turns into a larger pool. From there I am dividing it up into chunks. This is for terrain generation.

So for this example.

  • N = 512 (the original input dimensions. 512*512)

  • Up = 5 (the upres amount)

  • Cs = 512 (The chunk dimensions. 512*512)

  • Ms = N * Up (The total dimensions of the upresed array. 2560*2560)

  • Gs = Ms/Cs (The grid dimensions. 5*5 chunks)

Currently I am upresing the entire thing all at once. What I want to be able to do is upress only the necessary areas. As you can imagine, upressing a 512*512 image 50 times (25600*25600) would take a while to process a lot of unnecessary data...especially when its going to be representing terrain that the player wont be near.

Where I fail: I need to be able to access the specific values that are getting upresed into the chunk dimensions (512x512) from the original input (N) and upres only those. I cant have float values and I cant be rounding. The values exist and are being upressed, I just cant think of a way to reverse this process.

Conclusion: I want to collect only the necessary values from the original input and pass those to be upresed instead of unpresing the entire original input array.

Here is the code I am currently working with.

 float[,] originalInput; // an array containing the original values, im using 512*512 (N)
 int upres = 5; // how many times the original values are upres (Up)
 originalInput = UpresHeights(originalInput, upres); //upres the input 
 int mapsize = originalInput.GetLength(0); // (Ms)
 int chunkSize = 512; //(Cs)
 int gridSize = (int)Mathf.Round((mapsize / (float)chunkSize)); //Grid size (Gs)

     float[,] UpresHeights(float[,] oldHeights, int upres)
     {
         //Duplicate the array input array
         int originalHeight = oldHeights.GetLength(0);
         float[,] heights = new float[originalHeight, originalHeight];
         for (int y = 0; y < originalHeight; y++)
         {
             for (int x = 0; x < originalHeight; x++)
             {
                 float val = oldHeights[x, y];
                 heights[x, y] = val;
             }
         }
         //Upres the new array
         int heightsLength = originalHeight;
         int resolution = (heightsLength * upres);
         float[,] newHeights = new float[resolution, resolution];
         for (int y = 0; y < originalHeight; y++)
         {
             for (int x = 0; x < originalHeight; x++)
             {
                 //The original input is tileable, so the following
                 //just makes sure to sample from the opposite side
                 //of the array if at the border
                 float right = 0.0f;
                 if (x == originalHeight - 1)
                 {
                     right = heights[0, y];
                 }
                 else {
                     right = heights[x + 1, y];
                 }
 
                 float top = 0.0f;
                 if (y == originalHeight - 1)
                 {
                     top = heights[x, 0];
                 }
                 else {
                     top = heights[x, y + 1];
                 }
 
                 for (int xx = 0; xx < upres; xx++)
                 {
                     for (int yy = 0; yy < upres; yy++)
                     {
                         //smooth the values (could use vector2.distance, 
                         //but this isnt important right now)
                         //not that important since blur is applied later               
                         float a = Mathf.Lerp(heights[x, y], right, (xx / (float)upres));
                         float b = Mathf.Lerp(heights[x, y], top, (yy / (float)upres));
                         newHeights[x * upres + xx, y * upres + yy] = (a + b) / 2f;
                     }
                 }
             }
         }
         return newHeights;
     }


Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Owen-Reynolds · Oct 01, 2016 at 10:09 PM 0
Share

Usually helps to draw a picture, pick some arbitrary spot, hand-make the numbers, and compare to your code-idea. For example, pixel [3,2] is probably easy to hand-translate into the correct $$anonymous$$i-grid(?) and check. Then hand-compute for [4,2] and see if they actually fit together.

The other trick is is to think up tests using colors or drawing lines. Often they show you where your math is junk, and sometimes you can program them faster than you can hand-work the equations.

2 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by b1gry4n · Oct 02, 2016 at 07:34 AM

Heres the solution.

I needed to create two new variables

 //The sample area "per chunk" of the lower resolution array
 lowResWidth = (N) / (Gs);
 //the value of a step. Since its being upresed and between each value in //the array many other values are being made, this would be a float
 //example: between value 1 and value 2, theres 5 values with a pixel
 //step of 0.2
 pixelstep = lowResWidth / (CS);

My grid was already set up with x and y coordinates, so i needed to find the start value of the x and y in relation to the "downscaled" version

         float startX = lowResWidth * gridpoint.x;
         float startY = lowResWidth * gridpoint.y;

I created a new function to return an upresed array from that specific area of the downscaled array called with

 float[,] segment = UpresSeg(originalValues(N), chunkDimensions(Cs), startX, startY, gridPoint.x, gridPoint.y);

and the meat:

     float[,] UpresSeg(float[,] originalHeight, int resolution, float startX, float startY, int gridX, int gridY)
     {
         //create a new array to return
         float[,] returnThis = new float[resolution, resolution];
 
         //Since its possible to start on a float (example 1.2), we need to floor the original start values
         int origStartX = Mathf.FloorToInt(startX);
         int origStartY = Mathf.FloorToInt(startY);
 
         //we also need to subtract the original start floored value from the given start so we can retieve our
         //xstep and ystep starting points
         float xStep = startX - origStartX;
         float yStep = startY - origStartY;      
 
         int xCounter = 0;
         int yCounter = 0;        
 
         for (int y = 0; y < resolution; y++)
         {
             //reset the x counter for the new row
             xCounter = 0;
             for (int x = 0; x < resolution; x++)
             {
                 int origX = Mathf.FloorToInt(gridX * lowResWidth) + xCounter;
                 int origY = Mathf.FloorToInt(gridY * lowResWidth) + yCounter;
 
                 float right = 0.0f;
                 float top = 0.0f;
 
                 int xMod = 0;
                 int yMod = 0;
 
                 if (origX < originalHeight.GetLength(0) - 1)
                 {
                     xMod = origX + 1;
                 }
                 else {
                     xMod = originalHeight.GetLength(0) - 1;
                 }
 
                 right = originalHeight[xMod, origY];
 
                 if (origY < originalHeight.GetLength(1) - 1)
                 {
                     yMod = origY + 1;
                 }
                 else {
                     yMod = originalHeight.GetLength(1) - 1;
                 }
 
                 top = originalHeight[origX, yMod];                    
 
                 float a = Mathf.Lerp(originalHeight[origX, origY], right, xStep);
                 float b = Mathf.Lerp(originalHeight[origX, origY], top, yStep);               
                 returnThis[x, y] = (a + b) / 2f;
 
                 xStep += pixelstep;                
                 if (xStep >= pixelstep * tileSettings.upres)
                 {
                     xStep = 0.0f;
                     xCounter++;                  
                 }      
             }
             yStep += pixelstep;
             if (yStep >= pixelstep * tileSettings.upres)
             {
                 yStep = 0.0f;                
                 yCounter++;             
             }
             
         }
         return returnThis;
     }


There are some new issues that arise for me, but those are related to my generation script and what it does after this step. This might not be the best way to do this or even the "smartest" way, but it works

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
1

Answer by Bunny83 · Oct 02, 2016 at 01:42 AM

Well, it all boils down how you want to interpolate the values across your new resolution. What you do currently is kinda strange:

 top----unused
  |       |
  |       |
 x/y----right

Currently you ignore the height at "unused" and only interpolate in the lower left triangle.

Maybe you want a bilinear interpolation?

As for how to find the right values, first need some additional information: The chunk x and y position in "chunk coordinates". So the first chunk would have (0, 0) the second on the x axis would have (1, 0). The last chunk would be (4,4)

Now you could split the problem into smaller pieces but the easiest way is to simply iterate through your target array and work out the 4 required source coordinates.

 // chunk coordinate
 int cx;
 int cy;
 
 // this is the offset of this chunk inside the source image
 Vector2 offset = new Vector2(cx * Up, cy * Up);
 
 for(int y = 0; y < chunkSize; y++)
 {
     for(int x = 0; x < chunkSize; x++)
     {
         // "p" is the exact point inside the source image including fraction
         var p = offset + new Vector2(x,y) / Up;
         // get the bottom left and upper right corners
         int x0 = Mathf.FloorToInt(p.x);
         int y0 = Mathf.FloorToInt(p.y);
         int x1 = (x0 >= originalHeight - 1)?0:x0 + 1;
         int y1 = (y0 >= originalHeight - 1)?0:y0 + 1;
         var t = p - new Vector2(x0, y0); // extract the fractional part
         float r0 = Mathf.Lerp(heights[x0, y0], heights[x1, y0], t.x);
         float r1 = Mathf.Lerp(heights[x0, y1], heights[x1, y1], t.x);
         newHeights[x,y] = Mathf.Lerp(r0, r1, t.y);
     }
 }

Note: I've written this from scratch without testing or syntax checking, so use at your own risk ^^.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image b1gry4n · Oct 02, 2016 at 04:54 AM 0
Share

I upvoted because while this isnt exactly what I was going for (i do things really weird after this step so i need it a specific way) it gave me the idea of dividing the original input, retrieving the fraction and rounding it up. It needs to be rounded up since the returned value could be a float, i need the "pixels between the pixels" that havent been created yet. That way I can plug in an array of values Ive collected from the "originalinput" and get an upresd version

I will post a solution...if it works, when i get it up and running

avatar image b1gry4n b1gry4n · Oct 02, 2016 at 07:39 AM 0
Share

Just wanted to clarify why I ignore the top right. The way I am setting up my tiles, that top right value ends up being the value for the tile that sits to the current tiles top right. it isnt ignored, it just belongs to a different tile in the grid. tiles that reach the end of the grid look to the tiles at the "looped" side. every edge is calculated/used

After this process each tile sets its top and right edge heights to match the heights of its top and right neighbor. Another pass is done for all 4 tiles that share a common corner height, the value is averaged and set to those tiles.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

59 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How to Instantiate from mouse pos? 0 Answers

Relative Position Not Constant? 0 Answers

How do I make unity generate a random equation and an answer to to it (also making it show on the screen?) 0 Answers

Calculating laser energy 1 Answer

2D kinematics 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges