Giter VIP home page Giter VIP logo

mm1-map-editor's Introduction

Midtown Madness Map Editor

Preview

Download Latest Version Chat On Discord

Midtown Madness is a racing game made by Angel Studios, featuring the city of Chicago.

This Map Editor is developed to provide an easy way for users to create their own unique cities for Midtown Madness 1. Not only can you design roads, hills, and walls, you may also customize textures, facades, props, drawbridges, animations, lighting, physics, AI paths, races, and even the HUD.

In addition, the Editor seamlessly integrates with the 3D modelling software Blender. This enables quick importing & exporting of models. To further enhance the user experience, a custom Blender UI has been implemented. From here, all parameters of each polygon can be set and modified.
This visual integration, combined with Blender's extensive features, significantly streamlines the design process, enabling swift tweaks and iterations.

Upon completion of your design, the Map Editor will generate all the necessary city files, compile them into an .AR file, and automatically boot the game with the new city preloaded.

Installation

  • Click the Download button or clone the repo:
git clone https://github.com/KcRobin9/MM1-Map-Editor.git

Contributions

Contributions are welcomed. All questions, feature requests, issues, and pull requests will be reviewed.

Credits

  • 0x1F9F1 - Instrumental help, including Open1560 features and coding Q & A
  • Dading - Alpha tester, creator of Moronville
  • Vwp914 - Alpha tester, Blender tutor
  • Lars - For his Race Making Tool
  • DDucky - Code help with Prop Editor
  • fatiyesman - Alpha tester, Contributer

Gallery

Preview

Preview

Preview

Preview

Preview

Preview

mm1-map-editor's People

Contributors

fatiyesman avatar kcrobin9 avatar sharkwouter avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

mm1-map-editor's Issues

Share Vertex Indices Across Multiple Polygons

Currently, every vertex within a polygon is assigned a unique index. However, the game engine supports sharing vertex indices across multiple polygons. This is beneficial because in the current binary format, there are "only" 65.535 indices available (i.e. 16.383 quads / 21.845 triangles).

By enabling this feature, more polygons can be constructed, enhancing the design process of very large and complex maps.

Example (data extracted from an original bound file)

Polygon
Bound Number: 0
Flags: 4
Vertices Indices: (6, 4, 5, 7)
Vertices Coordinates: [{-1.01,1.34,-2.07}, {-1.01,0.33,-2.07}, {-1.01,0.33,2.11}, {-1.01,1.34,1.49}]
Plane Edges: [{0.00,1.00,-2.07}, {1.00,-0.00,0.33}, {-0.53,-0.85,-1.97}, {-1.00,-0.00,-1.34}]
Plane N: {-1.00,0.00,0.00}
Plane D: [-1.01]

Polygon
Bound Number: 1
Flags: 6
Vertices Indices: (4, 0, 1, 5)
Vertices Coordinates: [{-1.01,0.33,-2.07}, {1.01,0.33,-2.07}, {1.01,0.33,2.11}, {-1.01,0.33,2.11}]
Plane Edges: [{-0.00,1.00,-2.07}, {-1.00,0.00,-1.01}, {-0.00,-1.00,-2.11}, {1.00,0.00,-1.01}]
Plane N: {0.00,-1.00,0.00}
Plane D: [0.33]

Investigate DDS File Exporting

The game uses DDS files for textures.

It would be nice to have a function that can automatically convert multiple JPGs into a DDS format that Midtown Madness supports (including images that should be transparent).

The libraries PIL and imageio may come in handy for this.

Utilize Vector Classes over Numpy Library

The Editor currently uses the numpy library for vector operations in several geometric calculations, such as computing normals. While numpy is powerful, the custom Vector2 and Vector3 classes provide tailored methods that could enhance performance and reduce external dependencies.

For instance:

def compute_normal(vertex_1: Vector3, vertex_2: Vector3, vertex_3: Vector3) -> np.ndarray:
    v1 = np.array(vertex_2) - np.array(vertex_1)
    v2 = np.array(vertex_3) - np.array(vertex_1)
    normal = np.cross(v1, v2)
    return normal / np.linalg.norm(normal)

Could be refactored into:

def compute_normal(vertex_1: Vector3, vertex_2: Vector3, vertex_3: Vector3) -> Vector3:
    v1 = vertex_2 - vertex_1
    v2 = vertex_3 - vertex_1
    normal = v1.Cross(v2)
    return normal.Normalize()

Improve Installation Instructions

While the README in the Setup folder is sound, it can be improved further by using markdown instead of a txt file.

Also, there are some edge cases in the installation process that should be documented.

Split Map Editor Python Files

For better readability and maintainability, some parts of the script should be split (e.g. class constants, or Blender related operators/panels). This will be a continuous WIP for the future.

Create a Wiki

The Wiki will include more background info about the Editor, as well as the older tools used for Map making.

Refactor Facade Integer Values to Bit Flags

Current Facade settings use distinct integer values for each condition, leading to potential overlap and confusion.

Converting the integer values to bitwise flags did not give the expected outcome/values, hence a review is needed.

Facade_Flags

Fix Duplicate Opponent Car Selection Issue in Race Configuration

In the current race configuration setup, when the same opponent car is selected multiple times for a specific race, only the last entry is processed. For example, if three Panoz GTR-1's are selected CIRCUIT 1, in-game, there will only be one GTR-1 appearing in the first circuit race. This issue stems from the way Python's dictionaries handle key-value pairs.

This should be fixed.

Race_Config_Issue

New Mesh Rotation Wrong During Script Compile.

When adding a fresh polygon from blender, that isn't already in the standard example map included in the script, the rotations dont match the values that midtown madness has, causing them to rotate incorrectly when compiling a level with new polygons, based on blenders' coordinate values, and not midtown madness'.

Implement Double-Sided Polygons

Currently, when a polygon is set, it only works for one side / face.

The side is determined by the order and winding of the coordinates.

Setting double-sided polygons can be especially useful when users set vertical walls, such that both sides will have collision and textures.

This feature can be added as a parameter double_sided = True in the function create_polygon()

Implement mmPlayerData Class

Reading and Writing the player's datafile (.sav) will enable users to customize their player profile.

This includes for example the PlayerName, LastCarPicked, LastRacePicked, among other variables.

In file are also records for individual races written, e.g. Dearborn Dash | 19.47 | Fati | Panoz GTR-1

mmPlayerData

Increase Cells File Charachter Limit

This issue relates to issue Imperfect Generation of the Portals File.

For the game to properly render the cells, it primarily relies on a well constructed portal file.
In edge cases however, a .CELLS file is used to ensure certain cells are visible from other cells.

The contents of a .CELLS file are as follows:
Cell ID, buffer, flag, visit_count, visible_cells

36,462,0,0
37,462,0,0
39,462,0,3,37,239,8

Where in the example above, the game ensures that from cell 39, three additional cells will be rendered, with the cell index: 37, 239, 8.

The Map Editor relies on this method quite extensively, that is, generate a portal file as best as possible, and then make sure all cells are visible from each cell (users can make exceptions on this, always_visible: bool = False in create_polygon()).

Concretely, a line in the .CELLS file of a custom map may look like this:
1,8,64,38,99,201,861,202,1,862,203,2,863,204,205,...,...,...

Where 99 additional cells are visible from cell index 1 (the data line has been truncated for example purposes).

This method works well in practice, however the game's engine only reads the first 254 characters in each row.
This means that as the number of polygons (= cells) increases, the number of characters in each row will surpass the limit CELL_CHARACTER_LIMIT = 254, and subsequently crash the game.

To avoid this problem, the reading limit must be increased, likely involving reverse engineering functions in the Open1560 project.

Doing so will greatly expand the Map making capabilities. The geometry of e.g. Yoshi Falls from Mario Kart Wii has already been successfully imported in Midtown Madness, however, due to the visibility problem described above, the player only sees a fraction of the available polygon/cells, making the map unplayable. Only in the geometry-view (see below), the full map is visible.

Yoshi Falls

Yoshi_Falls

Implement a Collision Table Generator

Approximately the second half of the {map_name}_HITID.BND file consists of lookup tables.
These tables are crucial for optimizing collision performance by quickly determining the room/cell an object is located in.

Reverse engineering the table generator is challenging. The game engine generates these tables through a series of function calls as outlined below:

mmCullCity::Init --> asRenderWeb::Load --> mmBoundTemplate::GetBoundTemplate -->

mmBoundTemplate::Load      
(if (x_dim && y_dim && z_dim))

	mmBoundTemplate::MakeTable
		
		mmBoundTemplate::DoMakeTable 	

			mmPolygon::Plot
			
					mmPolygon::PlotTriangle
							
							Vector3::Swap
							swapf
							
							mmPolygon::PlotScan 
							
									j_clamp
									mmBoundTemplate::AddIndex

			mmPolygon::MaxY
			
					mmPolygon::CornersHeight
					
							sqrtf_fast_0
							mmPolygon::CheckCorner
							
					mmPolygon::CheckCellXSide
                    
					mmPolygon::CheckCellZSide

For more context, see the pictures below.

Chicago without a collision table:

Chicago_No_Table

Chicago_No_Table_Perf

Chicago with a collision table:

Chicago_With_Table

Visual representation of the collision table in-game:

Grid_Example_1

Grid_Example_2

Implement a Breakable Prop Editor

When a player collides with a prop, the prop can "break" into multiple other (sub) props.

With the proper configuration, it should be possible to break a small bench into multiple huge trucks.

More info on this feature later.

Reorganize Blender Shortcuts

Over time, several custom Blender Shortcuts were added to the Map Editor.

While all of them are functional, some keybindings may conflict with other (important) Blender operations (e.g., Shift + R or Ctrl + E).

In general, all keybindings should be reviewed, and during that process, they should also be grouped more logically.

Blender_Shortcuts

Replace Mathutils Vector with Custom Vector3 Class

The Blender Waypoint Functions have been designed with Vector from Mathutils, but this library is notoriously difficult to install outside Blender. So use existing Vector3 functions or implement new ones to replace the current Mathutils Vector present in the functions.

Bridge Attributes Are Not Breakable

Normally, when hitting a bridge crossgate, the crossgate will split/break/fall into multiple smaller pieces

However, in custom maps (so far), the crossgate doesn't break when an object "collides" with it

No previous custom maps featured custom bridges, making it unclear whether the inconsistency originates from an incorrect bridge file or if custom maps inherently have limitations in some way

While the issue is relatively minor, it would be nice to have it solved in the future

Below are a few pictures below for more info / context

Bridge_No_Break_1

Bridge_No_Break_2

Bridge_Yes_Break

Collision and Computational Issues with Coplanar Vertices in Vertical Polygons

Coplanar vertices in perfectly vertical polygons are currently causing computational and collision detection issues (see e.g. polygon with bound number = 5).

NaN Outputs for Perfectly Vertical Polygons

POLYGON
    Bound Number: 5
    Vertices Indices: [50, 51, 52, 53]
    Vertices Coordinates: [{ -10.00, 0.00, -70.00 }, { -10.00, 30.00, -70.00 }, { 10.00, 30.00, -70.00 }, { 10.00, 0.00, -70.00 }]
    Plane Edges: [{ nan, nan, nan }, { nan, nan, nan }, { nan, nan, nan }, { nan, nan, nan }]
    Plane N: { 0.00, 0.00, -1.00 }
    Plane D: -70.0

Infinite Collision Height with Minor Z-Axis Deviation

POLYGON
    Bound Number: 5
    Vertices Indices: [50, 51, 52, 53]
    Vertices Coordinates: [{ -10.00, 0.00, -70.00 }, { -10.00, 30.00, -69.99 }, { 10.00, 30.00, -69.99 }, { 10.00, 0.00, -70.00 }]
    Plane Edges: [{ 1.00, -0.00, -10.00 }, { 0.00, -1.00, 69.99 }, { -1.00, -0.00, -10.00 }, { 0.00, 1.00, -70.00 }]
    Plane N: { 0.00, 0.00, -1.00 }
    Plane D: -70.0

Accurate Collision Detection with Larger Z-Axis Deviation:

POLYGON
    Bound Number: 5
    Vertices Indices: [50, 51, 52, 53]
    Vertices Coordinates: [{ -10.00, 0.00, -70.00 }, { -10.00, 30.00, -69.80 }, { 10.00, 30.00, -69.80 }, { 10.00, 0.00, -70.00 }]
    Plane Edges: [{ 1.00, -0.00, -10.00 }, { 0.00, -1.00, 69.80 }, { -1.00, -0.00, -10.00 }, { 0.00, 1.00, -70.00 }]
    Plane N: { 0.00, 0.01, -1.00 }
    Plane D: -69.998

Ideally, the user should be able to set coplanar vertices as this is more convenient in both Blender and in the editor. However, currently, this is not possible due to the issues mentioned above. Moreover, the offset is not arbitrary, adding either 0.2 or -0.2 will change the collision face. This issue requires additional investigation.

Implement a Blender Car Editor

Since the game utilizes the same custom file formats (.BND and .BMS) for cities as for cars, extending the Editor's capabilities to include a workflow for designing and exporting drivable cars should be feasible.

Meticulous attention to detail should be applied in designing the Blender UI to ensure it is as intuitive and user-friendly as possible.

More information on this feature will be added as it is implemented step by step.

Implement mmPlayerConfig Class

Similar to the issue of Implement mmPlayerData Class, implementing the mmPlayerConfig class enables users to customize their player configuration.

Especially setting the Audio volumes can be quite handy, as they're very loud by default. Additionally, setting the PhysicsRealism and MouseSensitivity is often preferred by players.

The picture below depicts the main portion of the config variables.

mmPlayerConfig

Implement Per-Race Traffic Path Exceptions

The Editor's race_data dictionary has already successfully integrated most of the fields from the game's AIMAP files. However, as ambient traffic is likely to become more commonplace in maps, users should also be able to set traffic path exceptions.

These exceptions, listing the path ID, density, and speed limit, will help users further customize their races.
Below is an example of how the AIMAP file looks:

# Ambient Traffic Exceptions
# Rd Id, Density, Speed Limit
[Exceptions]
7
648 0.0 45
646 1.0 60
644 0.3 45
647 0.3 45
152 0.0 45
153 0.0 45

Improve Road Generation

It would be great if there was a road generator which creates sidewalks, light poles, trees and other stuff with the road we are creating.

image

Incorrect Debugging Portals Data

The output that is obtained when debugging portals is incorrect.

Currently, we get this:

(7, 861, 10.00, -70.00, 9.90, -70.00)(2223, 2224, -156.59, -204.88, -191.82, -223.82)(203, 863, 93.01, 70.00, 140.00, 70.00) ... 

While we should get something like this:

PORTAL
    Flags: 2
    EdgeCount: 2
    Gap 2: 101
    Cell 1: 22
    Cell 2: 23
    Height: 50
    Min: (10, 0, 30)
    Max: (10, 0, 60)
	
...
...

This should be fixed.

Blender Vertex Panel Doesn't Update Coordinates After Manual Vertex Adjustment

When polygon data is imported, the custom Vertex Panel correctly displays the coordinates of a selected polygon's vertices. In addition, when a coordinate is changed in the panel, the polygon's shape updates accordingly (see picture one). However, there is an issue where the Vertex Panel does not update its values when a vertex is manually manipulated (e.g. via vertex snapping), as shown in picture two.

The coordinates in the Vertex Panel should reflect the polygon's shape consistently, regardless of the method used for manipulating vertices. This issue requires further investigation.

Vertex_Panel_Pic1

Vertex_Panel_Pic2

Upgrade Blender Waypoint Texture

Currently, when importing waypoints into Blender, the flag is simply blue (1).

It would be nicer to apply the game's checkpoint texture to the flag instead. However, the original texture is of low resolution, and the text on the right side is vertically flipped (2). Additionally, to precisely match the game, the last waypoint for Blitzes and Races should have the 'Finish' texture. For Circuits, the first waypoint should have the 'Finish' texture applied to the flag.

(1)
Waypoint_Texture

(2)
Waypoint_Game

Imperfect Generation of the Portals File

Currently, a portals file is generated based on the polygon vertices used in the HIT_ID bound file. Portals are important for visibility of the map, among other things (e.g. the AI).

Issue one is that the height is disregarded during the construction of the portals (i.e. it is being set to y = 0).

The second issue is that the portal lines do not follow the curvature of the road in the current design process.
Typically, when modeling a road, a base quad is selected, and then extruded multiple times. For curved roads (as shown in the picture), triangulation is necessary to ensure correct collision generation. The picture clearly shows that the portal lines follow the shapes, and not the road's curvature (which is the intended behavior).

This issue needs to be further investigated.

Portal_Issue

Implement Original BND Design: Split `_HITID.BND` Into Separate Bound Files

Currently, bound polygons for all areas are consolidated into a single {map_name}_HITID.BND file.

This implementation differs from the original design, where spatial data was more granularly managed:

  1. A primary reference polygon (or polygons) for each specific area / cell (e.g. cell 201) is defined.
  2. Detailed polygons for these areas are stored in dedicated bound files (e.g., BOUND201.BND).
  3. The {map_name}_HITID.BND file serves primarily as an index, directing the game to load detailed data from the appropriate BOUND file. Should a detailed file be missing, the game defaults to the (minimal) polygon data in _HITID.BND.

See the pictures below for more context.

HITID Polygons:

RACECITY_HIT_ID

Separate Polygons:

RACECITY_SEP_BOUND

Implement a Skeleton Editor

The pedestrian skeleton files .SKEL are text-based and not written in binary

Hence, it should be relatively straightforward to customize the skeleton of different pedestrians and integrate them into the Map Editor

Below are a few pictures below for more info / context

Skel_Code

Skel_1

Skel_2

Skel_3

Skel_4

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.